From d3b81495c68ae06291929a0f878e3dbe2545cc99 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 ef229a4098a..53d6d4f6852 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 a41d3d534fe..a596bceb181 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1082,6 +1082,11 @@ static void validate_my_share_entries(struct smbd_server_connection *sconn, smb_panic(str); } + if (share_entry->share_file_id == 0) { + /* INTERNAL_OPEN_ONLY */ + return; + } + if (!is_valid_share_mode_entry(share_entry)) { return; } @@ -2029,9 +2034,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