s3: smbd: Change the function signature of srvstr_push() from returning a length...
authorJeremy Allison <jra@samba.org>
Tue, 26 Aug 2014 00:11:58 +0000 (17:11 -0700)
committerDavid Disseldorp <ddiss@samba.org>
Mon, 15 Sep 2014 23:56:54 +0000 (01:56 +0200)
srvstr_push_fn() now returns an NTSTATUS reporting any
string conversion failure.

We need to get serious about returning character set conversion errors
inside smbd.

Bug 10775 - smbd crashes when accessing garbage filenames

https://bugzilla.samba.org/show_bug.cgi?id=10775

Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: David Disseldorp <ddiss@samba.org>
lib/util/samba_util.h
lib/util/string_wrappers.h
source3/include/safe_string.h
source3/modules/vfs_default.c
source3/smbd/lanman.c
source3/smbd/proto.h
source3/smbd/reply.c
source3/smbd/srvstr.c
source3/smbd/trans2.c

index f1f4c2df839ec7ff347aa25beb7ea330c9bf978f..528d3737dd2c94b03cd99c60fc044fc2e22996e5 100644 (file)
@@ -63,6 +63,7 @@ do { \
 
 #include "lib/util/memory.h"
 
+#include "../libcli/util/ntstatus.h"
 #include "lib/util/string_wrappers.h"
 
 /**
index fcc088ca0404175e0d621e56e6cfba111c83c32a..1feea8cbc071adc846ddce913787cc3f305831d1 100644 (file)
@@ -57,6 +57,8 @@ char * __unsafe_string_function_usage_here__(void);
 
 size_t __unsafe_string_function_usage_here_size_t__(void);
 
+NTSTATUS __unsafe_string_function_usage_here_NTSTATUS__(void);
+
 #define CHECK_STRING_SIZE(d, len) (sizeof(d) != (len) && sizeof(d) != sizeof(char *))
 
 /* if the compiler will optimize out function calls, then use this to tell if we are
@@ -68,10 +70,10 @@ size_t __unsafe_string_function_usage_here_size_t__(void);
     ? __unsafe_string_function_usage_here_size_t__() \
     : push_string_check_fn(dest, src, dest_len, flags))
 
-#define srvstr_push(base_ptr, smb_flags2, dest, src, dest_len, flags) \
+#define srvstr_push(base_ptr, smb_flags2, dest, src, dest_len, flags, ret_len) \
     (CHECK_STRING_SIZE(dest, dest_len) \
-    ? __unsafe_string_function_usage_here_size_t__() \
-    : srvstr_push_fn(base_ptr, smb_flags2, dest, src, dest_len, flags))
+    ? __unsafe_string_function_usage_here_NTSTATUS__() \
+    : srvstr_push_fn(base_ptr, smb_flags2, dest, src, dest_len, flags, ret_len))
 
 /* This allows the developer to choose to check the arguments to
    strlcpy.  if the compiler will optimize out function calls, then
index 03878b48f51a70b355ef69c8922eff5e678f8b7e..e77017c61c9ce47b79965710077b73e68a22fa52 100644 (file)
@@ -62,6 +62,7 @@
 
 #endif /* !_SPLINT_ */
 
+#include "../libcli/util/ntstatus.h"
 #include "lib/util/string_wrappers.h"
 
 #endif
index 3430cd0d68cc783cd6342ce4d98d95b410711c28..3a3943b2571b44964687cffb243dd0ee837b1e55 100644 (file)
@@ -1178,10 +1178,16 @@ static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
                          shadow_data->num_volumes, fsp_str_dbg(fsp)));
                if (labels && shadow_data->labels) {
                        for (i=0; i<shadow_data->num_volumes; i++) {
-                               srvstr_push(cur_pdata, req_flags,
+                               size_t len = 0;
+                               status = srvstr_push(cur_pdata, req_flags,
                                            cur_pdata, shadow_data->labels[i],
                                            2 * sizeof(SHADOW_COPY_LABEL),
-                                           STR_UNICODE|STR_TERMINATE);
+                                           STR_UNICODE|STR_TERMINATE, &len);
+                               if (!NT_STATUS_IS_OK(status)) {
+                                       TALLOC_FREE(*out_data);
+                                       TALLOC_FREE(shadow_data);
+                                       return status;
+                               }
                                cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
                                DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
                        }
index b7c74e907b3ff7059f4247b6e4b9f566b70fbf29..ac4873decca0d07c05f17b37100a25768ca20af9 100644 (file)
@@ -3655,8 +3655,13 @@ static bool api_RNetServerGetInfo(struct smbd_server_connection *sconn,
        }
 
        if (uLevel != 20) {
-               srvstr_push(NULL, 0, p, info.info101->server_name, 16,
-                       STR_ASCII|STR_UPPER|STR_TERMINATE);
+               size_t len = 0;
+               status = srvstr_push(NULL, 0, p, info.info101->server_name, 16,
+                       STR_ASCII|STR_UPPER|STR_TERMINATE, &len);
+               if (!NT_STATUS_IS_OK(status)) {
+                       errcode = W_ERROR_V(ntstatus_to_werror(status));
+                       goto out;
+               }
        }
        p += 16;
        if (uLevel > 0) {
index f2b58884918294f1fd77104249e4c21611a05338..3a5ebcce08fa6d028490dbe9f6b74b4dbe7a3a01 100644 (file)
@@ -1011,8 +1011,8 @@ bool is_share_read_only_for_token(const char *username,
 
 /* The following definitions come from smbd/srvstr.c  */
 
-size_t srvstr_push_fn(const char *base_ptr, uint16 smb_flags2, void *dest,
-                     const char *src, int dest_len, int flags);
+NTSTATUS srvstr_push_fn(const char *base_ptr, uint16 smb_flags2, void *dest,
+                     const char *src, int dest_len, int flags, size_t *ret_len);
 ssize_t message_push_string(uint8 **outbuf, const char *str, int flags);
 
 /* The following definitions come from smbd/statcache.c  */
index 2422ad36290b1df3a113a9a048687564e077ac7c..3c22bbb09a09d1d405a0269f3f100d045804ad24 100644 (file)
@@ -1099,6 +1099,8 @@ void reply_ioctl(struct smb_request *req)
        switch (ioctl_code) {
                case IOCTL_QUERY_JOB_INFO:                  
                {
+                       NTSTATUS status;
+                       size_t len = 0;
                        files_struct *fsp = file_fsp(
                                req, SVAL(req->vwv+0, 0));
                        if (!fsp) {
@@ -1109,15 +1111,25 @@ void reply_ioctl(struct smb_request *req)
                        /* Job number */
                        SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
 
-                       srvstr_push((char *)req->outbuf, req->flags2, p+2,
+                       status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
                                    lp_netbios_name(), 15,
-                                   STR_TERMINATE|STR_ASCII);
+                                   STR_TERMINATE|STR_ASCII, &len);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               reply_nterror(req, status);
+                               END_PROFILE(SMBioctl);
+                               return;
+                       }
                        if (conn) {
-                               srvstr_push((char *)req->outbuf, req->flags2,
+                               status = srvstr_push((char *)req->outbuf, req->flags2,
                                            p+18,
                                            lp_servicename(talloc_tos(),
                                                           SNUM(conn)),
-                                           13, STR_TERMINATE|STR_ASCII);
+                                           13, STR_TERMINATE|STR_ASCII, &len);
+                               if (!NT_STATUS_IS_OK(status)) {
+                                       reply_nterror(req, status);
+                                       END_PROFILE(SMBioctl);
+                                       return;
+                               }
                        } else {
                                memset(p+18, 0, 13);
                        }
@@ -5791,6 +5803,7 @@ void reply_printqueue(struct smb_request *req)
                        char *p = blob;
                        time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
                        int qstatus;
+                       size_t len = 0;
                        uint16_t qrapjobid = pjobid_to_rap(sharename,
                                                        info[i].info2.job_id);
 
@@ -5805,9 +5818,12 @@ void reply_printqueue(struct smb_request *req)
                        SSVAL(p, 5, qrapjobid);
                        SIVAL(p, 7, info[i].info2.size);
                        SCVAL(p, 11, 0);
-                       srvstr_push(blob, req->flags2, p+12,
-                                   info[i].info2.notify_name, 16, STR_ASCII);
-
+                       status = srvstr_push(blob, req->flags2, p+12,
+                                   info[i].info2.notify_name, 16, STR_ASCII, &len);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               reply_nterror(req, status);
+                               goto out;
+                       }
                        if (message_push_blob(
                                    &req->outbuf,
                                    data_blob_const(
index 648c69fbb7b35826555bde0b7259b0de61278530..e6a85419b8a2f2cd3b640c3f4265dc3ac176b5d0 100644 (file)
 
 /* Make sure we can't write a string past the end of the buffer */
 
-size_t srvstr_push_fn(const char *base_ptr, uint16 smb_flags2, void *dest,
-                     const char *src, int dest_len, int flags)
+NTSTATUS srvstr_push_fn(const char *base_ptr, uint16 smb_flags2, void *dest,
+                     const char *src, int dest_len, int flags, size_t *ret_len)
 {
+       size_t len;
+       int saved_errno;
+       NTSTATUS status;
+
        if (dest_len < 0) {
-               return 0;
+               return NT_STATUS_INVALID_PARAMETER;
        }
 
+       saved_errno = errno;
+       errno = 0;
+
        /* 'normal' push into size-specified buffer */
-       return push_string_base(base_ptr, smb_flags2, dest, src,
+       len = push_string_base(base_ptr, smb_flags2, dest, src,
                                dest_len, flags);
+
+       if (errno != 0) {
+               /*
+                * Special case E2BIG, EILSEQ, EINVAL
+                * as they mean conversion errors here,
+                * but we don't generically map them as
+                * they can mean different things in
+                * generic filesystem calls (such as
+                * read xattrs).
+                */
+               if (errno == E2BIG || errno == EILSEQ || errno == EINVAL) {
+                       status = NT_STATUS_ILLEGAL_CHARACTER;
+               } else {
+                       status = map_nt_error_from_unix_common(errno);
+                       /*
+                        * Paranoia - Filter out STATUS_MORE_ENTRIES.
+                        * I don't think we can get this but it has a
+                        * specific meaning to the client.
+                        */
+                       if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
+                               status = NT_STATUS_UNSUCCESSFUL;
+                       }
+               }
+               DEBUG(10,("character conversion failure "
+                       "on string (%s) (%s)\n",
+                       src, strerror(errno)));
+       } else {
+               /* Success - restore untouched errno. */
+               errno = saved_errno;
+               *ret_len = len;
+               status = NT_STATUS_OK;
+       }
+       return status;
 }
 
 /*******************************************************************
@@ -45,8 +85,9 @@ ssize_t message_push_string(uint8 **outbuf, const char *str, int flags)
 {
        size_t buf_size = smb_len(*outbuf) + 4;
        size_t grow_size;
-       size_t result;
+       size_t result = 0;
        uint8 *tmp;
+       NTSTATUS status;
 
        /*
         * We need to over-allocate, now knowing what srvstr_push will
@@ -62,10 +103,10 @@ ssize_t message_push_string(uint8 **outbuf, const char *str, int flags)
                return -1;
        }
 
-       result = srvstr_push((char *)tmp, SVAL(tmp, smb_flg2),
-                            tmp + buf_size, str, grow_size, flags);
+       status = srvstr_push((char *)tmp, SVAL(tmp, smb_flg2),
+                            tmp + buf_size, str, grow_size, flags, &result);
 
-       if (result == 0) {
+       if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0, ("srvstr_push failed\n"));
                return -1;
        }
index 70d29f291ef460fbd98e2afaa7eb149a8b42f406..bdecc607b406416dcf9e8b744bff7361c1e80449 100644 (file)
@@ -1602,6 +1602,7 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
        bool was_8_3;
        int off;
        int pad = 0;
+       NTSTATUS status;
 
        *out_of_space = false;
 
@@ -1684,9 +1685,12 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                if (flags2 & FLAGS2_UNICODE_STRINGS) {
                        p += ucs2_align(base_data, p, 0);
                }
-               len = srvstr_push(base_data, flags2, p,
+               status = srvstr_push(base_data, flags2, p,
                                  fname, PTR_DIFF(end_data, p),
-                                 STR_TERMINATE);
+                                 STR_TERMINATE, &len);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return false;
+               }
                if (flags2 & FLAGS2_UNICODE_STRINGS) {
                        if (len > 2) {
                                SCVAL(nameptr, -1, len - 2);
@@ -1722,9 +1726,12 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                }
                p += 27;
                nameptr = p - 1;
-               len = srvstr_push(base_data, flags2,
+               status = srvstr_push(base_data, flags2,
                                  p, fname, PTR_DIFF(end_data, p),
-                                 STR_TERMINATE | STR_NOALIGN);
+                                 STR_TERMINATE | STR_NOALIGN, &len);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return false;
+               }
                if (flags2 & FLAGS2_UNICODE_STRINGS) {
                        if (len > 2) {
                                len -= 2;
@@ -1747,7 +1754,6 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
        {
                struct ea_list *file_list = NULL;
                size_t ea_len = 0;
-               NTSTATUS status;
 
                DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
                if (!name_list) {
@@ -1787,9 +1793,12 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                /* Push the ea_data followed by the name. */
                p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
                nameptr = p;
-               len = srvstr_push(base_data, flags2,
+               status = srvstr_push(base_data, flags2,
                                  p + 1, fname, PTR_DIFF(end_data, p+1),
-                                 STR_TERMINATE | STR_NOALIGN);
+                                 STR_TERMINATE | STR_NOALIGN, &len);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return false;
+               }
                if (flags2 & FLAGS2_UNICODE_STRINGS) {
                        if (len > 2) {
                                len -= 2;
@@ -1842,9 +1851,12 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                                memset(mangled_name,'\0',12);
                        }
                        mangled_name[12] = 0;
-                       len = srvstr_push(base_data, flags2,
+                       status = srvstr_push(base_data, flags2,
                                          p+2, mangled_name, 24,
-                                         STR_UPPER|STR_UNICODE);
+                                         STR_UPPER|STR_UNICODE, &len);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return false;
+                       }
                        if (len < 24) {
                                memset(p + 2 + len,'\0',24 - len);
                        }
@@ -1853,9 +1865,12 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                        memset(p,'\0',26);
                }
                p += 2 + 24;
-               len = srvstr_push(base_data, flags2, p,
+               status = srvstr_push(base_data, flags2, p,
                                  fname, PTR_DIFF(end_data, p),
-                                 STR_TERMINATE_ASCII);
+                                 STR_TERMINATE_ASCII, &len);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return false;
+               }
                SIVAL(q,0,len);
                p += len;
 
@@ -1889,9 +1904,12 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                SOFF_T(p,0,file_size); p += 8;
                SOFF_T(p,0,allocation_size); p += 8;
                SIVAL(p,0,mode); p += 4;
-               len = srvstr_push(base_data, flags2,
+               status = srvstr_push(base_data, flags2,
                                  p + 4, fname, PTR_DIFF(end_data, p+4),
-                                 STR_TERMINATE_ASCII);
+                                 STR_TERMINATE_ASCII, &len);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return false;
+               }
                SIVAL(p,0,len);
                p += 4 + len;
 
@@ -1932,9 +1950,12 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                        SIVAL(p,0,ea_size); /* Extended attributes */
                        p +=4;
                }
-               len = srvstr_push(base_data, flags2, p,
+               status = srvstr_push(base_data, flags2, p,
                                  fname, PTR_DIFF(end_data, p),
-                                 STR_TERMINATE_ASCII);
+                                 STR_TERMINATE_ASCII, &len);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return false;
+               }
                SIVAL(q, 0, len);
                p += len;
 
@@ -1964,9 +1985,12 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                p += 4;
                /* this must *not* be null terminated or w2k gets in a loop trying to set an
                   acl on a dir (tridge) */
-               len = srvstr_push(base_data, flags2, p,
+               status = srvstr_push(base_data, flags2, p,
                                  fname, PTR_DIFF(end_data, p),
-                                 STR_TERMINATE_ASCII);
+                                 STR_TERMINATE_ASCII, &len);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return false;
+               }
                SIVAL(p, -4, len);
                p += len;
 
@@ -2011,9 +2035,12 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                p += 4;
                SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
                SBVAL(p,0,file_index); p += 8;
-               len = srvstr_push(base_data, flags2, p,
+               status = srvstr_push(base_data, flags2, p,
                                  fname, PTR_DIFF(end_data, p),
-                                 STR_TERMINATE_ASCII);
+                                 STR_TERMINATE_ASCII, &len);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return false;
+               }
                SIVAL(q, 0, len);
                p += len;
 
@@ -2069,9 +2096,12 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                                memset(mangled_name,'\0',12);
                        }
                        mangled_name[12] = 0;
-                       len = srvstr_push(base_data, flags2,
+                       status = srvstr_push(base_data, flags2,
                                          p+2, mangled_name, 24,
-                                         STR_UPPER|STR_UNICODE);
+                                         STR_UPPER|STR_UNICODE, &len);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return false;
+                       }
                        SSVAL(p, 0, len);
                        if (len < 24) {
                                memset(p + 2 + len,'\0',24 - len);
@@ -2083,9 +2113,12 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                p += 26;
                SSVAL(p,0,0); p += 2; /* Reserved ? */
                SBVAL(p,0,file_index); p += 8;
-               len = srvstr_push(base_data, flags2, p,
+               status = srvstr_push(base_data, flags2, p,
                                  fname, PTR_DIFF(end_data, p),
-                                 STR_TERMINATE_ASCII);
+                                 STR_TERMINATE_ASCII, &len);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return false;
+               }
                SIVAL(q,0,len);
                p += len;
 
@@ -2121,17 +2154,23 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
                        DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
                        p = store_file_unix_basic(conn, p,
                                                NULL, &smb_fname->st);
-                       len = srvstr_push(base_data, flags2, p,
+                       status = srvstr_push(base_data, flags2, p,
                                          fname, PTR_DIFF(end_data, p),
-                                         STR_TERMINATE);
+                                         STR_TERMINATE, &len);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return false;
+                       }
                } else {
                        DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
                        p = store_file_unix_basic_info2(conn, p,
                                                NULL, &smb_fname->st);
                        nameptr = p;
                        p += 4;
-                       len = srvstr_push(base_data, flags2, p, fname,
-                                         PTR_DIFF(end_data, p), 0);
+                       status = srvstr_push(base_data, flags2, p, fname,
+                                         PTR_DIFF(end_data, p), 0, &len);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return false;
+                       }
                        SIVAL(nameptr, 0, len);
                }
 
@@ -3181,11 +3220,14 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
                         * this call so try fixing this by adding a terminating null to
                         * the pushed string. The change here was adding the STR_TERMINATE. JRA.
                         */
-                       len = srvstr_push(
+                       status = srvstr_push(
                                pdata, flags2,
                                pdata+l2_vol_szVolLabel, vname,
                                PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
-                               STR_NOALIGN|STR_TERMINATE);
+                               STR_NOALIGN|STR_TERMINATE, &len);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return status;
+                       }
                        SCVAL(pdata,l2_vol_cch,len);
                        data_len = l2_vol_szVolLabel + len;
                        DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
@@ -3218,9 +3260,12 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
                        SIVAL(pdata,4,255); /* Max filename component length */
                        /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
                                and will think we can't do long filenames */
-                       len = srvstr_push(pdata, flags2, pdata+12, fstype,
+                       status = srvstr_push(pdata, flags2, pdata+12, fstype,
                                          PTR_DIFF(end_data, pdata+12),
-                                         STR_UNICODE);
+                                         STR_UNICODE, &len);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return status;
+                       }
                        SIVAL(pdata,8,len);
                        data_len = 12 + len;
                        if (max_data_bytes >= 16 && data_len > max_data_bytes) {
@@ -3234,8 +3279,11 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
 
                case SMB_QUERY_FS_LABEL_INFO:
                case SMB_FS_LABEL_INFORMATION:
-                       len = srvstr_push(pdata, flags2, pdata+4, vname,
-                                         PTR_DIFF(end_data, pdata+4), 0);
+                       status = srvstr_push(pdata, flags2, pdata+4, vname,
+                                         PTR_DIFF(end_data, pdata+4), 0, &len);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return status;
+                       }
                        data_len = 4 + len;
                        SIVAL(pdata,0,len);
                        break;
@@ -3251,9 +3299,12 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
                                (str_checksum(get_local_machine_name())<<16));
 
                        /* Max label len is 32 characters. */
-                       len = srvstr_push(pdata, flags2, pdata+18, vname,
+                       status = srvstr_push(pdata, flags2, pdata+18, vname,
                                          PTR_DIFF(end_data, pdata+18),
-                                         STR_UNICODE);
+                                         STR_UNICODE, &len);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return status;
+                       }
                        SIVAL(pdata,12,len);
                        data_len = 18+len;
 
@@ -4735,10 +4786,13 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                                                True,conn->params)) {
                                return NT_STATUS_NO_MEMORY;
                        }
-                       len = srvstr_push(dstart, flags2,
+                       status = srvstr_push(dstart, flags2,
                                          pdata+4, mangled_name,
                                          PTR_DIFF(dend, pdata+4),
-                                         STR_UNICODE);
+                                         STR_UNICODE, &len);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return status;
+                       }
                        data_size = 4 + len;
                        SIVAL(pdata,0,len);
                        *fixed_portion = 8;
@@ -4750,10 +4804,13 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                        /*
                          this must be *exactly* right for ACLs on mapped drives to work
                         */
-                       len = srvstr_push(dstart, flags2,
+                       status = srvstr_push(dstart, flags2,
                                          pdata+4, dos_fname,
                                          PTR_DIFF(dend, pdata+4),
-                                         STR_UNICODE);
+                                         STR_UNICODE, &len);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return status;
+                       }
                        DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
                        data_size = 4 + len;
                        SIVAL(pdata,0,len);
@@ -4796,10 +4853,13 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                        pdata += 24;
                        SIVAL(pdata,0,ea_size);
                        pdata += 4; /* EA info */
-                       len = srvstr_push(dstart, flags2,
+                       status = srvstr_push(dstart, flags2,
                                          pdata+4, dos_fname,
                                          PTR_DIFF(dend, pdata+4),
-                                         STR_UNICODE);
+                                         STR_UNICODE, &len);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return status;
+                       }
                        SIVAL(pdata,0,len);
                        pdata += 4 + len;
                        data_size = PTR_DIFF(pdata,(*ppdata));
@@ -4833,10 +4893,13 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
 
                        pdata += 0x60;
 
-                       len = srvstr_push(dstart, flags2,
+                       status = srvstr_push(dstart, flags2,
                                          pdata+4, dos_fname,
                                          PTR_DIFF(dend, pdata+4),
-                                         STR_UNICODE);
+                                         STR_UNICODE, &len);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return status;
+                       }
                        SIVAL(pdata,0,len);
                        pdata += 4 + len;
                        data_size = PTR_DIFF(pdata,(*ppdata));
@@ -5030,10 +5093,13 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                                        return map_nt_error_from_unix(errno);
                                }
                                buffer[link_len] = 0;
-                               len = srvstr_push(dstart, flags2,
+                               status = srvstr_push(dstart, flags2,
                                                  pdata, buffer,
                                                  PTR_DIFF(dend, pdata),
-                                                 STR_TERMINATE);
+                                                 STR_TERMINATE, &len);
+                               if (!NT_STATUS_IS_OK(status)) {
+                                       return status;
+                               }
                                pdata += len;
                                data_size = PTR_DIFF(pdata,(*ppdata));
 
@@ -8602,6 +8668,8 @@ static void call_trans2ioctl(connection_struct *conn,
 {
        char *pdata = *ppdata;
        files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
+       NTSTATUS status;
+       size_t len = 0;
 
        /* check for an invalid fid before proceeding */
 
@@ -8625,12 +8693,20 @@ static void call_trans2ioctl(connection_struct *conn,
                /* Job number */
                SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
 
-               srvstr_push(pdata, req->flags2, pdata + 2,
+               status = srvstr_push(pdata, req->flags2, pdata + 2,
                            lp_netbios_name(), 15,
-                           STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
-               srvstr_push(pdata, req->flags2, pdata+18,
+                           STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
+               if (!NT_STATUS_IS_OK(status)) {
+                       reply_nterror(req, status);
+                       return;
+               }
+               status = srvstr_push(pdata, req->flags2, pdata+18,
                            lp_servicename(talloc_tos(), SNUM(conn)), 13,
-                           STR_ASCII|STR_TERMINATE); /* Service name */
+                           STR_ASCII|STR_TERMINATE, &len); /* Service name */
+               if (!NT_STATUS_IS_OK(status)) {
+                       reply_nterror(req, status);
+                       return;
+               }
                send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
                                    max_data_bytes);
                return;