The Samba-Bugzilla – Attachment 8873 Details for
Bug 9722
Samba does not properly handle Oplock breaks in compound requests
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
git-am patchset for 3.6.next
bug-9722-v3.6.patchset (text/plain), 9.78 KB, created by
Jeremy Allison
on 2013-05-08 22:32:17 UTC
(
hide
)
Description:
git-am patchset for 3.6.next
Filename:
MIME Type:
Creator:
Jeremy Allison
Created:
2013-05-08 22:32:17 UTC
Size:
9.78 KB
patch
obsolete
>From 13886dacabd2622f4723e1981412c6fa61bbd2ee Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 8 May 2013 11:50:32 -0700 >Subject: [PATCH 1/4] Only do the 1 second delay for sharing violations for > SMB1, not SMB2. > >Match Windows behavior. > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/smbd/open.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > >diff --git a/source3/smbd/open.c b/source3/smbd/open.c >index d10b697..447de80 100644 >--- a/source3/smbd/open.c >+++ b/source3/smbd/open.c >@@ -2002,10 +2002,11 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, > > /* > * If we're returning a share violation, ensure we >- * cope with the braindead 1 second delay. >+ * cope with the braindead 1 second delay (SMB1 only). > */ > > if (!(oplock_request & INTERNAL_OPEN_ONLY) && >+ !conn->sconn->using_smb2 && > lp_defer_sharing_violations()) { > struct timeval timeout; > struct deferred_open_record state; >-- >1.8.2.1 > > >From 6bdf6ec5ce116d15995014f5162a17ac930772dc Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 8 May 2013 11:51:38 -0700 >Subject: [PATCH 2/4] Ensure we don't try and cancel anything that is in a > compound-related request. > >Too hard to deal with splitting off the replies. > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/smbd/smb2_server.c | 8 ++++++++ > 1 file changed, 8 insertions(+) > >diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c >index cc884c3..396d476 100644 >--- a/source3/smbd/smb2_server.c >+++ b/source3/smbd/smb2_server.c >@@ -1178,6 +1178,14 @@ static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req) > uint64_t message_id; > uint64_t async_id; > >+ if (cur->compound_related) { >+ /* >+ * Never cancel anything in a compound request. >+ * Way too hard to deal with the result. >+ */ >+ continue; >+ } >+ > i = cur->current_idx; > > outhdr = (const uint8_t *)cur->out.vector[i].iov_base; >-- >1.8.2.1 > > >From be669df1dbb62d605fedd71788afa0b02f345d75 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 8 May 2013 15:08:50 -0700 >Subject: [PATCH 3/4] The core of the fix to allow opens to go async inside a > compound request. > >This is only allowed for opens that cause an oplock break, otherwise it >is not allowed. See [MS-SMB2].pdf note <194> on Section 3.3.5.2.7. > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/smbd/smb2_server.c | 128 ++++++++++++++++++++------------------------- > 1 file changed, 57 insertions(+), 71 deletions(-) > >diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c >index 396d476..f1f9966 100644 >--- a/source3/smbd/smb2_server.c >+++ b/source3/smbd/smb2_server.c >@@ -927,7 +927,6 @@ NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req, > uint32_t flags = 0; > uint64_t message_id = 0; > uint64_t async_id = 0; >- struct iovec *outvec = NULL; > > if (!tevent_req_is_in_progress(subreq)) { > return NT_STATUS_OK; >@@ -944,16 +943,27 @@ NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req, > if (req->in.vector_count > i + 3) { > /* > * We're trying to go async in a compound >- * request chain. This is not allowed. >- * Cancel the outstanding request. >+ * request chain. >+ * This is only allowed for opens that >+ * cause an oplock break, otherwise it >+ * is not allowed. See [MS-SMB2].pdf >+ * note <194> on Section 3.3.5.2.7. > */ >- bool ok = tevent_req_cancel(req->subreq); >- if (ok) { >- return NT_STATUS_OK; >- } >- TALLOC_FREE(req->subreq); >- return smbd_smb2_request_error(req, >- NT_STATUS_INTERNAL_ERROR); >+ const uint8_t *inhdr = >+ (const uint8_t *)req->in.vector[i].iov_base; >+ >+ if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_CREATE) { >+ /* >+ * Cancel the outstanding request. >+ */ >+ bool ok = tevent_req_cancel(req->subreq); >+ if (ok) { >+ return NT_STATUS_OK; >+ } >+ TALLOC_FREE(req->subreq); >+ return smbd_smb2_request_error(req, >+ NT_STATUS_INTERNAL_ERROR); >+ } > } > > if (DEBUGLEVEL >= 10) { >@@ -962,35 +972,55 @@ NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req, > print_req_vectors(req); > } > >- if (req->out.vector_count > 4) { >- /* This is a compound reply. We >- * must do an interim response >- * followed by the async response >- * to match W2K8R2. >+ if (i > 1) { >+ /* >+ * We're going async in a compound >+ * chain after the first request has >+ * already been processed. Send an >+ * interim response containing the >+ * set of replies already generated. > */ > status = smb2_send_async_interim_response(req); > if (!NT_STATUS_IS_OK(status)) { > return status; > } > >+ req->current_idx = 1; >+ > /* >- * We're splitting off the last SMB2 >- * request in a compound set, and the >- * smb2_send_async_interim_response() >- * call above just sent all the replies >- * for the previous SMB2 requests in >- * this compound set. So we're no longer >- * in the "compound_related_in_progress" >- * state, and this is no longer a compound >- * request. >+ * Re-arrange the in.vectors to remove what >+ * we just sent. > */ >- req->compound_related = false; >- req->sconn->smb2.compound_related_in_progress = false; >+ memmove(&req->in.vector[1], >+ &req->in.vector[i], >+ sizeof(req->in.vector[0])*(req->in.vector_count - i)); >+ req->in.vector_count = 1 + (req->in.vector_count - i); >+ >+ smb2_setup_nbt_length(req->in.vector, req->in.vector_count); >+ >+ /* Re-arrange the out.vectors to match. */ >+ memmove(&req->out.vector[1], >+ &req->out.vector[i], >+ sizeof(req->out.vector[0])*(req->out.vector_count - i)); >+ req->out.vector_count = 1 + (req->out.vector_count - i); >+ >+ if (req->in.vector_count == 4) { >+ uint8_t *outhdr = (uint8_t *)req->out.vector[i].iov_base; >+ /* >+ * We only have one remaining request as >+ * we've processed everything else. >+ * This is no longer a compound request. >+ */ >+ req->compound_related = false; >+ req->sconn->smb2.compound_related_in_progress = false; >+ flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED); >+ SIVAL(outhdr, SMB2_HDR_FLAGS, flags); >+ } > } > > /* Don't return an intermediate packet on a pipe read/write. */ > if (req->tcon && req->tcon->compat_conn && IS_IPC(req->tcon->compat_conn)) { >- goto ipc_out; >+ goto out; > } > > reqhdr = (uint8_t *)req->out.vector[i].iov_base; >@@ -1081,50 +1111,6 @@ NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req, > /* Note we're going async with this request. */ > req->async = true; > >- ipc_out: >- >- /* >- * Now manipulate req so that the outstanding async request >- * is the only one left in the struct smbd_smb2_request. >- */ >- >- if (req->current_idx == 1) { >- /* There was only one. */ >- goto out; >- } >- >- /* Re-arrange the in.vectors. */ >- req->in.vector[1] = req->in.vector[i]; >- req->in.vector[2] = req->in.vector[i+1]; >- req->in.vector[3] = req->in.vector[i+2]; >- req->in.vector_count = 4; >- /* Reset the new in size. */ >- smb2_setup_nbt_length(req->in.vector, 4); >- >- /* Now recreate the out.vectors. */ >- outvec = talloc_zero_array(req, struct iovec, 4); >- if (!outvec) { >- return NT_STATUS_NO_MEMORY; >- } >- >- /* 0 is always boilerplate and must >- * be of size 4 for the length field. */ >- >- outvec[0].iov_base = req->out.nbt_hdr; >- outvec[0].iov_len = 4; >- SIVAL(req->out.nbt_hdr, 0, 0); >- >- if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) { >- return NT_STATUS_NO_MEMORY; >- } >- >- TALLOC_FREE(req->out.vector); >- >- req->out.vector = outvec; >- >- req->current_idx = 1; >- req->out.vector_count = 4; >- > out: > > smb2_setup_nbt_length(req->out.vector, >-- >1.8.2.1 > > >From e8a381d214471a45ba707b1e0bf388cb722e0824 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 8 May 2013 15:10:32 -0700 >Subject: [PATCH 4/4] Remove the compound_related_in_progress state from the > smb2 global state. > >And also remove the restriction that we can't read a new >request whilst we're in this state. > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/smbd/globals.h | 1 - > source3/smbd/smb2_server.c | 11 ----------- > 2 files changed, 12 deletions(-) > >diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h >index 730bb7e..ce5b18d 100644 >--- a/source3/smbd/globals.h >+++ b/source3/smbd/globals.h >@@ -647,7 +647,6 @@ struct smbd_server_connection { > uint32_t max_trans; > uint32_t max_read; > uint32_t max_write; >- bool compound_related_in_progress; > } smb2; > }; > >diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c >index f1f9966..9615907 100644 >--- a/source3/smbd/smb2_server.c >+++ b/source3/smbd/smb2_server.c >@@ -1012,7 +1012,6 @@ NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req, > * This is no longer a compound request. > */ > req->compound_related = false; >- req->sconn->smb2.compound_related_in_progress = false; > flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED); > SIVAL(outhdr, SMB2_HDR_FLAGS, flags); > } >@@ -1354,7 +1353,6 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req) > > if (flags & SMB2_HDR_FLAG_CHAINED) { > req->compound_related = true; >- req->sconn->smb2.compound_related_in_progress = true; > } > > switch (opcode) { >@@ -1824,7 +1822,6 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req) > > if (req->compound_related) { > req->compound_related = false; >- req->sconn->smb2.compound_related_in_progress = false; > } > > smb2_setup_nbt_length(req->out.vector, req->out.vector_count); >@@ -2541,14 +2538,6 @@ static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *s > size_t cur_send_queue_len; > struct tevent_req *subreq; > >- if (sconn->smb2.compound_related_in_progress) { >- /* >- * Can't read another until the related >- * compound is done. >- */ >- return NT_STATUS_OK; >- } >- > if (tevent_queue_length(sconn->smb2.recv_queue) > 0) { > /* > * if there is already a smbd_smb2_request_read >-- >1.8.2.1 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Flags:
rsharpe
:
review+
jra
:
review?
(
ira
)
Actions:
View
Attachments on
bug 9722
:
8646
|
8647
|
8684
|
8844
|
8846
|
8847
|
8869
| 8873