summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2011-05-16 12:20:14 -0700
committerKarolin Seeger <kseeger@samba.org>2011-05-17 09:20:13 +0200
commit3c21f14a0686384697cdec4b02360d958505f51b (patch)
tree3d979a6f425188e7c5bef34389b5f4be325761e7
parenta58a74d2bdf0897bfa76426fc721c7c216458549 (diff)
downloadsamba-3c21f14a0686384697cdec4b02360d958505f51b.tar.gz
samba-3c21f14a0686384697cdec4b02360d958505f51b.tar.xz
samba-3c21f14a0686384697cdec4b02360d958505f51b.zip
Fix the SMB2 showstopper, found by an extended torture test from Volker.
In the oplock refactoring, the algorithm underwent an unnoticed change. In 3.5.x stat_opens were silently (i.e. no explicit code had comments explaining this) ignored when looking for oplock breaks and share mode violations. After the refactoring, the function find_oplock_types() no longer ignored stat_open entries in the share mode table when looking for batch and exclusive oplocks. This patch adds two changes to find_oplock_types() to ignore the case where the incoming open request is a stat open being tested against existing opens, and also when the incoming open request is a non-stat open being tested against existing stat opens. Neither of these cause an oplock break or share mode violation. Thanks a *lot* to Volker, who persevered in reproducing this problem. Autobuild-User: Jeremy Allison <jra@samba.org> Autobuild-Date: Mon May 16 22:38:20 CEST 2011 on sn-devel-104 (cherry picked from commit 8cf14c21b3bc55454728bf48b23f696e15c92aea) (cherry picked from commit a2bc1d37b98a0581960039a5ff3deb55cf0c4f90)
-rw-r--r--source3/smbd/open.c28
1 files changed, 25 insertions, 3 deletions
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index b8984ee4417..e537d0fc2f1 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -950,7 +950,9 @@ static NTSTATUS send_break_message(files_struct *fsp,
* Do internal consistency checks on the share mode for a file.
*/
-static void find_oplock_types(struct share_mode_lock *lck,
+static void find_oplock_types(files_struct *fsp,
+ int oplock_request,
+ struct share_mode_lock *lck,
struct share_mode_entry **pp_batch,
struct share_mode_entry **pp_ex_or_batch,
bool *got_level2,
@@ -963,11 +965,27 @@ static void find_oplock_types(struct share_mode_lock *lck,
*got_level2 = false;
*got_no_oplock = false;
+ /* Ignore stat or internal opens, as is done in
+ delay_for_batch_oplocks() and
+ delay_for_exclusive_oplocks().
+ */
+ if ((oplock_request & INTERNAL_OPEN_ONLY) || is_stat_open(fsp->access_mask)) {
+ return;
+ }
+
for (i=0; i<lck->num_share_modes; i++) {
if (!is_valid_share_mode_entry(&lck->share_modes[i])) {
continue;
}
+ if (lck->share_modes[i].op_type == NO_OPLOCK &&
+ is_stat_open(lck->share_modes[i].access_mask)) {
+ /* We ignore stat opens in the table - they
+ always have NO_OPLOCK and never get or
+ cause breaks. JRA. */
+ continue;
+ }
+
if (BATCH_OPLOCK_TYPE(lck->share_modes[i].op_type)) {
/* batch - can only be one. */
if (*pp_ex_or_batch || *pp_batch || *got_level2 || *got_no_oplock) {
@@ -1907,7 +1925,9 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
}
/* Get the types we need to examine. */
- find_oplock_types(lck,
+ find_oplock_types(fsp,
+ oplock_request,
+ lck,
&batch_entry,
&exclusive_entry,
&got_level2_oplock,
@@ -2152,7 +2172,9 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
}
/* Get the types we need to examine. */
- find_oplock_types(lck,
+ find_oplock_types(fsp,
+ oplock_request,
+ lck,
&batch_entry,
&exclusive_entry,
&got_level2_oplock,