1
0
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:
Rusty Russell 2010-09-13 20:05:59 +09:30
parent f77708e962
commit 786b726300
3 changed files with 65 additions and 2 deletions

View File

@ -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;

View File

@ -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: "

View File

@ -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);