[SCM] Samba Shared Repository - branch master updated

Jeremy Allison jra at samba.org
Fri Apr 11 15:56:03 MDT 2014


The branch, master has been updated
       via  e49bae7 s3:smb2_server: remove unused get_min_receive_file_size() wrapper function
       via  535103e s3:smb2_server: only allocate the required buffer in the smb2 recvfile() code path
       via  80de72b s3:smb2_server: prepare smbd_smb2_request_verify_sizes() for the optimized recvfile() case
       via  1f767b2 s3:smb2_write: allow SMBD_SMB2_IN_DYN_LEN() to be 0 for the recvfile case.
       via  95df39b s3:smb2_server: make sure we don't try recvfile for special NBT messages
       via  7968749 s3:smb2_server: use the same logic to avoid recvfile() for IPC/PRINT shares
       via  77b6860 s3:smbd: use smb1srv_open_lookup() in is_valid_writeX_buffer()
       via  8d45b75 s3:smbXsrv_open: allow now==0 to skip the idle_time update.
       via  f717802 s3:lib: use stack buffers in drain_socket() and default_sys_recvfile()
      from  4daf7d4 libs: s3 and s4: make our dns lookup code signal-safe.

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


- Log -----------------------------------------------------------------
commit e49bae7ac9fb0be4cbb4530d75a4431cbbb495c8
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Apr 11 01:37:42 2014 +0200

    s3:smb2_server: remove unused get_min_receive_file_size() wrapper function
    
    smb2req always comes from talloc_zero().
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    
    Autobuild-User(master): Jeremy Allison <jra at samba.org>
    Autobuild-Date(master): Fri Apr 11 23:55:17 CEST 2014 on sn-devel-104

commit 535103e7a38e175fec082a658c2b70dbdd9af33e
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Nov 15 09:12:40 2013 +0100

    s3:smb2_server: only allocate the required buffer in the smb2 recvfile() code path
    
    This way the buffer will likely be allocated within the existing talloc_pool,
    which avoids one malloc() per request.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 80de72bb57520a1a14c3d3db3f31dc588d0afd64
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Nov 18 13:46:10 2013 +0100

    s3:smb2_server: prepare smbd_smb2_request_verify_sizes() for the optimized recvfile() case
    
    For recvfile we haven't read and may not allocated the dyn buffer.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 1f767b29a89e15c4d7187cd0bc9b0c2e3152edd7
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Nov 18 13:45:37 2013 +0100

    s3:smb2_write: allow SMBD_SMB2_IN_DYN_LEN() to be 0 for the recvfile case.
    
    For recvfile we haven't read and may not allocated the dyn buffer.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 95df39b99f17810cb230c4a6a0d0952919cd0b81
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Apr 11 01:05:21 2014 +0200

    s3:smb2_server: make sure we don't try recvfile for special NBT messages
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 796874912d9935e202b8c767ca33d557dce9c43e
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Apr 11 00:43:46 2014 +0200

    s3:smb2_server: use the same logic to avoid recvfile() for IPC/PRINT shares
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 77b6860668437bbb3bb66f57f75ea4fc378de49b
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Apr 11 00:51:32 2014 +0200

    s3:smbd: use smb1srv_open_lookup() in is_valid_writeX_buffer()
    
    It's more logical to check the fnum instead of tid here.
    This will make it easier to reuse the logic for SMB2 and
    allows per fsp recvfile detection.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 8d45b75df31d5c382345186791a375e2b800066e
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Apr 11 00:29:48 2014 +0200

    s3:smbXsrv_open: allow now==0 to skip the idle_time update.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit f71780202a3e736432020cf894b138a06e4bb869
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Dec 5 11:20:49 2013 +0100

    s3:lib: use stack buffers in drain_socket() and default_sys_recvfile()
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

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

Summary of changes:
 source3/lib/recvfile.c      |   18 +------
 source3/smbd/globals.h      |    1 +
 source3/smbd/reply.c        |   29 +++++++---
 source3/smbd/smb2_server.c  |  116 +++++++++++++++++++++++++++++++------------
 source3/smbd/smb2_write.c   |   20 +++++++-
 source3/smbd/smbXsrv_open.c |    4 +-
 6 files changed, 128 insertions(+), 60 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/lib/recvfile.c b/source3/lib/recvfile.c
index 72f4257..500a7e4 100644
--- a/source3/lib/recvfile.c
+++ b/source3/lib/recvfile.c
@@ -51,7 +51,7 @@ static ssize_t default_sys_recvfile(int fromfd,
 	size_t total = 0;
 	size_t bufsize = MIN(TRANSFER_BUF_SIZE,count);
 	size_t total_written = 0;
-	char *buffer = NULL;
+	char buffer[bufsize];
 
 	DEBUG(10,("default_sys_recvfile: from = %d, to = %d, "
 		"offset=%.0f, count = %lu\n",
@@ -70,11 +70,6 @@ static ssize_t default_sys_recvfile(int fromfd,
 		}
 	}
 
-	buffer = SMB_MALLOC_ARRAY(char, bufsize);
-	if (buffer == NULL) {
-		return -1;
-	}
-
 	while (total < count) {
 		size_t num_written = 0;
 		ssize_t read_ret;
@@ -84,7 +79,6 @@ static ssize_t default_sys_recvfile(int fromfd,
 		read_ret = sys_read(fromfd, buffer, toread);
 		if (read_ret <= 0) {
 			/* EOF or socket error. */
-			free(buffer);
 			return -1;
 		}
 
@@ -119,7 +113,6 @@ static ssize_t default_sys_recvfile(int fromfd,
 		total += read_ret;
 	}
 
-	free(buffer);
 	if (saved_errno) {
 		/* Return the correct write error. */
 		errno = saved_errno;
@@ -247,21 +240,15 @@ ssize_t drain_socket(int sockfd, size_t count)
 {
 	size_t total = 0;
 	size_t bufsize = MIN(TRANSFER_BUF_SIZE,count);
-	char *buffer = NULL;
+	char buffer[bufsize];
 	int old_flags = 0;
 
 	if (count == 0) {
 		return 0;
 	}
 
-	buffer = SMB_MALLOC_ARRAY(char, bufsize);
-	if (buffer == NULL) {
-		return -1;
-	}
-
 	old_flags = fcntl(sockfd, F_GETFL, 0);
 	if (set_blocking(sockfd, true) == -1) {
-		free(buffer);
 		return -1;
 	}
 
@@ -281,7 +268,6 @@ ssize_t drain_socket(int sockfd, size_t count)
 
   out:
 
-	free(buffer);
 	if (fcntl(sockfd, F_SETFL, old_flags) == -1) {
 		return -1;
 	}
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 3baa048..cd99fe7 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -768,6 +768,7 @@ struct smbd_server_connection {
 			struct iovec vector;
 			bool doing_receivefile;
 			size_t min_recv_size;
+			size_t pktfull;
 			size_t pktlen;
 			uint8_t *pktbuf;
 		} request_read_state;
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index e58735e..da59ca7 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -4598,12 +4598,12 @@ bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
 			    const uint8_t *inbuf)
 {
 	size_t numtowrite;
-	connection_struct *conn = NULL;
 	unsigned int doff = 0;
 	size_t len = smb_len_large(inbuf);
-	struct smbXsrv_tcon *tcon;
+	uint16_t fnum;
+	struct smbXsrv_open *op = NULL;
+	struct files_struct *fsp = NULL;
 	NTSTATUS status;
-	NTTIME now = 0;
 
 	if (is_encrypted_packet(sconn, inbuf)) {
 		/* Can't do this on encrypted
@@ -4622,19 +4622,30 @@ bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
 		return false;
 	}
 
-	status = smb1srv_tcon_lookup(sconn->conn, SVAL(inbuf, smb_tid),
-				     now, &tcon);
+	fnum = SVAL(inbuf, smb_vwv2);
+	status = smb1srv_open_lookup(sconn->conn,
+				     fnum,
+				     0, /* now */
+				     &op);
 	if (!NT_STATUS_IS_OK(status)) {
-		DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
+		DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
+		return false;
+	}
+	fsp = op->compat;
+	if (fsp == NULL) {
+		DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
+		return false;
+	}
+	if (fsp->conn == NULL) {
+		DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
 		return false;
 	}
-	conn = tcon->compat;
 
-	if (IS_IPC(conn)) {
+	if (IS_IPC(fsp->conn)) {
 		DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
 		return false;
 	}
-	if (IS_PRINT(conn)) {
+	if (IS_PRINT(fsp->conn)) {
 		DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
 		return false;
 	}
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index 3c46efd..4a7abcb 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -1870,6 +1870,15 @@ NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req,
 	case SMB2_OP_GETINFO:
 		min_dyn_size = 0;
 		break;
+	case SMB2_OP_WRITE:
+		if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
+			if (req->smb1req->unread_bytes < min_dyn_size) {
+				return NT_STATUS_INVALID_PARAMETER;
+			}
+
+			min_dyn_size = 0;
+		}
+		break;
 	}
 
 	/*
@@ -2828,20 +2837,21 @@ NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
 	return NT_STATUS_OK;
 }
 
-static size_t get_min_receive_file_size(struct smbd_smb2_request *smb2_req)
-{
-	if (smb2_req->do_signing) {
-		return 0;
-	}
-	if (smb2_req->do_encryption) {
-		return 0;
-	}
-	return (size_t)lp_min_receive_file_size();
-}
-
 static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
 {
+	NTSTATUS status;
 	uint32_t flags;
+	uint64_t file_id_persistent;
+	uint64_t file_id_volatile;
+	struct smbXsrv_open *op = NULL;
+	struct files_struct *fsp = NULL;
+	const uint8_t *body = NULL;
+
+	/*
+	 * This is only called with a pktbuf
+	 * of at least SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN
+	 * bytes
+	 */
 
 	if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) {
 		/* Transform header. Cannot recvfile. */
@@ -2873,9 +2883,37 @@ static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state)
 		return false;
 	}
 
+	body = &state->pktbuf[SMB2_HDR_BODY];
+
+	file_id_persistent	= BVAL(body, 0x10);
+	file_id_volatile	= BVAL(body, 0x18);
+
+	status = smb2srv_open_lookup(state->req->sconn->conn,
+				     file_id_persistent,
+				     file_id_volatile,
+				     0, /* now */
+				     &op);
+	if (!NT_STATUS_IS_OK(status)) {
+		return false;
+	}
+
+	fsp = op->compat;
+	if (fsp == NULL) {
+		return false;
+	}
+	if (fsp->conn == NULL) {
+		return false;
+	}
+
+	if (IS_IPC(fsp->conn)) {
+		return false;
+	}
+	if (IS_PRINT(fsp->conn)) {
+		return false;
+	}
+
 	DEBUG(10,("Doing recvfile write len = %u\n",
-		(unsigned int)(state->pktlen -
-		SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN)));
+		(unsigned int)(state->pktfull - state->pktlen)));
 
 	return true;
 }
@@ -2920,7 +2958,7 @@ static NTSTATUS smbd_smb2_request_next_incoming(struct smbd_server_connection *s
 		return NT_STATUS_NO_MEMORY;
 	}
 	state->req->sconn = sconn;
-	state->min_recv_size = get_min_receive_file_size(state->req);
+	state->min_recv_size = lp_min_receive_file_size();
 
 	TEVENT_FD_READABLE(sconn->smb2.fde);
 
@@ -3213,10 +3251,21 @@ again:
 			 * Read the rest of the data.
 			 */
 			state->doing_receivefile = false;
+
+			state->pktbuf = talloc_realloc(state->req,
+						       state->pktbuf,
+						       uint8_t,
+						       state->pktfull);
+			if (state->pktbuf == NULL) {
+				return NT_STATUS_NO_MEMORY;
+			}
+
 			state->vector.iov_base = (void *)(state->pktbuf +
-				SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN);
-			state->vector.iov_len = (state->pktlen -
-				SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN);
+				state->pktlen);
+			state->vector.iov_len = (state->pktfull -
+				state->pktlen);
+
+			state->pktlen = state->pktfull;
 			goto again;
 		}
 
@@ -3230,24 +3279,20 @@ again:
 	/*
 	 * Now we analyze the NBT header
 	 */
-	state->pktlen = smb2_len(state->hdr.nbt);
-	if (state->pktlen == 0) {
-		goto got_full;
+	if (state->hdr.nbt[0] != 0x00) {
+		state->min_recv_size = 0;
 	}
-
-	state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
-	if (state->pktbuf == NULL) {
-		return NT_STATUS_NO_MEMORY;
+	state->pktfull = smb2_len(state->hdr.nbt);
+	if (state->pktfull == 0) {
+		goto got_full;
 	}
 
-	state->vector.iov_base = (void *)state->pktbuf;
-
 	if (state->min_recv_size != 0) {
 		min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
 		min_recvfile_size += state->min_recv_size;
 	}
 
-	if (state->pktlen > min_recvfile_size) {
+	if (state->pktfull > min_recvfile_size) {
 		/*
 		 * Might be a receivefile write. Read the SMB2 HEADER +
 		 * SMB2_WRITE header first. Set 'doing_receivefile'
@@ -3256,12 +3301,20 @@ again:
 		 * not suitable then we'll just read the rest of the data
 		 * the next time this function is called.
 		 */
-		state->vector.iov_len = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
+		state->pktlen = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
 		state->doing_receivefile = true;
 	} else {
-		state->vector.iov_len = state->pktlen;
+		state->pktlen = state->pktfull;
 	}
 
+	state->pktbuf = talloc_array(state->req, uint8_t, state->pktlen);
+	if (state->pktbuf == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	state->vector.iov_base = (void *)state->pktbuf;
+	state->vector.iov_len = state->pktlen;
+
 	goto again;
 
 got_full:
@@ -3273,7 +3326,7 @@ got_full:
 		req = state->req;
 		ZERO_STRUCTP(state);
 		state->req = req;
-		state->min_recv_size = get_min_receive_file_size(state->req);
+		state->min_recv_size = lp_min_receive_file_size();
 		req = NULL;
 		goto again;
 	}
@@ -3300,8 +3353,7 @@ got_full:
 		if (req->smb1req == NULL) {
 			return NT_STATUS_NO_MEMORY;
 		}
-		req->smb1req->unread_bytes =
-			state->pktlen - SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN;
+		req->smb1req->unread_bytes = state->pktfull - state->pktlen;
 	}
 
 	ZERO_STRUCTP(state);
diff --git a/source3/smbd/smb2_write.c b/source3/smbd/smb2_write.c
index 4e138fe..c61254f 100644
--- a/source3/smbd/smb2_write.c
+++ b/source3/smbd/smb2_write.c
@@ -48,6 +48,8 @@ NTSTATUS smbd_smb2_request_process_write(struct smbd_smb2_request *req)
 	uint64_t in_file_id_volatile;
 	struct files_struct *in_fsp;
 	uint32_t in_flags;
+	size_t in_dyn_len = 0;
+	uint8_t *in_dyn_ptr = NULL;
 	struct tevent_req *subreq;
 
 	status = smbd_smb2_request_verify_sizes(req, 0x31);
@@ -67,7 +69,15 @@ NTSTATUS smbd_smb2_request_process_write(struct smbd_smb2_request *req)
 		return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
 	}
 
-	if (in_data_length > SMBD_SMB2_IN_DYN_LEN(req)) {
+	if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) {
+		in_dyn_ptr = NULL;
+		in_dyn_len = req->smb1req->unread_bytes;
+	} else {
+		in_dyn_ptr = SMBD_SMB2_IN_DYN_PTR(req);
+		in_dyn_len = SMBD_SMB2_IN_DYN_LEN(req);
+	}
+
+	if (in_data_length > in_dyn_len) {
 		return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
 	}
 
@@ -79,7 +89,10 @@ NTSTATUS smbd_smb2_request_process_write(struct smbd_smb2_request *req)
 		return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
 	}
 
-	in_data_buffer.data = SMBD_SMB2_IN_DYN_PTR(req);
+	/*
+	 * Note: that in_dyn_ptr is NULL for the recvfile case.
+	 */
+	in_data_buffer.data = in_dyn_ptr;
 	in_data_buffer.length = in_data_length;
 
 	status = smbd_smb2_request_verify_creditcharge(req, in_data_length);
@@ -340,6 +353,9 @@ static struct tevent_req *smbd_smb2_write_send(TALLOC_CTX *mem_ctx,
 		return tevent_req_post(req, ev);
 	}
 
+	/*
+	 * Note: in_data.data is NULL for the recvfile case.
+	 */
 	nwritten = write_file(smbreq, fsp,
 			      (const char *)in_data.data,
 			      in_offset,
diff --git a/source3/smbd/smbXsrv_open.c b/source3/smbd/smbXsrv_open.c
index b15be28..c3ff3bb 100644
--- a/source3/smbd/smbXsrv_open.c
+++ b/source3/smbd/smbXsrv_open.c
@@ -444,7 +444,9 @@ static NTSTATUS smbXsrv_open_local_lookup(struct smbXsrv_open_table *table,
 		return NT_STATUS_FILE_CLOSED;
 	}
 
-	state.op->idle_time = now;
+	if (now != 0) {
+		state.op->idle_time = now;
+	}
 
 	*_open = state.op;
 	return state.op->status;


-- 
Samba Shared Repository


More information about the samba-cvs mailing list