From db4743a8a17280432cff496dce5b2bc354546973 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 1 May 2014 11:01:03 -0700 Subject: [PATCH] s3: smbd : Ensure file_new doesn't call into smbXsrv_open_create() for INTERNAL_OPEN_ONLY. This causes deadlocks which cause smbd to crash if the locking database has already been locked for a compound operation we need to be atomic (as in the file rename case). Ensure INTERNAL_OPEN_ONLY opens are synonymous with req==NULL. INTERNAL_OPEN_ONLY opens leave a NO_OPLOCK record in the share mode database, so they can be detected by other processes for share mode violation purposes (because they're doing an operation on the file that may include reads or writes they need to have real state inside the locking database) but have an fnum of FNUM_FIELD_INVALID and a local share_file_id of zero, as they will never be seen on the wire. Ensure validate_my_share_entries() ignores INTERNAL_OPEN_ONLY records (share_file_id == 0). Bug 10564 - Lock order violation and file lost https://bugzilla.samba.org/show_bug.cgi?id=10564 Signed-off-by: Jeremy Allison Signed-off-by: Volker Lendecke --- source3/smbd/files.c | 5 ++++- source3/smbd/open.c | 14 +++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/source3/smbd/files.c b/source3/smbd/files.c index d94ee119527..d1e7df6d38f 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -93,7 +93,7 @@ NTSTATUS file_new(struct smb_request *req, connection_struct *conn, GetTimeOfDay(&fsp->open_time); - if (sconn->conn) { + if (req) { struct smbXsrv_open *op = NULL; NTTIME now = timeval_to_nttime(&fsp->open_time); @@ -108,6 +108,9 @@ NTSTATUS file_new(struct smb_request *req, connection_struct *conn, op->compat = fsp; fsp->fnum = op->local_id; fsp->fh->gen_id = smbXsrv_open_hash(op); + } else { + DEBUG(10, ("%s: req==NULL, INTERNAL_OPEN_ONLY, smbXsrv_open " + "allocated\n", __func__)); } /* diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6e4f6904c01..15fec95ade2 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1079,6 +1079,11 @@ static void validate_my_share_entries(struct smbd_server_connection *sconn, return; } + if (share_entry->share_file_id == 0) { + /* INTERNAL_OPEN_ONLY */ + return; + } + if (!is_valid_share_mode_entry(share_entry)) { return; } @@ -2088,9 +2093,12 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, create_options, (unsigned int)unx_mode, oplock_request, (unsigned int)private_flags)); - if ((req == NULL) && ((oplock_request & INTERNAL_OPEN_ONLY) == 0)) { - DEBUG(0, ("No smb request but not an internal only open!\n")); - return NT_STATUS_INTERNAL_ERROR; + if (req == NULL) { + /* Ensure req == NULL means INTERNAL_OPEN_ONLY */ + SMB_ASSERT(((oplock_request & INTERNAL_OPEN_ONLY) != 0)); + } else { + /* And req != NULL means no INTERNAL_OPEN_ONLY */ + SMB_ASSERT(((oplock_request & INTERNAL_OPEN_ONLY) == 0)); } /* -- 2.11.4.GIT