summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2006-03-30 06:07:38 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:59:21 -0500
commit6942d1d62c23ea2e43469485c0e0503d3906760c (patch)
tree2d494810d445bd6c5f285778499a85bad68c2008
parent61ce5cd1c687041563873b679ece3ea2e1b7f1f7 (diff)
downloadsamba-6942d1d62c23ea2e43469485c0e0503d3906760c.tar.gz
samba-6942d1d62c23ea2e43469485c0e0503d3906760c.tar.bz2
samba-6942d1d62c23ea2e43469485c0e0503d3906760c.zip
r14805: use tdb_lock_bystring() to prevent race conditions in notify add/remove
(This used to be commit a6be44f78ca2eaecbf0b6d8598addba5a11ae966)
-rw-r--r--source4/ntvfs/common/notify.c61
1 files changed, 56 insertions, 5 deletions
diff --git a/source4/ntvfs/common/notify.c b/source4/ntvfs/common/notify.c
index 52abc08d74..dd39aca095 100644
--- a/source4/ntvfs/common/notify.c
+++ b/source4/ntvfs/common/notify.c
@@ -109,6 +109,26 @@ struct notify_context *notify_init(TALLOC_CTX *mem_ctx, uint32_t server,
return notify;
}
+
+/*
+ lock the notify db
+*/
+static NTSTATUS notify_lock(struct notify_context *notify)
+{
+ if (tdb_lock_bystring(notify->w->tdb, NOTIFY_KEY) != 0) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ return NT_STATUS_OK;
+}
+
+/*
+ unlock the notify db
+*/
+static void notify_unlock(struct notify_context *notify)
+{
+ tdb_unlock_bystring(notify->w->tdb, NOTIFY_KEY);
+}
+
/*
load the notify array
*/
@@ -230,14 +250,21 @@ NTSTATUS notify_add(struct notify_context *notify, struct notify_entry *e,
char *path = NULL;
size_t len;
- status = notify_load(notify);
+ status = notify_lock(notify);
NT_STATUS_NOT_OK_RETURN(status);
+ status = notify_load(notify);
+ if (!NT_STATUS_IS_OK(status)) {
+ notify_unlock(notify);
+ return status;
+ }
+
notify->array->entries = talloc_realloc(notify->array, notify->array->entries,
struct notify_entry,
notify->array->num_entries+1);
if (notify->array->entries == NULL) {
+ notify_unlock(notify);
return NT_STATUS_NO_MEMORY;
}
@@ -258,6 +285,9 @@ NTSTATUS notify_add(struct notify_context *notify, struct notify_entry *e,
notify->array->num_entries++;
status = notify_save(notify);
+
+ notify_unlock(notify);
+
NT_STATUS_NOT_OK_RETURN(status);
if (path) {
@@ -293,9 +323,15 @@ NTSTATUS notify_remove(struct notify_context *notify, void *private)
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
- status = notify_load(notify);
+ status = notify_lock(notify);
NT_STATUS_NOT_OK_RETURN(status);
+ status = notify_load(notify);
+ if (!NT_STATUS_IS_OK(status)) {
+ notify_unlock(notify);
+ return status;
+ }
+
for (i=0;i<notify->array->num_entries;i++) {
if (notify->server == notify->array->entries[i].server &&
private == notify->array->entries[i].private) {
@@ -303,6 +339,7 @@ NTSTATUS notify_remove(struct notify_context *notify, void *private)
}
}
if (i == notify->array->num_entries) {
+ notify_unlock(notify);
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
@@ -312,7 +349,11 @@ NTSTATUS notify_remove(struct notify_context *notify, void *private)
}
notify->array->num_entries--;
- return notify_save(notify);
+ status = notify_save(notify);
+
+ notify_unlock(notify);
+
+ return status;
}
/*
@@ -327,9 +368,15 @@ static NTSTATUS notify_remove_all(struct notify_context *notify)
return NT_STATUS_OK;
}
- status = notify_load(notify);
+ status = notify_lock(notify);
NT_STATUS_NOT_OK_RETURN(status);
+ status = notify_load(notify);
+ if (!NT_STATUS_IS_OK(status)) {
+ notify_unlock(notify);
+ return status;
+ }
+
for (i=0;i<notify->array->num_entries;i++) {
if (notify->server == notify->array->entries[i].server) {
if (i < notify->array->num_entries-1) {
@@ -342,7 +389,11 @@ static NTSTATUS notify_remove_all(struct notify_context *notify)
}
- return notify_save(notify);
+ status = notify_save(notify);
+
+ notify_unlock(notify);
+
+ return status;
}