The branch, master has been updated
       via  786fe9f Fix bug 8429 - Compound SMB2 requests on an IPC connection 
can corrupt the reply stream.
       via  726b468 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)
       via  0d450d1 s3:smb2_server: keep compound_related on struct 
smbd_smb2_request
      from  fe6c565 s3-waf: fix unresolved symbols in the group policy client 
side extensions subsystem.

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 786fe9fab223723e4d2340f285592b2a44945d73
Author: Jeremy Allison <[email protected]>
Date:   Tue Aug 30 17:37:19 2011 -0700

    Fix bug 8429 - Compound SMB2 requests on an IPC connection can corrupt the 
reply stream.
    
    Autobuild-User: Jeremy Allison <[email protected]>
    Autobuild-Date: Wed Aug 31 21:18:11 CEST 2011 on sn-devel-104

commit 726b4685aa25b0b3b4470bfec5d514fb2db7a95e
Author: Jeremy Allison <[email protected]>
Date:   Fri Aug 26 14:23:26 2011 -0700

    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)

commit 0d450d166bab952daf37d922e5c2e5cac16f1cc3
Author: Stefan Metzmacher <[email protected]>
Date:   Thu Aug 25 23:33:41 2011 +0200

    s3:smb2_server: keep compound_related on struct smbd_smb2_request
    
    metze
    (cherry picked from commit cda93f04eb4e7e975b192a5fd33275ec638140ac)

-----------------------------------------------------------------------

Summary of changes:
 source3/smbd/globals.h     |    2 +
 source3/smbd/smb2_server.c |   76 +++++++++++++++++++++++++++++++++----------
 2 files changed, 60 insertions(+), 18 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index b9bd212..35c44ee 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -355,6 +355,7 @@ struct smbd_smb2_request {
        bool do_signing;
        bool async;
        bool cancelled;
+       bool compound_related;
 
        /* fake smb1 request. */
        struct smb_request *smb1req;
@@ -605,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 6fc4b5d..fa4801c 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -360,7 +360,6 @@ static NTSTATUS smbd_smb2_request_validate(struct 
smbd_smb2_request *req)
 {
        int count;
        int idx;
-       bool compound_related = false;
 
        count = req->in.vector_count;
 
@@ -408,7 +407,7 @@ static NTSTATUS smbd_smb2_request_validate(struct 
smbd_smb2_request *req)
                         * compounded requests
                         */
                        if (flags & SMB2_HDR_FLAG_CHAINED) {
-                               compound_related = true;
+                               req->compound_related = true;
                        }
                } else if (idx > 4) {
 #if 0
@@ -421,13 +420,13 @@ static NTSTATUS smbd_smb2_request_validate(struct 
smbd_smb2_request *req)
                         * all other requests should match the 2nd one
                         */
                        if (flags & SMB2_HDR_FLAG_CHAINED) {
-                               if (!compound_related) {
+                               if (!req->compound_related) {
                                        req->next_status =
                                                NT_STATUS_INVALID_PARAMETER;
                                        return NT_STATUS_OK;
                                }
                        } else {
-                               if (compound_related) {
+                               if (req->compound_related) {
                                        req->next_status =
                                                NT_STATUS_INVALID_PARAMETER;
                                        return NT_STATUS_OK;
@@ -887,11 +886,25 @@ 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. */
        if (req->tcon && req->tcon->compat_conn && 
IS_IPC(req->tcon->compat_conn)) {
-               return NT_STATUS_OK;
+               goto ipc_out;
        }
 
        reqhdr = (uint8_t *)req->out.vector[i].iov_base;
@@ -980,6 +993,8 @@ 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.
@@ -1027,19 +1042,22 @@ NTSTATUS smbd_smb2_request_pending_queue(struct 
smbd_smb2_request *req,
        smb2_setup_nbt_length(req->out.vector,
                req->out.vector_count);
 
-       /* Ensure our final reply matches the interim one. */
-       reqhdr = (uint8_t *)req->out.vector[1].iov_base;
-       SIVAL(reqhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
-       SBVAL(reqhdr, SMB2_HDR_PID, async_id);
+       if (req->async) {
+               /* Ensure our final reply matches the interim one. */
+               reqhdr = (uint8_t *)req->out.vector[1].iov_base;
+               SIVAL(reqhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
+               SBVAL(reqhdr, SMB2_HDR_PID, async_id);
 
-       {
-               const uint8_t *inhdr =
-                       (const uint8_t *)req->in.vector[1].iov_base;
-               DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] mid %llu 
"
-                       "going async\n",
-                       smb2_opcode_name((uint16_t)IVAL(inhdr, 
SMB2_HDR_OPCODE)),
-                       (unsigned long long)async_id ));
+               {
+                       const uint8_t *inhdr =
+                               (const uint8_t *)req->in.vector[1].iov_base;
+                       DEBUG(10,("smbd_smb2_request_pending_queue: opcode[%s] 
mid %llu "
+                               "going async\n",
+                               smb2_opcode_name((uint16_t)IVAL(inhdr, 
SMB2_HDR_OPCODE)),
+                               (unsigned long long)async_id ));
+               }
        }
+
        return NT_STATUS_OK;
 }
 
@@ -1306,6 +1324,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 */
@@ -1752,6 +1774,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
@@ -1802,6 +1828,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)
@@ -1824,9 +1852,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)
 {
@@ -2465,6 +2497,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


-- 
Samba Shared Repository

Reply via email to