1
0
mirror of https://github.com/samba-team/samba.git synced 2025-08-26 01:49:31 +03:00

dbwrap: Protect against invalid db_record->value

After dbwrap_record_storev()/delete(), dbwrap_record_get_value()
information is stale. Assert on the attempt to re-fetch data after it
became stale. This can't protect against someone copying the result
from dbwrap_record_get_value() somewhere else, but it's better than
nothing.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
This commit is contained in:
Volker Lendecke
2019-10-24 16:41:47 +02:00
committed by Jeremy Allison
parent 5291208836
commit 1dc3c16824
6 changed files with 25 additions and 0 deletions

View File

@ -79,6 +79,7 @@ TDB_DATA dbwrap_record_get_key(const struct db_record *rec)
TDB_DATA dbwrap_record_get_value(const struct db_record *rec)
{
SMB_ASSERT(rec->value_valid);
return rec->value;
}
@ -87,6 +88,12 @@ NTSTATUS dbwrap_record_storev(struct db_record *rec,
{
NTSTATUS status;
/*
* Invalidate before rec->storev() is called, give
* rec->storev() the chance to re-validate rec->value.
*/
rec->value_valid = false;
status = rec->storev(rec, dbufs, num_dbufs, flags);
if (!NT_STATUS_IS_OK(status)) {
return status;
@ -103,6 +110,12 @@ NTSTATUS dbwrap_record_delete(struct db_record *rec)
{
NTSTATUS status;
/*
* Invalidate before rec->delete_rec() is called, give
* rec->delete_rec() the chance to re-validate rec->value.
*/
rec->value_valid = false;
status = rec->delete_rec(rec);
if (!NT_STATUS_IS_OK(status)) {
return status;

View File

@ -29,6 +29,7 @@ struct tevent_req;
struct db_record {
struct db_context *db;
TDB_DATA key, value;
bool value_valid;
NTSTATUS (*storev)(struct db_record *rec, const TDB_DATA *dbufs,
int num_dbufs, int flag);
NTSTATUS (*delete_rec)(struct db_record *rec);

View File

@ -375,6 +375,7 @@ static struct db_record *db_rbt_fetch_locked(struct db_context *db_ctx,
rec_priv->node = res.node;
result->value = res.val;
result->value_valid = true;
if (found) {
result->key = res.key;
@ -447,6 +448,7 @@ static int db_rbt_traverse_internal(struct db_context *db,
rec.storev = db_rbt_storev;
rec.delete_rec = db_rbt_delete;
db_rbt_parse_node(rec_priv.node, &rec.key, &rec.value);
rec.value_valid = true;
if (rw) {
ctx->traverse_nextp = &next;

View File

@ -108,6 +108,7 @@ static int db_tdb_fetchlock_parse(TDB_DATA key, TDB_DATA data,
else {
result->value.dptr = NULL;
}
result->value_valid = true;
return 0;
}
@ -215,6 +216,7 @@ static NTSTATUS db_tdb_do_locked(struct db_context *db, TDB_DATA key,
.db = db, .key = key,
.value = (struct TDB_DATA) { .dptr = buf,
.dsize = talloc_get_size(buf) },
.value_valid = true,
.storev = db_tdb_storev, .delete_rec = db_tdb_delete,
.private_data = ctx
};
@ -344,6 +346,7 @@ static int db_tdb_traverse_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
rec.key = kbuf;
rec.value = dbuf;
rec.value_valid = true;
rec.storev = db_tdb_storev;
rec.delete_rec = db_tdb_delete;
rec.private_data = ctx->db->private_data;
@ -387,6 +390,7 @@ static int db_tdb_traverse_read_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA d
rec.key = kbuf;
rec.value = dbuf;
rec.value_valid = true;
rec.storev = db_tdb_storev_deny;
rec.delete_rec = db_tdb_delete_deny;
rec.private_data = ctx->db->private_data;

View File

@ -554,6 +554,7 @@ static struct db_record *db_ctdb_fetch_locked_transaction(struct db_ctdb_ctx *ct
DEBUG(0, ("talloc failed\n"));
TALLOC_FREE(result);
}
result->value_valid = true;
SAFE_FREE(ctdb_data.dptr);
@ -1246,6 +1247,7 @@ again:
TALLOC_FREE(result);
}
}
result->value_valid = true;
SAFE_FREE(ctdb_data.dptr);

View File

@ -248,6 +248,7 @@ static struct db_record *dbwrap_watched_fetch_locked(
rec->key = dbwrap_record_get_key(subrec->subrec);
rec->storev = dbwrap_watched_storev;
rec->delete_rec = dbwrap_watched_delete;
rec->value_valid = true;
subrec_value = dbwrap_record_get_value(subrec->subrec);
@ -351,6 +352,7 @@ static void dbwrap_watched_do_locked_fn(
state->subrec.wrec.watchers = watchers;
rec.value = state->subrec.wrec.data;
rec.value_valid = true;
}
state->fn(&rec, state->subrec.wrec.data, state->private_data);
@ -556,6 +558,7 @@ static int dbwrap_watched_traverse_fn(struct db_record *rec,
}
prec.value = wrec.data;
prec.value_valid = true;
return state->fn(&prec, state->private_data);
}