summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Haslett <aaronhaslett@catalyst.net.nz>2019-05-10 18:10:51 +1200
committerAndrew Bartlett <abartlet@samba.org>2019-05-22 04:42:28 +0000
commit474e55523224430781ed22aa2d0c8a474306e794 (patch)
tree3903ab71c535f701bf7e493cc1c9a28a4b1d6fc6
parent3e6661fd73bb24ef5700a98f676f1df5eeca408b (diff)
downloadsamba-474e55523224430781ed22aa2d0c8a474306e794.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. Signed-off-by: Aaron Haslett <aaronhaslett@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abartlet@samba.org> Reviewed-by: Gary Lockyer <gary@catalyst.net.nz>
-rw-r--r--lib/ldb/common/ldb_pack.c23
-rw-r--r--lib/ldb/include/ldb_module.h9
-rw-r--r--lib/ldb/ldb_key_value/ldb_kv.c2
-rw-r--r--lib/ldb/ldb_key_value/ldb_kv.h1
-rw-r--r--lib/ldb/ldb_key_value/ldb_kv_cache.c37
5 files changed, 64 insertions, 8 deletions
diff --git a/lib/ldb/common/ldb_pack.c b/lib/ldb/common/ldb_pack.c
index 5360a36cccc..e59c542fc5b 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)
{
@@ -195,7 +189,7 @@ int ldb_unpack_data_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;
struct ldb_val *ldb_val_single_array = NULL;
@@ -208,7 +202,10 @@ int ldb_unpack_data_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;
@@ -402,6 +399,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 759a54a3169..d9114e99e34 100644
--- a/lib/ldb/include/ldb_module.h
+++ b/lib/ldb/include/ldb_module.h
@@ -544,12 +544,21 @@ int ldb_unpack_data_flags(struct ldb_context *ldb,
struct ldb_message *message,
unsigned int flags);
+int ldb_unpack_get_format(const struct ldb_val *data,
+ uint32_t *pack_format_version);
+
/* currently unused (was 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
#define LDB_UNPACK_DATA_FLAG_READ_LOCKED 0x0010
+/* 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_key_value/ldb_kv.c b/lib/ldb/ldb_key_value/ldb_kv.c
index 53c326d36b2..81a77462c83 100644
--- a/lib/ldb/ldb_key_value/ldb_kv.c
+++ b/lib/ldb/ldb_key_value/ldb_kv.c
@@ -1894,6 +1894,8 @@ int ldb_kv_init_store(struct ldb_kv_private *ldb_kv,
ldb_kv->sequence_number = 0;
+ ldb_kv->pack_format_version = LDB_PACKING_FORMAT;
+
ldb_kv->pid = getpid();
ldb_kv->module = ldb_module_new(ldb, ldb, name, &ldb_kv_ops);
diff --git a/lib/ldb/ldb_key_value/ldb_kv.h b/lib/ldb/ldb_key_value/ldb_kv.h
index 97bdcf09875..c9e55321d0d 100644
--- a/lib/ldb/ldb_key_value/ldb_kv.h
+++ b/lib/ldb/ldb_key_value/ldb_kv.h
@@ -63,6 +63,7 @@ struct ldb_kv_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 */
diff --git a/lib/ldb/ldb_key_value/ldb_kv_cache.c b/lib/ldb/ldb_key_value/ldb_kv_cache.c
index b14697c2a5e..c5f661113fd 100644
--- a/lib/ldb/ldb_key_value/ldb_kv_cache.c
+++ b/lib/ldb/ldb_key_value/ldb_kv_cache.c
@@ -395,6 +395,13 @@ int ldb_kv_cache_reload(struct ldb_module *module)
ldb_kv_cache_free(module);
return ldb_kv_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
@@ -411,6 +418,8 @@ int ldb_kv_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 = ldb_module_get_ctx(module);
@@ -435,6 +444,34 @@ int ldb_kv_cache_load(struct ldb_module *module)
if (r != LDB_SUCCESS) {
goto failed;
}
+
+ key = ldb_kv_key_dn(module, baseinfo, baseinfo_dn);
+ if (!key.data) {
+ goto failed_and_unlock;
+ }
+
+ /* Read packing format from first 4 bytes of @BASEINFO record */
+ r = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key,
+ 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 != ldb_kv->pack_format_version) {
+ ldb_debug(ldb, LDB_DEBUG_ERROR,
+ "Unexpected packing format. "
+ "Expected: %#010x, Got: %#010x",
+ pack_format_version,
+ ldb_kv->pack_format_version);
+ goto failed_and_unlock;
+ }
+ }
+
+ /* Now fetch the whole @BASEINFO record */
r = ldb_kv_search_dn1(module, baseinfo_dn, baseinfo, 0);
if (r != LDB_SUCCESS && r != LDB_ERR_NO_SUCH_OBJECT) {
goto failed_and_unlock;