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 <me...@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 <me...@samba.org>
    Reviewed-by: Jeremy Allison <j...@samba.org>
    
    Autobuild-User(master): Jeremy Allison <j...@samba.org>
    Autobuild-Date(master): Fri Apr 11 23:55:17 CEST 2014 on sn-devel-104

commit 535103e7a38e175fec082a658c2b70dbdd9af33e
Author: Stefan Metzmacher <me...@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 <me...@samba.org>
    Reviewed-by: Jeremy Allison <j...@samba.org>

commit 80de72bb57520a1a14c3d3db3f31dc588d0afd64
Author: Stefan Metzmacher <me...@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 <me...@samba.org>
    Reviewed-by: Jeremy Allison <j...@samba.org>

commit 1f767b29a89e15c4d7187cd0bc9b0c2e3152edd7
Author: Stefan Metzmacher <me...@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 <me...@samba.org>
    Reviewed-by: Jeremy Allison <j...@samba.org>

commit 95df39b99f17810cb230c4a6a0d0952919cd0b81
Author: Stefan Metzmacher <me...@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 <me...@samba.org>
    Reviewed-by: Jeremy Allison <j...@samba.org>

commit 796874912d9935e202b8c767ca33d557dce9c43e
Author: Stefan Metzmacher <me...@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 <me...@samba.org>
    Reviewed-by: Jeremy Allison <j...@samba.org>

commit 77b6860668437bbb3bb66f57f75ea4fc378de49b
Author: Stefan Metzmacher <me...@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 <me...@samba.org>
    Reviewed-by: Jeremy Allison <j...@samba.org>

commit 8d45b75df31d5c382345186791a375e2b800066e
Author: Stefan Metzmacher <me...@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 <me...@samba.org>
    Reviewed-by: Jeremy Allison <j...@samba.org>

commit f71780202a3e736432020cf894b138a06e4bb869
Author: Stefan Metzmacher <me...@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 <me...@samba.org>
    Reviewed-by: Jeremy Allison <j...@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

Reply via email to