mirror of
https://github.com/samba-team/samba.git
synced 2025-02-02 09:47:23 +03:00
tdb: put example hashes into header, so we notice incorrect hash_fn.
This is Stefan Metzmacher <metze@samba.org>'s patch with minor changes: 1) Use the TDB_MAGIC constant so both hashes aren't of strings. 2) Check the hash in tdb_check (paranoia, really). 3) Additional check in the (unlikely!) case where both examples hash to 0. 4) Cosmetic changes to var names and complaint message. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
f77708e962
commit
786b726300
@ -28,6 +28,7 @@
|
||||
static bool tdb_check_header(struct tdb_context *tdb, tdb_off_t *recovery)
|
||||
{
|
||||
struct tdb_header hdr;
|
||||
uint32_t h1, h2;
|
||||
|
||||
if (tdb->methods->tdb_read(tdb, 0, &hdr, sizeof(hdr), 0) == -1)
|
||||
return false;
|
||||
@ -41,6 +42,11 @@ static bool tdb_check_header(struct tdb_context *tdb, tdb_off_t *recovery)
|
||||
if (hdr.rwlocks != 0)
|
||||
goto corrupt;
|
||||
|
||||
tdb_header_hash(tdb, &h1, &h2);
|
||||
if (hdr.magic1_hash && hdr.magic2_hash &&
|
||||
(hdr.magic1_hash != h1 || hdr.magic2_hash != h2))
|
||||
goto corrupt;
|
||||
|
||||
if (hdr.hash_size == 0)
|
||||
goto corrupt;
|
||||
|
||||
|
@ -44,6 +44,25 @@ static unsigned int default_tdb_hash(TDB_DATA *key)
|
||||
return (1103515243 * value + 12345);
|
||||
}
|
||||
|
||||
/* We use two hashes to double-check they're using the right hash function. */
|
||||
void tdb_header_hash(struct tdb_context *tdb,
|
||||
uint32_t *magic1_hash, uint32_t *magic2_hash)
|
||||
{
|
||||
TDB_DATA hash_key;
|
||||
uint32_t tdb_magic = TDB_MAGIC;
|
||||
|
||||
hash_key.dptr = (unsigned char *)TDB_MAGIC_FOOD;
|
||||
hash_key.dsize = sizeof(TDB_MAGIC_FOOD);
|
||||
*magic1_hash = tdb->hash_fn(&hash_key);
|
||||
|
||||
hash_key.dptr = CONVERT(tdb_magic);
|
||||
hash_key.dsize = sizeof(tdb_magic);
|
||||
*magic2_hash = tdb->hash_fn(&hash_key);
|
||||
|
||||
/* Make sure at least one hash is non-zero! */
|
||||
if (*magic1_hash == 0 && *magic2_hash == 0)
|
||||
*magic1_hash = 1;
|
||||
}
|
||||
|
||||
/* initialise a new database with a specified hash size */
|
||||
static int tdb_new_database(struct tdb_context *tdb, int hash_size)
|
||||
@ -62,6 +81,9 @@ static int tdb_new_database(struct tdb_context *tdb, int hash_size)
|
||||
/* Fill in the header */
|
||||
newdb->version = TDB_VERSION;
|
||||
newdb->hash_size = hash_size;
|
||||
|
||||
tdb_header_hash(tdb, &newdb->magic1_hash, &newdb->magic2_hash);
|
||||
|
||||
if (tdb->flags & TDB_INTERNAL) {
|
||||
tdb->map_size = size;
|
||||
tdb->map_ptr = (char *)newdb;
|
||||
@ -140,6 +162,9 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
|
||||
unsigned char *vp;
|
||||
uint32_t vertest;
|
||||
unsigned v;
|
||||
uint32_t magic1_hash;
|
||||
uint32_t magic2_hash;
|
||||
const char *hash_alg;
|
||||
|
||||
if (!(tdb = (struct tdb_context *)calloc(1, sizeof *tdb))) {
|
||||
/* Can't log this */
|
||||
@ -161,7 +186,14 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
|
||||
tdb->log.log_fn = null_log_fn;
|
||||
tdb->log.log_private = NULL;
|
||||
}
|
||||
tdb->hash_fn = hash_fn ? hash_fn : default_tdb_hash;
|
||||
|
||||
if (hash_fn) {
|
||||
tdb->hash_fn = hash_fn;
|
||||
hash_alg = "user defined";
|
||||
} else {
|
||||
tdb->hash_fn = default_tdb_hash;
|
||||
hash_alg = "default";
|
||||
}
|
||||
|
||||
/* cache the page size */
|
||||
tdb->page_size = getpagesize();
|
||||
@ -279,6 +311,27 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
tdb_header_hash(tdb, &magic1_hash, &magic2_hash);
|
||||
|
||||
if ((tdb->header.magic1_hash == 0) && (tdb->header.magic2_hash == 0)) {
|
||||
/* older TDB without magic hash references */
|
||||
} else if ((tdb->header.magic1_hash != magic1_hash) ||
|
||||
(tdb->header.magic2_hash != magic2_hash)) {
|
||||
TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: "
|
||||
"%s was not created with the %s hash function we are using\n"
|
||||
"magic1_hash[0x%08X %s 0x%08X] "
|
||||
"magic2_hash[0x%08X %s 0x%08X]\n",
|
||||
name, hash_alg,
|
||||
tdb->header.magic1_hash,
|
||||
(tdb->header.magic1_hash == magic1_hash) ? "==" : "!=",
|
||||
magic1_hash,
|
||||
tdb->header.magic2_hash,
|
||||
(tdb->header.magic2_hash == magic2_hash) ? "==" : "!=",
|
||||
magic2_hash));
|
||||
errno = EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Is it already in the open list? If so, fail. */
|
||||
if (tdb_already_open(st.st_dev, st.st_ino)) {
|
||||
TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: "
|
||||
|
@ -147,7 +147,9 @@ struct tdb_header {
|
||||
tdb_off_t rwlocks; /* obsolete - kept to detect old formats */
|
||||
tdb_off_t recovery_start; /* offset of transaction recovery region */
|
||||
tdb_off_t sequence_number; /* used when TDB_SEQNUM is set */
|
||||
tdb_off_t reserved[29];
|
||||
uint32_t magic1_hash; /* hash of TDB_MAGIC_FOOD. */
|
||||
uint32_t magic2_hash; /* hash of TDB_MAGIC. */
|
||||
tdb_off_t reserved[27];
|
||||
};
|
||||
|
||||
struct tdb_lock_type {
|
||||
@ -268,3 +270,5 @@ int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off,
|
||||
struct tdb_record *rec);
|
||||
bool tdb_write_all(int fd, const void *buf, size_t count);
|
||||
int tdb_transaction_recover(struct tdb_context *tdb);
|
||||
void tdb_header_hash(struct tdb_context *tdb,
|
||||
uint32_t *magic1_hash, uint32_t *magic2_hash);
|
||||
|
Loading…
x
Reference in New Issue
Block a user