summaryrefslogtreecommitdiffstats
path: root/source3/smbd
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2014-05-01 11:01:03 -0700
committerJeremy Allison <jra@samba.org>2014-05-02 21:27:07 +0200
commit580eb9424c5a9645c44b933e2ef144301af035cb (patch)
treec3b389c7952ccb256c86a045a512b73dee06d5c5 /source3/smbd
parentbed323cebcfcf3298002ea8bc2eb6787419043b6 (diff)
downloadsamba-580eb9424c5a9645c44b933e2ef144301af035cb.tar.gz
samba-580eb9424c5a9645c44b933e2ef144301af035cb.tar.xz
samba-580eb9424c5a9645c44b933e2ef144301af035cb.zip
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 <jra@samba.org> Signed-off-by: Volker Lendecke <vl@samba.org>
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/files.c5
-rw-r--r--source3/smbd/open.c14
2 files changed, 15 insertions, 4 deletions
diff --git a/source3/smbd/files.c b/source3/smbd/files.c
index 84968067082..2a0f6cebc0c 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 d05c9ec199a..585d6c9a739 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -1080,6 +1080,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;
}
@@ -2125,9 +2130,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));
}
/*