summaryrefslogtreecommitdiff
path: root/source3/registry/reg_backend_db.c
diff options
context:
space:
mode:
authorMichael Adam <obnox@samba.org>2010-02-08 11:01:47 +0100
committerMichael Adam <obnox@samba.org>2010-02-12 23:12:12 +0100
commita752bbd10d661ebc93b8d51bd583eb62eb00ad18 (patch)
tree09e5e4c5883c3e08f2903448c410eb2bd3e05fa1 /source3/registry/reg_backend_db.c
parent09f3ed102472304d6b4446a6fab9cf6f05c9176a (diff)
downloadsamba-a752bbd10d661ebc93b8d51bd583eb62eb00ad18.tar.gz
samba-a752bbd10d661ebc93b8d51bd583eb62eb00ad18.tar.bz2
samba-a752bbd10d661ebc93b8d51bd583eb62eb00ad18.zip
s3:registry: eliminate race condition in creating/scanning sorted subkeys
Called, from key_exists, scan_sorted_subkeys re-creates the sorted subkeys record of the given key and then searches through it. The race is that between creation and parsing of the sorted subkey record, another process that stores some other subkey of the same parent key will delete the sorted subkey record, resulting in an WERR_BADFILE of an operation that should actually succeed. This patch fixes the issue by wrapping the creation and parsing into a transaction. Michael
Diffstat (limited to 'source3/registry/reg_backend_db.c')
-rw-r--r--source3/registry/reg_backend_db.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/source3/registry/reg_backend_db.c b/source3/registry/reg_backend_db.c
index 43963db3c2..fe15b4e461 100644
--- a/source3/registry/reg_backend_db.c
+++ b/source3/registry/reg_backend_db.c
@@ -1368,14 +1368,31 @@ static bool scan_parent_subkeys(struct db_context *db, const char *parent,
if (state.scanned) {
result = state.found;
} else {
+ res = db->transaction_start(db);
+ if (res != 0) {
+ DEBUG(0, ("error starting transacion\n"));
+ goto fail;
+ }
+
if (!create_sorted_subkeys(path, key)) {
+ res = db->transaction_cancel(db);
+ if (res != 0) {
+ smb_panic("Failed to cancel transaction.");
+ }
goto fail;
}
+
res = db->parse_record(db, string_term_tdb_data(key),
parent_subkey_scanner, &state);
if ((res == 0) && (state.scanned)) {
result = state.found;
}
+
+ res = db->transaction_commit(db);
+ if (res != 0) {
+ DEBUG(0, ("error committing transaction\n"));
+ result = false;
+ }
}
fail: