summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Haslett <aaronhaslett@catalyst.net.nz>2019-05-10 18:10:51 +1200
committerKarolin Seeger <kseeger@samba.org>2019-08-28 07:36:29 +0000
commit388cb30bd7d70301fe1fd9dbecd1a1921955dc5b (patch)
treeb0c9abf87d0764e5aa0a3fc48268bc292409f6a3
parent3cb3b34def330b57b008a02c027d8ea658ae487c (diff)
downloadsamba-388cb30bd7d70301fe1fd9dbecd1a1921955dc5b.tar.gz
ldb: baseinfo pack format check on init
We will be adding a new packing format in forthcoming commits and there may be more versions in the future. We need to make sure the database contains records in a format we know how to read and write. Done by fetching the @BASEINFO record and reading the first 4 bytes which contain the packing format version. NOTE: Configure with --abi-check-disable to build this commit. This patch is part of a set of LDB ABI changes, and the version update is done on the last commit. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13977 Signed-off-by: Aaron Haslett <aaronhaslett@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abartlet@samba.org> Reviewed-by: Gary Lockyer <gary@catalyst.net.nz> (backported from commit 474e55523224430781ed22aa2d0c8a474306e794)
-rw-r--r--lib/ldb/common/ldb_pack.c23
-rw-r--r--lib/ldb/include/ldb_module.h9
-rw-r--r--lib/ldb/ldb_tdb/ldb_cache.c45
-rw-r--r--lib/ldb/ldb_tdb/ldb_tdb.c2
-rw-r--r--lib/ldb/ldb_tdb/ldb_tdb.h1
5 files changed, 71 insertions, 9 deletions
diff --git a/lib/ldb/common/ldb_pack.c b/lib/ldb/common/ldb_pack.c
index 448c577ae1b..286803f0b41 100644
--- a/lib/ldb/common/ldb_pack.c
+++ b/lib/ldb/common/ldb_pack.c
@@ -33,12 +33,6 @@
#include "ldb_private.h"
-/* change this if the data format ever changes */
-#define LDB_PACKING_FORMAT 0x26011967
-
-/* old packing formats */
-#define LDB_PACKING_FORMAT_NODN 0x26011966
-
/* use a portable integer format */
static void put_uint32(uint8_t *p, int ofs, unsigned int val)
{
@@ -229,7 +223,7 @@ int ldb_unpack_data_only_attr_list_flags(struct ldb_context *ldb,
size_t remaining;
size_t dn_len;
unsigned int i, j;
- unsigned format;
+ uint32_t format;
unsigned int nelem = 0;
size_t len;
unsigned int found = 0;
@@ -247,7 +241,10 @@ int ldb_unpack_data_only_attr_list_flags(struct ldb_context *ldb,
goto failed;
}
- format = pull_uint32(p, 0);
+ if (ldb_unpack_get_format(data, &format) != LDB_SUCCESS) {
+ errno = EIO;
+ goto failed;
+ }
message->num_elements = pull_uint32(p, 4);
p += 8;
if (nb_elements_in_db) {
@@ -504,6 +501,16 @@ failed:
return -1;
}
+int ldb_unpack_get_format(const struct ldb_val *data,
+ uint32_t *pack_format_version)
+{
+ if (data->length < 4) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ *pack_format_version = pull_uint32(data->data, 0);
+ return LDB_SUCCESS;
+}
+
/*
* Unpack a ldb message from a linear buffer in ldb_val
*
diff --git a/lib/ldb/include/ldb_module.h b/lib/ldb/include/ldb_module.h
index c73fc37f3aa..8c47082690b 100644
--- a/lib/ldb/include/ldb_module.h
+++ b/lib/ldb/include/ldb_module.h
@@ -561,11 +561,20 @@ int ldb_unpack_data_only_attr_list_flags(struct ldb_context *ldb,
unsigned int flags,
unsigned int *nb_elements_in_db);
+int ldb_unpack_get_format(const struct ldb_val *data,
+ uint32_t *pack_format_version);
+
#define LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC 0x0001
#define LDB_UNPACK_DATA_FLAG_NO_DN 0x0002
#define LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC 0x0004
#define LDB_UNPACK_DATA_FLAG_NO_ATTRS 0x0008
+/* In-use packing formats */
+#define LDB_PACKING_FORMAT 0x26011967
+
+/* Old packing formats */
+#define LDB_PACKING_FORMAT_NODN 0x26011966
+
/**
Forces a specific ldb handle to use the global event context.
diff --git a/lib/ldb/ldb_tdb/ldb_cache.c b/lib/ldb/ldb_tdb/ldb_cache.c
index 1856fb13877..eb14a74e0a1 100644
--- a/lib/ldb/ldb_tdb/ldb_cache.c
+++ b/lib/ldb/ldb_tdb/ldb_cache.c
@@ -387,6 +387,13 @@ int ltdb_cache_reload(struct ldb_module *module)
ltdb_cache_free(module);
return ltdb_cache_load(module);
}
+static int get_pack_format_version(struct ldb_val key,
+ struct ldb_val data,
+ void *private_data)
+{
+ uint32_t *v = (uint32_t *) private_data;
+ return ldb_unpack_get_format(&data, v);
+}
/*
load the cache records
@@ -402,6 +409,9 @@ int ltdb_cache_load(struct ldb_module *module)
const struct ldb_schema_attribute *a;
bool have_write_txn = false;
int r;
+ uint32_t pack_format_version;
+ struct ldb_val key_ldb;
+ struct TDB_DATA key;
ldb = ldb_module_get_ctx(module);
@@ -425,7 +435,40 @@ int ltdb_cache_load(struct ldb_module *module)
if (r != LDB_SUCCESS) {
goto failed;
}
- r= ltdb_search_dn1(module, baseinfo_dn, baseinfo, 0);
+
+ key = ltdb_key_dn(module, baseinfo, baseinfo_dn);
+ if (!key.dptr) {
+ goto failed_and_unlock;
+ }
+
+ key_ldb = (struct ldb_val){
+ .data = key.dptr,
+ .length = key.dsize
+ };
+
+ /* Read packing format from first 4 bytes of @BASEINFO record */
+ r = ltdb->kv_ops->fetch_and_parse(ltdb, key_ldb,
+ get_pack_format_version,
+ &pack_format_version);
+
+ if (r != LDB_ERR_NO_SUCH_OBJECT) {
+ if (r != LDB_SUCCESS) {
+ goto failed_and_unlock;
+ }
+
+ /* Make sure the database has the right format */
+ if (pack_format_version != ltdb->pack_format_version) {
+ ldb_debug(ldb, LDB_DEBUG_ERROR,
+ "Unexpected packing format. "
+ "Expected: %#010x, Got: %#010x",
+ pack_format_version,
+ ltdb->pack_format_version);
+ goto failed_and_unlock;
+ }
+ }
+
+ /* Now fetch the whole @BASEINFO record */
+ r = ltdb_search_dn1(module, baseinfo_dn, baseinfo, 0);
if (r != LDB_SUCCESS && r != LDB_ERR_NO_SUCH_OBJECT) {
goto failed_and_unlock;
}
diff --git a/lib/ldb/ldb_tdb/ldb_tdb.c b/lib/ldb/ldb_tdb/ldb_tdb.c
index 337e7d2ee22..e3f552805c2 100644
--- a/lib/ldb/ldb_tdb/ldb_tdb.c
+++ b/lib/ldb/ldb_tdb/ldb_tdb.c
@@ -2272,6 +2272,8 @@ int init_store(struct ltdb_private *ltdb,
ltdb->sequence_number = 0;
+ ltdb->pack_format_version = LDB_PACKING_FORMAT;
+
ltdb->pid = getpid();
ltdb->module = ldb_module_new(ldb, ldb, name, &ltdb_ops);
diff --git a/lib/ldb/ldb_tdb/ldb_tdb.h b/lib/ldb/ldb_tdb/ldb_tdb.h
index 2896c6376b8..6c50e2856dc 100644
--- a/lib/ldb/ldb_tdb/ldb_tdb.h
+++ b/lib/ldb/ldb_tdb/ldb_tdb.h
@@ -42,6 +42,7 @@ struct ltdb_private {
unsigned int connect_flags;
unsigned long long sequence_number;
+ uint32_t pack_format_version;
/* the low level tdb seqnum - used to avoid loading BASEINFO when
possible */