summaryrefslogtreecommitdiff
path: root/source3/smbd/open.c
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2014-05-01 11:01:03 -0700
committerKarolin Seeger <kseeger@samba.org>2014-05-19 12:19:52 +0200
commitdb4743a8a17280432cff496dce5b2bc354546973 (patch)
treea3d7fee82334ca4cb998f6d6a82fa6da136304a4 /source3/smbd/open.c
parent90871a52194c8135336ae2dac185059ba9193040 (diff)
downloadsamba-db4743a8a17280432cff496dce5b2bc354546973.tar.gz
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/open.c')
-rw-r--r--source3/smbd/open.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 6e4f6904c0..15fec95ade 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));
}
/*