summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2011-08-26 14:23:26 -0700
committerJeremy Allison <jra@samba.org>2011-08-31 19:49:31 +0200
commit726b4685aa25b0b3b4470bfec5d514fb2db7a95e (patch)
tree0c92c9604dcac5796a89a50dbbb8fdf4563bdd95
parent0d450d166bab952daf37d922e5c2e5cac16f1cc3 (diff)
downloadsamba-726b4685aa25b0b3b4470bfec5d514fb2db7a95e.tar.gz
samba-726b4685aa25b0b3b4470bfec5d514fb2db7a95e.tar.bz2
samba-726b4685aa25b0b3b4470bfec5d514fb2db7a95e.zip
Based on metze's fix for Bug 8407 - SMB2 server can return requests out-of-order when processing a compound request. (cherry picked from commit 19db1c98c6ba3cb5e883e16e865c44900ce17444)
-rw-r--r--source3/smbd/globals.h1
-rw-r--r--source3/smbd/smb2_server.c40
2 files changed, 39 insertions, 2 deletions
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 0baf159dd9..35c44eebb5 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -606,6 +606,7 @@ struct smbd_server_connection {
uint32_t credits_granted;
uint32_t max_credits;
struct bitmap *credits_bitmap;
+ bool compound_related_in_progress;
} smb2;
};
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index 0310cb1baa..d29b055b29 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -886,6 +886,20 @@ NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
if (!NT_STATUS_IS_OK(status)) {
return status;
}
+
+ /*
+ * 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.
+ */
+ req->compound_related = false;
+ req->sconn->smb2.compound_related_in_progress = false;
}
/* Don't return an intermediate packet on a pipe read/write. */
@@ -1305,6 +1319,10 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
req->compat_chain_fsp = NULL;
}
+ if (req->compound_related) {
+ req->sconn->smb2.compound_related_in_progress = true;
+ }
+
switch (opcode) {
case SMB2_OP_NEGPROT:
/* This call needs to be run as root */
@@ -1751,6 +1769,10 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
return NT_STATUS_OK;
}
+ if (req->compound_related) {
+ req->sconn->smb2.compound_related_in_progress = false;
+ }
+
smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
/* Set credit for this operation (zero credits if this
@@ -1801,6 +1823,8 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
return NT_STATUS_OK;
}
+static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
+
void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
struct tevent_immediate *im,
void *private_data)
@@ -1823,9 +1847,13 @@ void smbd_smb2_request_dispatch_immediate(struct tevent_context *ctx,
smbd_server_connection_terminate(sconn, nt_errstr(status));
return;
}
-}
-static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *sconn);
+ status = smbd_smb2_request_next_incoming(sconn);
+ if (!NT_STATUS_IS_OK(status)) {
+ smbd_server_connection_terminate(sconn, nt_errstr(status));
+ return;
+ }
+}
static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
{
@@ -2464,6 +2492,14 @@ 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