From 726b4685aa25b0b3b4470bfec5d514fb2db7a95e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 26 Aug 2011 14:23:26 -0700 Subject: [PATCH] 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) --- source3/smbd/globals.h | 1 + source3/smbd/smb2_server.c | 40 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 0baf159dd9a..35c44eebb57 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 0310cb1baa0..d29b055b296 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 -- 2.34.1