The branch, master has been updated via 79dc084 torture: Add smb2.notify.rmdir via 50a1247 smbd: Cancel pending notifies if the directory goes away via b0d4a7d smbd: Remove bool arg from set_delete_on_close_lck via 1f3735a smbd: Use reset_delete_on_close_lck directly via d75a0a5 smbd: Introduce reset_delete_on_close_lck via 9e7cf87 s3:smbd: use smbd_reinit_after_fork via b4a0864 s3:smbd: add wrapper around reinit_after_fork from 2e2ff8b s4-torture: add one more test for witness_RegisterEx() and invalid sharenames.
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 79dc084dcb6e28211addfc5d75b817cc735d67c1 Author: Volker Lendecke <v...@samba.org> Date: Mon Apr 20 10:44:07 2015 +0000 torture: Add smb2.notify.rmdir We need to cancel a pending FileChangeNotify with DELETE_PENDING if the directory watched is about to be deleted. I know I just deleted a bool parameter, but to me torture is different :-) Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> Autobuild-User(master): Jeremy Allison <j...@samba.org> Autobuild-Date(master): Thu Apr 23 01:36:48 CEST 2015 on sn-devel-104 commit 50a1247927cb68303701a11517811deda10364f7 Author: Volker Lendecke <v...@samba.org> Date: Tue Apr 21 10:16:16 2015 +0200 smbd: Cancel pending notifies if the directory goes away Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit b0d4a7daa149cfc9ef697dd7fae4524a35078126 Author: Volker Lendecke <v...@samba.org> Date: Tue Apr 21 11:41:45 2015 +0200 smbd: Remove bool arg from set_delete_on_close_lck We now have reset_delete_on_close_lck, this was called with "true" everywhere now. Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 1f3735a28c3e6cbe2ca6c8e3bf312b3ea8c1754e Author: Volker Lendecke <v...@samba.org> Date: Tue Apr 21 11:38:32 2015 +0200 smbd: Use reset_delete_on_close_lck directly Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit d75a0a589f477e4541badfc1a6ba939e281a5582 Author: Volker Lendecke <v...@samba.org> Date: Tue Apr 21 11:36:30 2015 +0200 smbd: Introduce reset_delete_on_close_lck Boolean flags passed down make things more complex than necessary... Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 9e7cf87a30d92a32e7cdf1569d8b804078be456f Author: Ralph Boehme <s...@samba.org> Date: Wed Apr 22 12:00:10 2015 +0200 s3:smbd: use smbd_reinit_after_fork Signed-off-by: Ralph Boehme <s...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit b4a0864f64e4e6b5997012bb33e0e5e0fa760b03 Author: Ralph Boehme <s...@samba.org> Date: Wed Apr 22 11:57:24 2015 +0200 s3:smbd: add wrapper around reinit_after_fork smbd_reinit_after_fork is a simple wrapper around reinit_after_fork that should be used after forking from the main smbd. At the moment the only additional step it performs is resetting am_parent to NULL. A subsequent commit will make use of this function. Signed-off-by: Ralph Boehme <s...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> ----------------------------------------------------------------------- Summary of changes: librpc/idl/messaging.idl | 3 ++ source3/include/proto.h | 3 ++ source3/locking/locking.c | 101 ++++++++++++++++++++++------------- source3/locking/proto.h | 3 +- source3/printing/queue_process.c | 2 +- source3/printing/spoolssd.c | 4 +- source3/rpc_server/epmd.c | 4 +- source3/rpc_server/fssd.c | 4 +- source3/rpc_server/lsasd.c | 4 +- source3/smbd/close.c | 6 +-- source3/smbd/notify.c | 43 +++++++++++++++ source3/smbd/process.c | 4 +- source3/smbd/proto.h | 3 ++ source3/smbd/scavenger.c | 4 +- source3/smbd/server.c | 7 +-- source3/smbd/server_exit.c | 12 +++++ source3/smbd/service.c | 4 ++ source4/torture/smb2/notify.c | 110 +++++++++++++++++++++++++++++++++++++++ 18 files changed, 255 insertions(+), 66 deletions(-) Changeset truncated at 500 lines: diff --git a/librpc/idl/messaging.idl b/librpc/idl/messaging.idl index 04dfa1e..2b902ec 100644 --- a/librpc/idl/messaging.idl +++ b/librpc/idl/messaging.idl @@ -96,6 +96,9 @@ interface messaging MSG_SMB_TELL_NUM_CHILDREN = 0x0317, MSG_SMB_NUM_CHILDREN = 0x0318, + /* Cancel a notify, directory got deleted */ + MSG_SMB_NOTIFY_CANCEL_DELETED = 0x0319, + /* winbind messages */ MSG_WINBIND_FINISHED = 0x0401, MSG_WINBIND_FORGET_STATE = 0x0402, diff --git a/source3/include/proto.h b/source3/include/proto.h index 4acad41..30fd4fa 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -374,6 +374,9 @@ NTSTATUS init_before_fork(void); NTSTATUS reinit_after_fork(struct messaging_context *msg_ctx, struct tevent_context *ev_ctx, bool parent_longlived); +NTSTATUS smbd_reinit_after_fork(struct messaging_context *msg_ctx, + struct tevent_context *ev_ctx, + bool parent_longlived); void *malloc_(size_t size); void *Realloc(void *p, size_t size, bool free_old_on_error); void add_to_large_array(TALLOC_CTX *mem_ctx, size_t element_size, diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 221d6ee..ce595e1 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -46,6 +46,7 @@ #include "messages.h" #include "util_tdb.h" #include "../librpc/gen_ndr/ndr_open_files.h" +#include "librpc/gen_ndr/ndr_file_id.h" #include "locking/leases_db.h" #undef DBGC_CLASS @@ -1081,6 +1082,27 @@ static bool add_delete_on_close_token(struct share_mode_data *d, return true; } +void reset_delete_on_close_lck(files_struct *fsp, + struct share_mode_lock *lck) +{ + struct share_mode_data *d = lck->data; + uint32_t i; + + for (i=0; i<d->num_delete_tokens; i++) { + struct delete_token *dt = &d->delete_tokens[i]; + + if (dt->name_hash == fsp->name_hash) { + d->modified = true; + + /* Delete this entry. */ + TALLOC_FREE(dt->delete_nt_token); + TALLOC_FREE(dt->delete_token); + *dt = d->delete_tokens[d->num_delete_tokens-1]; + d->num_delete_tokens -= 1; + } + } +} + /**************************************************************************** Sets the delete on close flag over all share modes on this file. Modify the share mode entry for all files open @@ -1094,54 +1116,63 @@ static bool add_delete_on_close_token(struct share_mode_data *d, void set_delete_on_close_lck(files_struct *fsp, struct share_mode_lock *lck, - bool delete_on_close, const struct security_token *nt_tok, const struct security_unix_token *tok) { + struct messaging_context *msg_ctx = fsp->conn->sconn->msg_ctx; struct share_mode_data *d = lck->data; - int i; + uint32_t i; bool ret; + DATA_BLOB fid_blob = {}; + enum ndr_err_code ndr_err; - if (delete_on_close) { - SMB_ASSERT(nt_tok != NULL); - SMB_ASSERT(tok != NULL); - } else { - SMB_ASSERT(nt_tok == NULL); - SMB_ASSERT(tok == NULL); - } + SMB_ASSERT(nt_tok != NULL); + SMB_ASSERT(tok != NULL); for (i=0; i<d->num_delete_tokens; i++) { struct delete_token *dt = &d->delete_tokens[i]; if (dt->name_hash == fsp->name_hash) { d->modified = true; - if (delete_on_close == false) { - /* Delete this entry. */ - TALLOC_FREE(dt->delete_nt_token); - TALLOC_FREE(dt->delete_token); - *dt = d->delete_tokens[ - d->num_delete_tokens-1]; - d->num_delete_tokens -= 1; - } else { - /* Replace this token with the - given tok. */ - TALLOC_FREE(dt->delete_nt_token); - dt->delete_nt_token = dup_nt_token(dt, nt_tok); - SMB_ASSERT(dt->delete_nt_token != NULL); - TALLOC_FREE(dt->delete_token); - dt->delete_token = copy_unix_token(dt, tok); - SMB_ASSERT(dt->delete_token != NULL); - } + + /* Replace this token with the given tok. */ + TALLOC_FREE(dt->delete_nt_token); + dt->delete_nt_token = dup_nt_token(dt, nt_tok); + SMB_ASSERT(dt->delete_nt_token != NULL); + TALLOC_FREE(dt->delete_token); + dt->delete_token = copy_unix_token(dt, tok); + SMB_ASSERT(dt->delete_token != NULL); + return; } } - if (!delete_on_close) { - /* Nothing to delete - not found. */ - return; - } - ret = add_delete_on_close_token(lck->data, fsp->name_hash, nt_tok, tok); SMB_ASSERT(ret); + + ndr_err = ndr_push_struct_blob(&fid_blob, talloc_tos(), &fsp->file_id, + (ndr_push_flags_fn_t)ndr_push_file_id); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DEBUG(10, ("ndr_push_file_id failed: %s\n", + ndr_errstr(ndr_err))); + } + + for (i=0; i<d->num_share_modes; i++) { + struct share_mode_entry *e = &d->share_modes[i]; + NTSTATUS status; + + status = messaging_send( + msg_ctx, e->pid, MSG_SMB_NOTIFY_CANCEL_DELETED, + &fid_blob); + + if (!NT_STATUS_IS_OK(status)) { + struct server_id_buf tmp; + DEBUG(10, ("%s: messaging_send to %s returned %s\n", + __func__, server_id_str_buf(e->pid, &tmp), + nt_errstr(status))); + } + } + + TALLOC_FREE(fid_blob.data); } bool set_delete_on_close(files_struct *fsp, bool delete_on_close, @@ -1161,13 +1192,9 @@ bool set_delete_on_close(files_struct *fsp, bool delete_on_close, } if (delete_on_close) { - set_delete_on_close_lck(fsp, lck, true, - nt_tok, - tok); + set_delete_on_close_lck(fsp, lck, nt_tok, tok); } else { - set_delete_on_close_lck(fsp, lck, false, - NULL, - NULL); + reset_delete_on_close_lck(fsp, lck); } if (fsp->is_directory) { diff --git a/source3/locking/proto.h b/source3/locking/proto.h index c4ea198..75faa94 100644 --- a/source3/locking/proto.h +++ b/source3/locking/proto.h @@ -185,9 +185,10 @@ bool get_delete_on_close_token(struct share_mode_lock *lck, uint32_t name_hash, const struct security_token **pp_nt_tok, const struct security_unix_token **pp_tok); +void reset_delete_on_close_lck(files_struct *fsp, + struct share_mode_lock *lck); void set_delete_on_close_lck(files_struct *fsp, struct share_mode_lock *lck, - bool delete_on_close, const struct security_token *nt_tok, const struct security_unix_token *tok); bool set_delete_on_close(files_struct *fsp, bool delete_on_close, diff --git a/source3/printing/queue_process.c b/source3/printing/queue_process.c index 88196b4..50622dc 100644 --- a/source3/printing/queue_process.c +++ b/source3/printing/queue_process.c @@ -373,7 +373,7 @@ pid_t start_background_queue(struct tevent_context *ev, close(pause_pipe[0]); pause_pipe[0] = -1; - status = reinit_after_fork(msg_ctx, ev, true); + status = smbd_reinit_after_fork(msg_ctx, ev, true); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("reinit_after_fork() failed\n")); diff --git a/source3/printing/spoolssd.c b/source3/printing/spoolssd.c index 11bd82f..3007898 100644 --- a/source3/printing/spoolssd.c +++ b/source3/printing/spoolssd.c @@ -645,9 +645,7 @@ pid_t start_spoolssd(struct tevent_context *ev_ctx, return pid; } - status = reinit_after_fork(msg_ctx, - ev_ctx, - true); + status = smbd_reinit_after_fork(msg_ctx, ev_ctx, true); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("reinit_after_fork() failed\n")); smb_panic("reinit_after_fork() failed"); diff --git a/source3/rpc_server/epmd.c b/source3/rpc_server/epmd.c index 6b6119b..dad67ae 100644 --- a/source3/rpc_server/epmd.c +++ b/source3/rpc_server/epmd.c @@ -162,9 +162,7 @@ void start_epmd(struct tevent_context *ev_ctx, return; } - status = reinit_after_fork(msg_ctx, - ev_ctx, - true); + status = smbd_reinit_after_fork(msg_ctx, ev_ctx, true); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("reinit_after_fork() failed\n")); smb_panic("reinit_after_fork() failed"); diff --git a/source3/rpc_server/fssd.c b/source3/rpc_server/fssd.c index eb9b7e6..fc1f630 100644 --- a/source3/rpc_server/fssd.c +++ b/source3/rpc_server/fssd.c @@ -171,9 +171,7 @@ void start_fssd(struct tevent_context *ev_ctx, } /* child */ - status = reinit_after_fork(msg_ctx, - ev_ctx, - true); + status = smbd_reinit_after_fork(msg_ctx, ev_ctx, true); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("reinit_after_fork() failed\n")); smb_panic("reinit_after_fork() failed"); diff --git a/source3/rpc_server/lsasd.c b/source3/rpc_server/lsasd.c index 42d91fd..d287bff 100644 --- a/source3/rpc_server/lsasd.c +++ b/source3/rpc_server/lsasd.c @@ -861,9 +861,7 @@ void start_lsasd(struct tevent_context *ev_ctx, return; } - status = reinit_after_fork(msg_ctx, - ev_ctx, - true); + status = smbd_reinit_after_fork(msg_ctx, ev_ctx, true); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("reinit_after_fork() failed\n")); smb_panic("reinit_after_fork() failed"); diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 4fbd442f..09be2e7 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -303,7 +303,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, became_user = True; } fsp->delete_on_close = true; - set_delete_on_close_lck(fsp, lck, True, + set_delete_on_close_lck(fsp, lck, get_current_nttok(conn), get_current_utok(conn)); if (became_user) { @@ -461,7 +461,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, */ fsp->delete_on_close = false; - set_delete_on_close_lck(fsp, lck, false, NULL, NULL); + reset_delete_on_close_lck(fsp, lck); done: @@ -1076,7 +1076,7 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp, } send_stat_cache_delete_message(fsp->conn->sconn->msg_ctx, fsp->fsp_name->base_name); - set_delete_on_close_lck(fsp, lck, true, + set_delete_on_close_lck(fsp, lck, get_current_nttok(fsp->conn), get_current_utok(fsp->conn)); fsp->delete_on_close = true; diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 5ac8c0c..8cb44df 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -23,6 +23,7 @@ #include "smbd/smbd.h" #include "smbd/globals.h" #include "../librpc/gen_ndr/ndr_notify.h" +#include "librpc/gen_ndr/ndr_file_id.h" struct notify_change_event { struct timespec when; @@ -418,6 +419,48 @@ void smbd_notify_cancel_by_smbreq(const struct smb_request *smbreq) change_notify_remove_request(sconn, map->req); } +static struct files_struct *smbd_notify_cancel_deleted_fn( + struct files_struct *fsp, void *private_data) +{ + struct file_id *fid = talloc_get_type_abort( + private_data, struct file_id); + + if (file_id_equal(&fsp->file_id, fid)) { + remove_pending_change_notify_requests_by_fid( + fsp, NT_STATUS_DELETE_PENDING); + } + return NULL; +} + +void smbd_notify_cancel_deleted(struct messaging_context *msg, + void *private_data, uint32_t msg_type, + struct server_id server_id, DATA_BLOB *data) +{ + struct smbd_server_connection *sconn = talloc_get_type_abort( + private_data, struct smbd_server_connection); + struct file_id *fid; + enum ndr_err_code ndr_err; + + fid = talloc(talloc_tos(), struct file_id); + if (fid == NULL) { + DEBUG(1, ("talloc failed\n")); + return; + } + + ndr_err = ndr_pull_struct_blob_all( + data, fid, fid, (ndr_pull_flags_fn_t)ndr_pull_file_id); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DEBUG(10, ("%s: ndr_pull_file_id failed: %s\n", __func__, + ndr_errstr(ndr_err))); + goto done; + } + + files_forall(sconn, smbd_notify_cancel_deleted_fn, fid); + +done: + TALLOC_FREE(fid); +} + /**************************************************************************** Delete entries by fnum from the change notify pending queue. *****************************************************************************/ diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 38edb02..aa7f419 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -3306,9 +3306,7 @@ bool fork_echo_handler(struct smbXsrv_connection *xconn) close(listener_pipe[0]); set_blocking(listener_pipe[1], false); - status = reinit_after_fork(xconn->msg_ctx, - xconn->ev_ctx, - true); + status = smbd_reinit_after_fork(xconn->msg_ctx, xconn->ev_ctx, true); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("reinit_after_fork failed: %s\n", nt_errstr(status))); diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index f01bbbd..a5144d5 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -517,6 +517,9 @@ NTSTATUS change_notify_add_request(struct smb_request *req, void (*reply_fn)(struct smb_request *req, NTSTATUS error_code, uint8_t *buf, size_t len)); +void smbd_notify_cancel_deleted(struct messaging_context *msg, + void *private_data, uint32_t msg_type, + struct server_id server_id, DATA_BLOB *data); void remove_pending_change_notify_requests_by_mid( struct smbd_server_connection *sconn, uint64_t mid); void remove_pending_change_notify_requests_by_fid(files_struct *fsp, diff --git a/source3/smbd/scavenger.c b/source3/smbd/scavenger.c index 013b4d2..19f9b43 100644 --- a/source3/smbd/scavenger.c +++ b/source3/smbd/scavenger.c @@ -244,11 +244,9 @@ static bool smbd_scavenger_start(struct smbd_scavenger_state *state) close(fds[0]); - am_parent = NULL; - set_my_unique_id(unique_id); - status = reinit_after_fork(state->msg, state->ev, true); + status = smbd_reinit_after_fork(state->msg, state->ev, true); if (!NT_STATUS_IS_OK(status)) { DEBUG(2, ("reinit_after_fork failed: %s\n", nt_errstr(status))); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 030f760..6921719 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -590,9 +590,6 @@ static void smbd_accept_connection(struct tevent_context *ev, if (pid == 0) { NTSTATUS status = NT_STATUS_OK; - /* Child code ... */ - am_parent = NULL; - /* * Can't use TALLOC_FREE here. Nulling out the argument to it * would overwrite memory we've just freed. @@ -606,9 +603,7 @@ static void smbd_accept_connection(struct tevent_context *ev, * them, counting worker smbds. */ CatchChild(); - status = reinit_after_fork(msg_ctx, - ev, - true); + status = smbd_reinit_after_fork(msg_ctx, ev, true); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status, NT_STATUS_TOO_MANY_OPENED_FILES)) { diff --git a/source3/smbd/server_exit.c b/source3/smbd/server_exit.c index 69d0fdd..700f595 100644 --- a/source3/smbd/server_exit.c +++ b/source3/smbd/server_exit.c @@ -268,3 +268,15 @@ void smbd_exit_server_cleanly(const char *const explanation) { exit_server_common(SERVER_EXIT_NORMAL, explanation); } + +/* + * reinit_after_fork() wrapper that should be called when forking from + * smbd. + */ +NTSTATUS smbd_reinit_after_fork(struct messaging_context *msg_ctx, + struct tevent_context *ev_ctx, + bool parent_longlived) +{ + am_parent = NULL; + return reinit_after_fork(msg_ctx, ev_ctx, parent_longlived); +} diff --git a/source3/smbd/service.c b/source3/smbd/service.c index ada2d07..d11987e 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -682,6 +682,10 @@ static NTSTATUS make_connection_snum(struct smbXsrv_connection *xconn, if (sconn->notify_ctx == NULL) { sconn->notify_ctx = notify_init( sconn, sconn->msg_ctx, sconn->ev_ctx); + status = messaging_register( + sconn->msg_ctx, sconn, + MSG_SMB_NOTIFY_CANCEL_DELETED, + smbd_notify_cancel_deleted); } if (sconn->sys_notify_ctx == NULL) { sconn->sys_notify_ctx = sys_notify_context_create( diff --git a/source4/torture/smb2/notify.c b/source4/torture/smb2/notify.c index bbdc223..0f572b6 100644 --- a/source4/torture/smb2/notify.c +++ b/source4/torture/smb2/notify.c @@ -2015,6 +2015,108 @@ done: return ret; } +static bool torture_smb2_notify_rmdir(struct torture_context *torture, + struct smb2_tree *tree1, + struct smb2_tree *tree2, + bool initial_delete_on_close) +{ + bool ret = true; + NTSTATUS status; + union smb_notify notify = {}; + union smb_setfileinfo sfinfo = {}; + union smb_open io = {}; + struct smb2_handle h = {}; + struct smb2_request *req; + + torture_comment(torture, "TESTING NOTIFY CANCEL FOR DELETED DIR\n"); + + smb2_deltree(tree1, BASEDIR); + smb2_util_rmdir(tree1, BASEDIR); + + ZERO_STRUCT(io.smb2); + io.generic.level = RAW_OPEN_SMB2; + io.smb2.in.create_flags = 0; + io.smb2.in.desired_access = SEC_FILE_ALL; + io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; + io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL; + io.smb2.in.share_access = + NTCREATEX_SHARE_ACCESS_READ | -- Samba Shared Repository