diff options
author | Andrew Tridgell <tridge@samba.org> | 2006-03-30 06:07:38 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:59:21 -0500 |
commit | 6942d1d62c23ea2e43469485c0e0503d3906760c (patch) | |
tree | 2d494810d445bd6c5f285778499a85bad68c2008 | |
parent | 61ce5cd1c687041563873b679ece3ea2e1b7f1f7 (diff) | |
download | samba-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.c | 61 |
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; } |