summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGordon Ross <gwr@nexenta.com>2019-11-22 23:39:36 -0500
committerGordon Ross <gordon.ross@tintri.com>2021-02-27 13:33:24 -0500
commit25a9a7aaf35c7e4a2b5a57d3875af906147710d5 (patch)
tree32d4dabef674b6ff39dbd02891b5aedb90c803b3
parent4d00d81bf82141f996e032f9c53e0e996a5f7204 (diff)
downloadillumos-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.c96
-rw-r--r--usr/src/cmd/smbsrv/test-msgbuf/test_msgbuf.c88
-rw-r--r--usr/src/common/smbsrv/smb_msgbuf.c20
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb2_fsctl_fs.c27
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb2_qinfo_file.c73
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb2_qinfo_fs.c72
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_mbuf_marshaling.c30
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_tree.c21
-rw-r--r--usr/src/uts/common/smbsrv/smb_ktypes.h1
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)