diff options
author | Gordon Ross <gwr@nexenta.com> | 2019-11-22 23:39:36 -0500 |
---|---|---|
committer | Gordon Ross <gordon.ross@tintri.com> | 2021-02-27 13:33:24 -0500 |
commit | 25a9a7aaf35c7e4a2b5a57d3875af906147710d5 (patch) | |
tree | 32d4dabef674b6ff39dbd02891b5aedb90c803b3 | |
parent | 4d00d81bf82141f996e032f9c53e0e996a5f7204 (diff) | |
download | illumos-joyent-25a9a7aaf35c7e4a2b5a57d3875af906147710d5.tar.gz |
13572 SMB Query FileFsVolumeInformation should allow truncation
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: C Fraire <cfraire@me.com>
Approved by: Robert Mustacchi <rm@fingolfin.org>
-rw-r--r-- | usr/src/cmd/smbsrv/test-msgbuf/test_mbmarshal.c | 96 | ||||
-rw-r--r-- | usr/src/cmd/smbsrv/test-msgbuf/test_msgbuf.c | 88 | ||||
-rw-r--r-- | usr/src/common/smbsrv/smb_msgbuf.c | 20 | ||||
-rw-r--r-- | usr/src/uts/common/fs/smbsrv/smb2_fsctl_fs.c | 27 | ||||
-rw-r--r-- | usr/src/uts/common/fs/smbsrv/smb2_qinfo_file.c | 73 | ||||
-rw-r--r-- | usr/src/uts/common/fs/smbsrv/smb2_qinfo_fs.c | 72 | ||||
-rw-r--r-- | usr/src/uts/common/fs/smbsrv/smb_mbuf_marshaling.c | 30 | ||||
-rw-r--r-- | usr/src/uts/common/fs/smbsrv/smb_tree.c | 21 | ||||
-rw-r--r-- | usr/src/uts/common/smbsrv/smb_ktypes.h | 1 |
9 files changed, 337 insertions, 91 deletions
diff --git a/usr/src/cmd/smbsrv/test-msgbuf/test_mbmarshal.c b/usr/src/cmd/smbsrv/test-msgbuf/test_mbmarshal.c index 967915688e..06798f6ade 100644 --- a/usr/src/cmd/smbsrv/test-msgbuf/test_mbmarshal.c +++ b/usr/src/cmd/smbsrv/test-msgbuf/test_mbmarshal.c @@ -10,7 +10,7 @@ */ /* - * Copyright 2018 Nexenta Systems, Inc. All rights reserved. + * Copyright 2019 Nexenta by DDN, Inc. All rights reserved. */ /* @@ -139,7 +139,7 @@ out: } static void -mbm_put_atrunc() +mbm_put_atrunc1() { uint8_t wire[] = { 'o', 'n', 'e', 't', }; mbuf_chain_t *mbc; @@ -150,23 +150,57 @@ mbm_put_atrunc() /* Encode with wire length < strlen */ rc = smb_mbc_encodef(mbc, "4s", "onetwo"); if (rc != 0) { - printf("Fail: mbm_put_atrunc encode\n"); + printf("Fail: mbm_put_atrunc1 encode\n"); goto out; } /* Trunc should put exactly 4 */ if (mbc->chain->m_len != 4) { - printf("Fail: mbm_put_atrunc len=%d\n", + printf("Fail: mbm_put_atrunc1 len=%d\n", mbc->chain->m_len); return; } if (memcmp(mbc->chain->m_data, wire, 4)) { - printf("Fail: mbm_put_atrunc cmp:\n"); + printf("Fail: mbm_put_atrunc1 cmp:\n"); hexdump((uchar_t *)mbc->chain->m_data, 4); return; } - printf("Pass: mbm_put_atrunc\n"); + printf("Pass: mbm_put_atrunc1\n"); + +out: + smb_mbc_free(mbc); +} + +static void +mbm_put_atrunc2() +{ + uint8_t wire[] = { 'o', 'n', 'e', 't', 0 }; + mbuf_chain_t *mbc; + int rc; + + mbc = smb_mbc_alloc(4); + + /* Encode with wire length < strlen */ + rc = smb_mbc_encodef(mbc, "s", "onetwo"); + if (rc != 1) { + printf("Fail: mbm_put_atrunc2 encode rc=%d\n", rc); + goto out; + } + /* Trunc should put exactly 4 */ + if (mbc->chain->m_len != 4) { + printf("Fail: mbm_put_atrunc2 len=%d\n", + mbc->chain->m_len); + return; + } + + if (memcmp(mbc->chain->m_data, wire, 5)) { + printf("Fail: mbm_put_atrunc2 cmp:\n"); + hexdump((uchar_t *)mbc->chain->m_data, 4); + return; + } + + printf("Pass: mbm_put_atrunc2\n"); out: smb_mbc_free(mbc); @@ -338,7 +372,7 @@ out: } static void -mbm_put_utrunc() +mbm_put_utrunc1() { uint16_t wire[] = { 'o', 'n', 'e', 't' }; mbuf_chain_t *mbc; @@ -349,23 +383,57 @@ mbm_put_utrunc() /* Encode with wire length < strlen */ rc = smb_mbc_encodef(mbc, "8U", "onetwo"); if (rc != 0) { - printf("Fail: mbm_put_utrunc encode\n"); + printf("Fail: mbm_put_utrunc1 encode\n"); goto out; } /* Trunc should put exactly 8 */ if (mbc->chain->m_len != 8) { - printf("Fail: mbm_put_utrunc len=%d\n", + printf("Fail: mbm_put_utrunc1 len=%d\n", mbc->chain->m_len); return; } if (memcmp(mbc->chain->m_data, wire, 8)) { - printf("Fail: mbm_put_utrunc cmp:\n"); + printf("Fail: mbm_put_utrunc1 cmp:\n"); + hexdump((uchar_t *)mbc->chain->m_data, 8); + return; + } + + printf("Pass: mbm_put_utrunc1\n"); + +out: + smb_mbc_free(mbc); +} + +static void +mbm_put_utrunc2() +{ + uint16_t wire[] = { 'o', 'n', 'e', 't', 0 }; + mbuf_chain_t *mbc; + int rc; + + mbc = smb_mbc_alloc(8); + + /* Encode with wire length < strlen */ + rc = smb_mbc_encodef(mbc, "U", "onetwo"); + if (rc != 1) { + printf("Fail: mbm_put_utrunc2 encode rc=%d\n", rc); + goto out; + } + /* Trunc should put exactly 8 */ + if (mbc->chain->m_len != 8) { + printf("Fail: mbm_put_utrunc2 len=%d\n", + mbc->chain->m_len); + return; + } + + if (memcmp(mbc->chain->m_data, wire, 10)) { + printf("Fail: mbm_put_utrunc2 cmp:\n"); hexdump((uchar_t *)mbc->chain->m_data, 8); return; } - printf("Pass: mbm_put_utrunc\n"); + printf("Pass: mbm_put_utrunc2\n"); out: smb_mbc_free(mbc); @@ -657,14 +725,16 @@ test_mbmarshal() mbm_put_a0(); mbm_put_a1(); mbm_put_apad(); - mbm_put_atrunc(); + mbm_put_atrunc1(); + mbm_put_atrunc2(); mbm_put_u0(); mbm_put_u1(); mbm_put_u3(); mbm_put_u4(); mbm_put_upad(); - mbm_put_utrunc(); + mbm_put_utrunc1(); + mbm_put_utrunc2(); mbm_get_a0(); mbm_get_a1(); diff --git a/usr/src/cmd/smbsrv/test-msgbuf/test_msgbuf.c b/usr/src/cmd/smbsrv/test-msgbuf/test_msgbuf.c index b58bd54b83..24bd62e8f1 100644 --- a/usr/src/cmd/smbsrv/test-msgbuf/test_msgbuf.c +++ b/usr/src/cmd/smbsrv/test-msgbuf/test_msgbuf.c @@ -10,7 +10,7 @@ */ /* - * Copyright 2018 Nexenta Systems, Inc. All rights reserved. + * Copyright 2019 Nexenta by DDN, Inc. All rights reserved. */ /* @@ -127,7 +127,7 @@ out: } static void -msg_put_atrunc() +msg_put_atrunc1() { uint8_t wire[] = { 'o', 'n', 'e', 't', }; uint8_t temp[32]; @@ -141,17 +141,49 @@ msg_put_atrunc() rc = smb_msgbuf_encode(&mb, "4s", "onetwo"); /* Trunc should put exactly 4 */ if (rc != 4) { - printf("Fail: msg_put_atrunc encode\n"); + printf("Fail: msg_put_atrunc1 encode\n"); goto out; } if (memcmp(temp, wire, 4)) { - printf("Fail: msg_put_atrunc cmp:\n"); + printf("Fail: msg_put_atrunc1 cmp:\n"); hexdump((uchar_t *)temp, 4); return; } - printf("Pass: msg_put_atrunc\n"); + printf("Pass: msg_put_atrunc1\n"); + +out: + smb_msgbuf_term(&mb); +} + +static void +msg_put_atrunc2() +{ + uint8_t wire[] = { 'o', 'n', 'e', 't', 0}; + uint8_t temp[32]; + smb_msgbuf_t mb; + int mbflags = 0; + int rc; + + (void) memset(temp, 0, sizeof (temp)); + smb_msgbuf_init(&mb, temp, 4, mbflags); + + /* Encode with wire length < strlen */ + rc = smb_msgbuf_encode(&mb, "s", "onetwo"); + /* Trunc should return "overflow" */ + if (rc != -1) { + printf("Fail: msg_put_atrunc2 encode rc=%d\n", rc); + goto out; + } + + if (memcmp(temp, wire, 5)) { + printf("Fail: msg_put_atrunc2 cmp:\n"); + hexdump((uchar_t *)temp, 5); + return; + } + + printf("Pass: msg_put_atrunc2\n"); out: smb_msgbuf_term(&mb); @@ -308,7 +340,7 @@ out: } static void -msg_put_utrunc() +msg_put_utrunc1() { uint16_t wire[] = { 'o', 'n', 'e', 't' }; uint8_t temp[32]; @@ -322,17 +354,49 @@ msg_put_utrunc() rc = smb_msgbuf_encode(&mb, "8U", "onetwo"); /* Trunc should put exactly 8 */ if (rc != 8) { - printf("Fail: msg_put_utrunc encode\n"); + printf("Fail: msg_put_utrunc1 encode\n"); goto out; } if (memcmp(temp, wire, 8)) { - printf("Fail: msg_put_utrunc cmp:\n"); + printf("Fail: msg_put_utrunc1 cmp:\n"); hexdump((uchar_t *)temp, 8); return; } - printf("Pass: msg_put_utrunc\n"); + printf("Pass: msg_put_utrunc1\n"); + +out: + smb_msgbuf_term(&mb); +} + +static void +msg_put_utrunc2() +{ + uint16_t wire[] = { 'o', 'n', 'e', 't', 0 }; + uint8_t temp[32]; + smb_msgbuf_t mb; + int mbflags = 0; + int rc; + + (void) memset(temp, 0, sizeof (temp)); + smb_msgbuf_init(&mb, temp, 8, mbflags); + + /* Encode with wire length < strlen */ + rc = smb_msgbuf_encode(&mb, "U", "onetwo"); + /* Trunc should return "overflow" */ + if (rc != -1) { + printf("Fail: msg_put_utrunc2 encode rc=%d\n", rc); + goto out; + } + + if (memcmp(temp, wire, 10)) { + printf("Fail: msg_put_utrunc2 cmp:\n"); + hexdump((uchar_t *)temp, 10); + return; + } + + printf("Pass: msg_put_utrunc2\n"); out: smb_msgbuf_term(&mb); @@ -617,14 +681,16 @@ test_msgbuf() msg_put_a0(); msg_put_a1(); msg_put_apad(); - msg_put_atrunc(); + msg_put_atrunc1(); + msg_put_atrunc2(); msg_put_u0(); msg_put_u1(); msg_put_u3(); msg_put_u4(); msg_put_upad(); - msg_put_utrunc(); + msg_put_utrunc1(); + msg_put_utrunc2(); msg_get_a0(); msg_get_a1(); diff --git a/usr/src/common/smbsrv/smb_msgbuf.c b/usr/src/common/smbsrv/smb_msgbuf.c index b11cd39a50..5a58a80f37 100644 --- a/usr/src/common/smbsrv/smb_msgbuf.c +++ b/usr/src/common/smbsrv/smb_msgbuf.c @@ -22,7 +22,7 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * - * Copyright 2018 Nexenta Systems, Inc. All rights reserved. + * Copyright 2019 Nexenta by DDN, Inc. All rights reserved. */ /* @@ -733,8 +733,6 @@ msgbuf_put_oem_string(smb_msgbuf_t *mb, char *mbs, int repc) if ((mb->flags & SMB_MSGBUF_NOTERM) == 0) repc += sizeof (char); } - if (smb_msgbuf_has_space(mb, repc) == 0) - return (SMB_MSGBUF_OVERFLOW); /* * Convert into a temporary buffer @@ -756,6 +754,8 @@ msgbuf_put_oem_string(smb_msgbuf_t *mb, char *mbs, int repc) */ s = oembuf; while (repc > 0) { + if (smb_msgbuf_has_space(mb, 1) == 0) + return (SMB_MSGBUF_OVERFLOW); *mb->scan++ = *s; if (*s != '\0') s++; @@ -777,6 +777,7 @@ msgbuf_put_unicode_string(smb_msgbuf_t *mb, char *mbs, int repc) { smb_wchar_t *wcsbuf = NULL; smb_wchar_t *wp; + smb_wchar_t wchar; size_t wcslen, wcsbytes; size_t rlen; @@ -800,8 +801,6 @@ msgbuf_put_unicode_string(smb_msgbuf_t *mb, char *mbs, int repc) if ((mb->flags & SMB_MSGBUF_NOTERM) == 0) repc += sizeof (smb_wchar_t); } - if (smb_msgbuf_has_space(mb, repc) == 0) - return (SMB_MSGBUF_OVERFLOW); /* * Convert into a temporary buffer @@ -824,16 +823,21 @@ msgbuf_put_unicode_string(smb_msgbuf_t *mb, char *mbs, int repc) * little-endian order while copying. */ wp = wcsbuf; - while (repc > 1) { - smb_wchar_t wchar = LE_IN16(wp); + while (repc >= sizeof (smb_wchar_t)) { + if (smb_msgbuf_has_space(mb, sizeof (smb_wchar_t)) == 0) + return (SMB_MSGBUF_OVERFLOW); + wchar = LE_IN16(wp); LE_OUT16(mb->scan, wchar); mb->scan += 2; if (wchar != 0) wp++; repc -= sizeof (smb_wchar_t); } - if (repc > 0) + if (repc > 0) { + if (smb_msgbuf_has_space(mb, 1) == 0) + return (SMB_MSGBUF_OVERFLOW); *mb->scan++ = '\0'; + } return (0); } diff --git a/usr/src/uts/common/fs/smbsrv/smb2_fsctl_fs.c b/usr/src/uts/common/fs/smbsrv/smb2_fsctl_fs.c index 829beda2e4..381fd7663e 100644 --- a/usr/src/uts/common/fs/smbsrv/smb2_fsctl_fs.c +++ b/usr/src/uts/common/fs/smbsrv/smb2_fsctl_fs.c @@ -10,7 +10,7 @@ */ /* - * Copyright 2018 Nexenta Systems, Inc. All rights reserved. + * Copyright 2019 Nexenta by DDN, Inc. All rights reserved. */ /* @@ -23,7 +23,16 @@ #include <smbsrv/smb_fsops.h> #include <smb/winioctl.h> -/* ARGSUSED */ +/* + * XXX: Should use smb2_fsctl_invalid in place of smb2_fsctl_notsup + * but that will require some re-testing. + */ +static uint32_t +smb2_fsctl_invalid(smb_request_t *sr, smb_fsctl_t *fsctl) +{ + return (NT_STATUS_INVALID_DEVICE_REQUEST); +} + static uint32_t smb2_fsctl_notsup(smb_request_t *sr, smb_fsctl_t *fsctl) { @@ -52,9 +61,12 @@ smb2_fsctl_get_compression(smb_request_t *sr, smb_fsctl_t *fsctl) { _NOTE(ARGUNUSED(sr)) uint16_t compress_state = 0; + int rc; - (void) smb_mbc_encodef(fsctl->in_mbc, "w", + rc = smb_mbc_encodef(fsctl->in_mbc, "w", compress_state); + if (rc != 0) + return (NT_STATUS_BUFFER_OVERFLOW); return (NT_STATUS_SUCCESS); } @@ -97,6 +109,7 @@ smb2_fsctl_get_resume_key(smb_request_t *sr, smb_fsctl_t *fsctl) { smb_ofile_t *of = sr->fid_ofile; smb2fid_t smb2fid; + int rc; /* Caller makes sure we have of = sr->fid_ofile */ /* Don't insist on a plain file (see above). */ @@ -104,10 +117,12 @@ smb2_fsctl_get_resume_key(smb_request_t *sr, smb_fsctl_t *fsctl) smb2fid.persistent = of->f_persistid; smb2fid.temporal = of->f_fid; - (void) smb_mbc_encodef( + rc = smb_mbc_encodef( fsctl->out_mbc, "qq16.", smb2fid.persistent, smb2fid.temporal); + if (rc != 0) + return (NT_STATUS_BUFFER_OVERFLOW); return (NT_STATUS_SUCCESS); } @@ -130,9 +145,11 @@ smb2_fsctl_fs(smb_request_t *sr, smb_fsctl_t *fsctl) break; case FSCTL_SET_REPARSE_POINT: /* 41 */ case FSCTL_GET_REPARSE_POINT: /* 42 */ - case FSCTL_CREATE_OR_GET_OBJECT_ID: /* 48 */ func = smb2_fsctl_notsup; break; + case FSCTL_CREATE_OR_GET_OBJECT_ID: /* 48 */ + func = smb2_fsctl_invalid; + break; case FSCTL_SET_SPARSE: /* 49 */ func = smb2_fsctl_set_sparse; break; diff --git a/usr/src/uts/common/fs/smbsrv/smb2_qinfo_file.c b/usr/src/uts/common/fs/smbsrv/smb2_qinfo_file.c index ab682b7966..929f02522b 100644 --- a/usr/src/uts/common/fs/smbsrv/smb2_qinfo_file.c +++ b/usr/src/uts/common/fs/smbsrv/smb2_qinfo_file.c @@ -10,7 +10,7 @@ */ /* - * Copyright 2015 Nexenta Systems, Inc. All rights reserved. + * Copyright 2019 Nexenta by DDN, Inc. All rights reserved. */ /* @@ -240,10 +240,11 @@ static uint32_t smb2_qif_basic(smb_request_t *sr, smb_queryinfo_t *qi) { smb_attr_t *sa = &qi->qi_attr; + int rc; ASSERT((sa->sa_mask & SMB_AT_BASIC) == SMB_AT_BASIC); - (void) smb_mbc_encodef( + rc = smb_mbc_encodef( &sr->raw_data, "TTTTll", &sa->sa_crtime, /* T */ &sa->sa_vattr.va_atime, /* T */ @@ -251,6 +252,8 @@ smb2_qif_basic(smb_request_t *sr, smb_queryinfo_t *qi) &sa->sa_vattr.va_ctime, /* T */ sa->sa_dosattr, /* l */ 0); /* reserved */ /* l */ + if (rc != 0) + return (NT_STATUS_BUFFER_OVERFLOW); return (0); } @@ -265,10 +268,11 @@ static uint32_t smb2_qif_standard(smb_request_t *sr, smb_queryinfo_t *qi) { smb_attr_t *sa = &qi->qi_attr; + int rc; ASSERT((sa->sa_mask & SMB_AT_STANDARD) == SMB_AT_STANDARD); - (void) smb_mbc_encodef( + rc = smb_mbc_encodef( &sr->raw_data, "qqlbbw", sa->sa_allocsz, /* q */ sa->sa_vattr.va_size, /* q */ @@ -276,6 +280,8 @@ smb2_qif_standard(smb_request_t *sr, smb_queryinfo_t *qi) qi->qi_delete_on_close, /* b */ qi->qi_isdir, /* b */ 0); /* reserved */ /* w */ + if (rc != 0) + return (NT_STATUS_BUFFER_OVERFLOW); return (0); } @@ -290,6 +296,7 @@ smb2_qif_internal(smb_request_t *sr, smb_queryinfo_t *qi) { smb_attr_t *sa = &qi->qi_attr; u_longlong_t nodeid; + int rc; ASSERT((sa->sa_mask & SMB_AT_NODEID) == SMB_AT_NODEID); nodeid = sa->sa_vattr.va_nodeid; @@ -298,9 +305,11 @@ smb2_qif_internal(smb_request_t *sr, smb_queryinfo_t *qi) (sr->session->s_flags & SMB_SSN_AAPL_CCEXT) != 0) nodeid = 0; - (void) smb_mbc_encodef( + rc = smb_mbc_encodef( &sr->raw_data, "q", nodeid); /* q */ + if (rc != 0) + return (NT_STATUS_BUFFER_OVERFLOW); return (0); } @@ -315,9 +324,12 @@ static uint32_t smb2_qif_ea_size(smb_request_t *sr, smb_queryinfo_t *qi) { _NOTE(ARGUNUSED(qi)) + int rc; - (void) smb_mbc_encodef( + rc = smb_mbc_encodef( &sr->raw_data, "l", 0); + if (rc != 0) + return (NT_STATUS_BUFFER_OVERFLOW); return (0); } @@ -341,10 +353,13 @@ smb2_qif_access(smb_request_t *sr, smb_queryinfo_t *qi) { _NOTE(ARGUNUSED(qi)) smb_ofile_t *of = sr->fid_ofile; + int rc; - (void) smb_mbc_encodef( + rc = smb_mbc_encodef( &sr->raw_data, "l", of->f_granted_access); + if (rc != 0) + return (NT_STATUS_BUFFER_OVERFLOW); return (0); } @@ -358,14 +373,17 @@ smb2_qif_access(smb_request_t *sr, smb_queryinfo_t *qi) static uint32_t smb2_qif_name(smb_request_t *sr, smb_queryinfo_t *qi) { + int rc; ASSERT(qi->qi_namelen > 0); - (void) smb_mbc_encodef( + rc = smb_mbc_encodef( &sr->raw_data, "llU", 0, /* FileIndex (l) */ qi->qi_namelen, /* l */ qi->qi_name); /* U */ + if (rc != 0) + return (NT_STATUS_BUFFER_OVERFLOW); return (0); } @@ -379,13 +397,16 @@ smb2_qif_position(smb_request_t *sr, smb_queryinfo_t *qi) _NOTE(ARGUNUSED(qi)) smb_ofile_t *of = sr->fid_ofile; uint64_t pos; + int rc; mutex_enter(&of->f_mutex); pos = of->f_seek_pos; mutex_exit(&of->f_mutex); - (void) smb_mbc_encodef( + rc = smb_mbc_encodef( &sr->raw_data, "q", pos); + if (rc != 0) + return (NT_STATUS_BUFFER_OVERFLOW); return (0); } @@ -399,9 +420,12 @@ static uint32_t smb2_qif_mode(smb_request_t *sr, smb_queryinfo_t *qi) { _NOTE(ARGUNUSED(qi)) + int rc; - (void) smb_mbc_encodef( + rc = smb_mbc_encodef( &sr->raw_data, "l", 0); + if (rc != 0) + return (NT_STATUS_BUFFER_OVERFLOW); return (0); } @@ -413,9 +437,12 @@ static uint32_t smb2_qif_alignment(smb_request_t *sr, smb_queryinfo_t *qi) { _NOTE(ARGUNUSED(qi)) + int rc; - (void) smb_mbc_encodef( + rc = smb_mbc_encodef( &sr->raw_data, "l", 0); + if (rc != 0) + return (NT_STATUS_BUFFER_OVERFLOW); return (0); } @@ -430,6 +457,7 @@ static uint32_t smb2_qif_altname(smb_request_t *sr, smb_queryinfo_t *qi) { smb_ofile_t *of = sr->fid_ofile; + int rc; ASSERT(qi->qi_namelen > 0); ASSERT(qi->qi_attr.sa_mask & SMB_AT_NODEID); @@ -442,10 +470,12 @@ smb2_qif_altname(smb_request_t *sr, smb_queryinfo_t *qi) /* fill in qi->qi_shortname */ smb_query_shortname(of->f_node, qi); - (void) smb_mbc_encodef( + rc = smb_mbc_encodef( &sr->raw_data, "%lU", sr, smb_wcequiv_strlen(qi->qi_shortname), qi->qi_shortname); + if (rc != 0) + return (NT_STATUS_BUFFER_OVERFLOW); return (0); } @@ -481,6 +511,7 @@ smb2_qif_pipe(smb_request_t *sr, smb_queryinfo_t *qi) smb_ofile_t *of = sr->fid_ofile; uint32_t pipe_mode; uint32_t nonblock; + int rc; switch (of->f_ftype) { case SMB_FTYPE_BYTE_PIPE: @@ -496,9 +527,11 @@ smb2_qif_pipe(smb_request_t *sr, smb_queryinfo_t *qi) } nonblock = 0; /* XXX todo: Get this from the pipe handle. */ - (void) smb_mbc_encodef( + rc = smb_mbc_encodef( &sr->raw_data, "ll", pipe_mode, nonblock); + if (rc != 0) + return (NT_STATUS_BUFFER_OVERFLOW); return (0); } @@ -532,13 +565,16 @@ smb2_qif_compr(smb_request_t *sr, smb_queryinfo_t *qi) { smb_attr_t *sa = &qi->qi_attr; uint16_t CompressionFormat = 0; /* COMPRESSION_FORMAT_NONE */ + int rc; ASSERT(sa->sa_mask & SMB_AT_SIZE); - (void) smb_mbc_encodef( + rc = smb_mbc_encodef( &sr->raw_data, "qw6.", sa->sa_vattr.va_size, /* q */ CompressionFormat); /* w */ + if (rc != 0) + return (NT_STATUS_BUFFER_OVERFLOW); return (0); } @@ -550,8 +586,9 @@ static uint32_t smb2_qif_opens(smb_request_t *sr, smb_queryinfo_t *qi) { smb_attr_t *sa = &qi->qi_attr; + int rc; - (void) smb_mbc_encodef( + rc = smb_mbc_encodef( &sr->raw_data, "TTTTqqll", &sa->sa_crtime, /* T */ &sa->sa_vattr.va_atime, /* T */ @@ -561,6 +598,8 @@ smb2_qif_opens(smb_request_t *sr, smb_queryinfo_t *qi) sa->sa_vattr.va_size, /* q */ sa->sa_dosattr, /* l */ 0); /* reserved */ /* l */ + if (rc != 0) + return (NT_STATUS_BUFFER_OVERFLOW); return (0); } @@ -578,8 +617,12 @@ static uint32_t smb2_qif_tags(smb_request_t *sr, smb_queryinfo_t *qi) { _NOTE(ARGUNUSED(qi)) - (void) smb_mbc_encodef( + int rc; + + rc = smb_mbc_encodef( &sr->raw_data, "ll", 0, 0); + if (rc != 0) + return (NT_STATUS_BUFFER_OVERFLOW); return (0); } diff --git a/usr/src/uts/common/fs/smbsrv/smb2_qinfo_fs.c b/usr/src/uts/common/fs/smbsrv/smb2_qinfo_fs.c index 856a59e939..7bf3d1339e 100644 --- a/usr/src/uts/common/fs/smbsrv/smb2_qinfo_fs.c +++ b/usr/src/uts/common/fs/smbsrv/smb2_qinfo_fs.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + * Copyright 2019 Nexenta by DDN, Inc. All rights reserved. */ /* @@ -100,6 +100,7 @@ smb2_qfs_volume(smb_request_t *sr) smb_node_t *snode; fsid_t fsid; uint32_t LabelLength; + int rc; if (!STYPE_ISDSK(tree->t_res_type)) return (NT_STATUS_INVALID_PARAMETER); @@ -112,14 +113,16 @@ smb2_qfs_volume(smb_request_t *sr) /* * NT has the "supports objects" flag set to 1. */ - (void) smb_mbc_encodef( - &sr->raw_data, "qllb.U", - 0LL, /* Volume creation time (q) */ + rc = smb_mbc_encodef( + &sr->raw_data, "Tllb.U", + &tree->t_create_time, /* (T) */ fsid.val[0], /* serial no. (l) */ LabelLength, /* (l) */ 0, /* Supports objects (b) */ /* reserved (.) */ tree->t_volume); /* (U) */ + if (rc != 0) + return (NT_STATUS_BUFFER_OVERFLOW); return (0); } @@ -141,12 +144,14 @@ smb2_qfs_size(smb_request_t *sr) if (rc) return (smb_errno2status(rc)); - (void) smb_mbc_encodef( + rc = smb_mbc_encodef( &sr->raw_data, "qqll", fssize.fs_caller_units, fssize.fs_caller_avail, fssize.fs_sectors_per_unit, fssize.fs_bytes_per_sector); + if (rc != 0) + return (NT_STATUS_BUFFER_OVERFLOW); return (0); } @@ -168,13 +173,15 @@ smb2_qfs_fullsize(smb_request_t *sr) if (rc) return (smb_errno2status(rc)); - (void) smb_mbc_encodef( + rc = smb_mbc_encodef( &sr->raw_data, "qqqll", fssize.fs_caller_units, fssize.fs_caller_avail, fssize.fs_volume_avail, fssize.fs_sectors_per_unit, fssize.fs_bytes_per_sector); + if (rc != 0) + return (NT_STATUS_BUFFER_OVERFLOW); return (0); } @@ -188,6 +195,7 @@ smb2_qfs_device(smb_request_t *sr) smb_tree_t *tree = sr->tid_tree; uint32_t DeviceType; uint32_t Characteristics; + int rc; if (!STYPE_ISDSK(tree->t_res_type)) return (NT_STATUS_INVALID_PARAMETER); @@ -195,10 +203,12 @@ smb2_qfs_device(smb_request_t *sr) DeviceType = FILE_DEVICE_DISK; Characteristics = FILE_DEVICE_IS_MOUNTED; - (void) smb_mbc_encodef( + rc = smb_mbc_encodef( &sr->raw_data, "ll", DeviceType, Characteristics); + if (rc != 0) + return (NT_STATUS_BUFFER_OVERFLOW); return (0); } @@ -213,6 +223,7 @@ smb2_qfs_attr(smb_request_t *sr) char *fsname; uint32_t namelen; uint32_t FsAttr; + int rc; /* This call is OK on all tree types. */ switch (tree->t_res_type & STYPE_MASK) { @@ -247,12 +258,14 @@ smb2_qfs_attr(smb_request_t *sr) if (tree->t_flags & SMB_TREE_SPARSE) FsAttr |= FILE_SUPPORTS_SPARSE_FILES; - (void) smb_mbc_encodef( + rc = smb_mbc_encodef( &sr->raw_data, "lllU", FsAttr, MAXNAMELEN-1, namelen, fsname); + if (rc != 0) + return (NT_STATUS_BUFFER_OVERFLOW); return (0); } @@ -264,6 +277,7 @@ uint32_t smb2_qfs_control(smb_request_t *sr) { smb_tree_t *tree = sr->tid_tree; + int rc; if (!STYPE_ISDSK(tree->t_res_type)) return (NT_STATUS_INVALID_PARAMETER); @@ -275,7 +289,7 @@ smb2_qfs_control(smb_request_t *sr) return (NT_STATUS_VOLUME_NOT_UPGRADED); } - (void) smb_mbc_encodef( + rc = smb_mbc_encodef( &sr->raw_data, "qqqqqll", 0, /* free space start filtering - MUST be 0 */ 0, /* free space threshold - MUST be 0 */ @@ -284,6 +298,8 @@ smb2_qfs_control(smb_request_t *sr) SMB_QUOTA_UNLIMITED, /* default quota limit */ FILE_VC_QUOTA_ENFORCE, /* fs control flag */ 0); /* pad bytes */ + if (rc != 0) + return (NT_STATUS_BUFFER_OVERFLOW); return (0); } @@ -364,7 +380,7 @@ smb2_qfs_sectorsize(smb_request_t *sr) smb_fssize_t fssize; smb_tree_t *tree = sr->tid_tree; uint32_t lbps, pbps; - uint32_t flags; + uint32_t flags, unk; int rc; if (!STYPE_ISDSK(tree->t_res_type)) @@ -373,24 +389,15 @@ smb2_qfs_sectorsize(smb_request_t *sr) rc = smb_fssize(sr, &fssize); if (rc) return (smb_errno2status(rc)); + + // PhysicalBytesPerSector pbps = fssize.fs_bytes_per_sector; + + // LogicalBytesPerSector lbps = fssize.fs_sectors_per_unit * pbps; if (lbps > smb2_max_logical_sector_size) lbps = smb2_max_logical_sector_size; - // LogicalBytesPerSector - (void) smb_mbc_encodef(&sr->raw_data, "l", lbps); - - // PhysicalBytesPerSectorForAtomicity - (void) smb_mbc_encodef(&sr->raw_data, "l", pbps); - - // PhysicalBytesPerSectorForPerformance - // Using logical size here. - (void) smb_mbc_encodef(&sr->raw_data, "l", lbps); - - // FileSystemEffectivePhysicalBytesPerSectorForAtomicity - (void) smb_mbc_encodef(&sr->raw_data, "l", pbps); - // Flags // We include "no seek penalty" because our files are // always ZFS-backed, which can reorder things on disk. @@ -398,15 +405,24 @@ smb2_qfs_sectorsize(smb_request_t *sr) flags = SSINFO_FLAGS_ALIGNED_DEVICE | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE | SSINFO_FLAGS_NO_SEEK_PENALTY; - (void) smb_mbc_encodef(&sr->raw_data, "l", flags); // ByteOffsetForSectorAlignment // ByteOffsetForPartitionAlignment // Just say "unknown" for these two. - (void) smb_mbc_encodef( - &sr->raw_data, "l", - SSINFO_OFFSET_UNKNOWN, - SSINFO_OFFSET_UNKNOWN); + unk = SSINFO_OFFSET_UNKNOWN; + + rc = smb_mbc_encodef( + &sr->raw_data, + "lllllll", + lbps, // LogicalBytesPerSector + pbps, // PhysicalBytesPerSectorForAtomicity + lbps, // PhysicalBytesPerSectorForPerformance + pbps, // FileSystemEffectivePhysicalBytesPerSectorForAtomicity + flags, + unk, unk); + + if (rc != 0) + return (NT_STATUS_BUFFER_OVERFLOW); return (0); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_mbuf_marshaling.c b/usr/src/uts/common/fs/smbsrv/smb_mbuf_marshaling.c index 132820a147..1476850683 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_mbuf_marshaling.c +++ b/usr/src/uts/common/fs/smbsrv/smb_mbuf_marshaling.c @@ -22,7 +22,7 @@ * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * - * Copyright 2018 Nexenta Systems, Inc. All rights reserved. + * Copyright 2019 Nexenta by DDN, Inc. All rights reserved. */ /* @@ -800,7 +800,7 @@ smb_mbc_poke(mbuf_chain_t *mbc, int offset, const char *fmt, ...) */ int smb_mbc_copy(mbuf_chain_t *dst_mbc, const mbuf_chain_t *src_mbc, - int copy_offset, int copy_len) + int copy_offset, int copy_len) { mbuf_t *src_m; int offset, len; @@ -1109,8 +1109,6 @@ mbc_marshal_put_oem_string(mbuf_chain_t *mbc, char *mbs, int repc) */ if (repc <= 0) repc = oemlen + 1; - if (mbc_marshal_make_room(mbc, repc)) - return (DECODE_NO_MORE_DATA); /* * Convert into a temporary buffer @@ -1133,6 +1131,10 @@ mbc_marshal_put_oem_string(mbuf_chain_t *mbc, char *mbs, int repc) */ s = oembuf; while (repc > 0) { + if (mbc_marshal_make_room(mbc, 1)) { + rc = DECODE_NO_MORE_DATA; + goto out; + } mbc_marshal_store_byte(mbc, *s); if (*s != '\0') s++; @@ -1158,6 +1160,7 @@ mbc_marshal_put_unicode_string(mbuf_chain_t *mbc, char *mbs, int repc) { smb_wchar_t *wcsbuf = NULL; smb_wchar_t *wp; + smb_wchar_t wchar; size_t wcslen, wcsbytes; size_t rlen; int rc; @@ -1183,8 +1186,6 @@ mbc_marshal_put_unicode_string(mbuf_chain_t *mbc, char *mbs, int repc) */ if (repc <= 0) repc = wcsbytes + 2; - if (mbc_marshal_make_room(mbc, repc)) - return (DECODE_NO_MORE_DATA); /* * Convert into a temporary buffer @@ -1208,18 +1209,27 @@ mbc_marshal_put_unicode_string(mbuf_chain_t *mbc, char *mbs, int repc) * little-endian order while copying. */ wp = wcsbuf; - while (repc > 1) { - smb_wchar_t wchar = LE_IN16(wp); + while (repc >= sizeof (smb_wchar_t)) { + if (mbc_marshal_make_room(mbc, sizeof (smb_wchar_t))) { + rc = DECODE_NO_MORE_DATA; + goto out; + } + wchar = LE_IN16(wp); mbc_marshal_store_byte(mbc, wchar); mbc_marshal_store_byte(mbc, wchar >> 8); if (wchar != 0) wp++; repc -= sizeof (smb_wchar_t); } - if (repc > 0) + if (repc > 0) { + if (mbc_marshal_make_room(mbc, 1)) { + rc = DECODE_NO_MORE_DATA; + goto out; + } mbc_marshal_store_byte(mbc, 0); - + } rc = 0; + out: if (wcsbuf != NULL) smb_mem_free(wcsbuf); diff --git a/usr/src/uts/common/fs/smbsrv/smb_tree.c b/usr/src/uts/common/fs/smbsrv/smb_tree.c index aedacf2123..639747962e 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_tree.c +++ b/usr/src/uts/common/fs/smbsrv/smb_tree.c @@ -21,8 +21,8 @@ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2018 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2016 by Delphix. All rights reserved. + * Copyright 2019 Nexenta by DDN, Inc. All rights reserved. */ /* @@ -188,6 +188,7 @@ static void smb_tree_dealloc(void *); static boolean_t smb_tree_is_connected_locked(smb_tree_t *); static char *smb_tree_get_sharename(char *); static int smb_tree_getattr(const smb_kshare_t *, smb_node_t *, smb_tree_t *); +static void smb_tree_get_creation(smb_node_t *, smb_tree_t *); static void smb_tree_get_volname(vfs_t *, smb_tree_t *); static void smb_tree_get_flags(const smb_kshare_t *, vfs_t *, smb_tree_t *); static void smb_tree_log(smb_request_t *, const char *, const char *, ...); @@ -1106,6 +1107,7 @@ smb_tree_getattr(const smb_kshare_t *si, smb_node_t *node, smb_tree_t *tree) if (getvfs(&vfsp->vfs_fsid) != vfsp) return (ESTALE); + smb_tree_get_creation(node, tree); smb_tree_get_volname(vfsp, tree); smb_tree_get_flags(si, vfsp, tree); @@ -1127,6 +1129,23 @@ smb_tree_getattr(const smb_kshare_t *si, smb_node_t *node, smb_tree_t *tree) } /* + * File volume creation time + */ +static void +smb_tree_get_creation(smb_node_t *node, smb_tree_t *tree) +{ + smb_attr_t attr; + cred_t *kcr = zone_kcred(); + + bzero(&attr, sizeof (attr)); + attr.sa_mask = SMB_AT_CRTIME; + (void) smb_node_getattr(NULL, node, kcr, NULL, &attr); + /* On failure we'll have time zero, which is OK */ + + tree->t_create_time = attr.sa_crtime; +} + +/* * Extract the volume name. */ static void diff --git a/usr/src/uts/common/smbsrv/smb_ktypes.h b/usr/src/uts/common/smbsrv/smb_ktypes.h index 0a84506726..1b596dbb9f 100644 --- a/usr/src/uts/common/smbsrv/smb_ktypes.h +++ b/usr/src/uts/common/smbsrv/smb_ktypes.h @@ -1170,6 +1170,7 @@ typedef struct smb_tree { time_t t_connect_time; volatile uint32_t t_open_files; smb_cfg_val_t t_encrypt; /* Share.EncryptData */ + timestruc_t t_create_time; } smb_tree_t; #define SMB_TREE_VFS(tree) ((tree)->t_snode->vp->v_vfsp) |