[SCM] Samba Shared Repository - branch master updated

Jeremy Allison jra at samba.org
Wed Aug 31 13:19:02 MDT 2011


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 <jra at samba.org>
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 <jra at samba.org>
    Autobuild-Date: Wed Aug 31 21:18:11 CEST 2011 on sn-devel-104

commit 726b4685aa25b0b3b4470bfec5d514fb2db7a95e
Author: Jeremy Allison <jra at samba.org>
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 <metze at samba.org>
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


More information about the samba-cvs mailing list