s3:registry: eliminate race condition in creating/scanning sorted subkeys
[samba.git] / source3 / registry / reg_backend_db.c
index 2b6259c03ad330cff0154e391629f0acbfefaa7e..fe15b4e46185c845be7c0f07e7ef595194384db9 100644 (file)
@@ -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:
@@ -1461,7 +1478,7 @@ static WERROR regdb_fetch_keys_internal(struct db_context *db, const char *key,
 
        value = regdb_fetch_key_internal(db, frame, key);
 
-       if (value.dptr == NULL) {
+       if (value.dsize == 0 || value.dptr == NULL) {
                DEBUG(10, ("regdb_fetch_keys: no subkeys found for key [%s]\n",
                           key));
                goto done;
@@ -1470,6 +1487,10 @@ static WERROR regdb_fetch_keys_internal(struct db_context *db, const char *key,
        buf = value.dptr;
        buflen = value.dsize;
        len = tdb_unpack( buf, buflen, "d", &num_items);
+       if (len == (uint32_t)-1) {
+               werr = WERR_NOT_FOUND;
+               goto done;
+       }
 
        werr = regsubkey_ctr_reinit(ctr);
        W_ERROR_NOT_OK_GOTO_DONE(werr);