diff options
author | Aaron Haslett <aaronhaslett@catalyst.net.nz> | 2019-05-10 18:10:51 +1200 |
---|---|---|
committer | Karolin Seeger <kseeger@samba.org> | 2019-08-28 07:36:29 +0000 |
commit | 388cb30bd7d70301fe1fd9dbecd1a1921955dc5b (patch) | |
tree | b0c9abf87d0764e5aa0a3fc48268bc292409f6a3 | |
parent | 3cb3b34def330b57b008a02c027d8ea658ae487c (diff) | |
download | samba-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.c | 23 | ||||
-rw-r--r-- | lib/ldb/include/ldb_module.h | 9 | ||||
-rw-r--r-- | lib/ldb/ldb_tdb/ldb_cache.c | 45 | ||||
-rw-r--r-- | lib/ldb/ldb_tdb/ldb_tdb.c | 2 | ||||
-rw-r--r-- | lib/ldb/ldb_tdb/ldb_tdb.h | 1 |
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, <db_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 */ |