Print this page
NEX-14666 Need to provide SMB 2.1 Client
NEX-17187 panic in smbfs_acl_store
NEX-17231 smbfs create xattr files finds wrong file
NEX-17224 smbfs lookup EINVAL should be ENOENT
NEX-17260 SMB1 client fails to list directory after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
and: (cleanup)
NEX-1643 dtrace provider for smbsrv
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-5844 want SMB2 ioctl FSCTL_SRV_COPYCHUNK
NEX-6124 smb_fsop_read/write should allow file != sr->fid_ofile
NEX-6125 smbtorture invalid response with smb2.ioctl
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-3553 SMB2/3 durable handles
Reviewed by: Gordon Ross <gwr@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-5598 SMB needs a few more ioctls for Hyper-V
Reviewed by: Gordon Ross <gwr@nexenta.com>
NEX-4159 SMB2 fsctl validate negotiate error
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
NEX-2188 Browsing top level share produces RPC error 1728
SMB-136 Snapshots not visible in Windows previous versions
NEX-1059 Shared folder is not available in Windows 7/8/2012 when SMB2 is enabled in Workgroup mode
(Implement "Secure Negotiation")
SMB-122 smbd core dumps in smbd_dc_update / smb_log
SMB-117 Win7 fails to open security properties
SMB-110 panic mapping a share from Nexentastor to the windows 2012 R2 client
SMB-109 Codenomicon: SMB TC: 409480 - Panic with SMB2_FIND request
SMB-11 SMB2 message parse & dispatch
SMB-12 SMB2 Negotiate Protocol
SMB-13 SMB2 Session Setup
SMB-14 SMB2 Logoff
SMB-15 SMB2 Tree Connect
SMB-16 SMB2 Tree Disconnect
SMB-17 SMB2 Create
SMB-18 SMB2 Close
SMB-19 SMB2 Flush
SMB-20 SMB2 Read
SMB-21 SMB2 Write
SMB-22 SMB2 Lock/Unlock
SMB-23 SMB2 Ioctl
SMB-24 SMB2 Cancel
SMB-25 SMB2 Echo
SMB-26 SMB2 Query Dir
SMB-27 SMB2 Change Notify
SMB-28 SMB2 Query Info
SMB-29 SMB2 Set Info
SMB-30 SMB2 Oplocks
SMB-53 SMB2 Create Context options
(SMB2 code review cleanup 1, 2, 3)
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/fs/smbsrv/smb2_ioctl.c
+++ new/usr/src/uts/common/fs/smbsrv/smb2_ioctl.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 *
25 - * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
25 + * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
26 26 */
27 27
28 28 /*
29 29 * Dispatch function for SMB2_IOCTL
30 30 * [MS-SMB2] 3.3.5.15
31 31 */
32 32
33 33 #include <smbsrv/smb2_kproto.h>
34 -#include <smbsrv/winioctl.h>
34 +#include <smb/winioctl.h>
35 35
36 -struct smb2_ioctbl_ent {
37 - uint32_t te_code;
38 - uint32_t te_flags;
39 - uint32_t (*te_func)(smb_request_t *, smb_fsctl_t *);
40 -};
41 -static struct smb2_ioctbl_ent smb2_ioc_tbl[];
42 -
43 -/* te_flags */
44 -#define ITF_IPC_ONLY 1
45 -#define ITF_NO_FID 2
46 -#define ITF_DISK_FID 4
47 -
48 36 smb_sdrc_t
49 37 smb2_ioctl(smb_request_t *sr)
50 38 {
51 39 smb2fid_t smb2fid;
52 40 smb_fsctl_t fsctl;
53 41 mbuf_chain_t in_mbc;
54 - struct smb2_ioctbl_ent *te;
55 42 uint32_t InputOffset;
56 43 uint32_t MaxInputResp;
57 44 uint32_t OutputOffset;
58 45 uint32_t Flags;
59 - uint32_t status;
60 46 uint16_t StructSize;
47 + uint16_t DeviceType;
48 + uint32_t status = 0;
61 49 int rc = 0;
62 50
51 + /* Todo: put fsctl in sr->arg.ioctl (visible in dtrace probes) */
63 52 bzero(&in_mbc, sizeof (in_mbc));
64 53
65 54 /*
66 - * SMB2 Ioctl request
55 + * Decode SMB2 Ioctl request
67 56 */
68 57 rc = smb_mbc_decodef(
69 58 &sr->smb_data, "w..lqqlllllll4.",
70 59 &StructSize, /* w */
71 60 /* reserved .. */
72 61 &fsctl.CtlCode, /* l */
73 62 &smb2fid.persistent, /* q */
74 63 &smb2fid.temporal, /* q */
75 64 &InputOffset, /* l */
76 65 &fsctl.InputCount, /* l */
77 66 &MaxInputResp, /* l */
78 67 &OutputOffset, /* l */
79 68 &fsctl.OutputCount, /* l */
80 69 &fsctl.MaxOutputResp, /* l */
81 70 &Flags); /* l */
82 71 /* reserved2 4. */
83 72 if (rc || StructSize != 57)
84 73 return (SDRC_ERROR);
85 74
86 - if (Flags != SMB2_0_IOCTL_IS_FSCTL) {
87 - status = NT_STATUS_NOT_SUPPORTED;
88 - goto errout;
75 + /*
76 + * If there's an input buffer, setup a shadow.
77 + */
78 + if (fsctl.InputCount) {
79 + if (InputOffset < (SMB2_HDR_SIZE + 56))
80 + return (SDRC_ERROR);
81 + if (fsctl.InputCount > smb2_max_trans)
82 + return (SDRC_ERROR);
83 + rc = MBC_SHADOW_CHAIN(&in_mbc, &sr->smb_data,
84 + sr->smb2_cmd_hdr + InputOffset, fsctl.InputCount);
85 + if (rc) {
86 + return (SDRC_ERROR);
87 + }
89 88 }
89 + fsctl.in_mbc = &in_mbc;
90 90
91 - for (te = smb2_ioc_tbl; te->te_code; te++) {
92 - if (te->te_code == fsctl.CtlCode)
93 - break;
94 - }
95 - if (te->te_code == 0) {
96 -#ifdef DEBUG
97 - cmn_err(CE_NOTE, "smb2_ioctl: unknown code 0x%x",
98 - fsctl.CtlCode);
99 -#endif
100 - status = NT_STATUS_NOT_SUPPORTED;
101 - goto errout;
102 - }
103 -
104 91 /*
105 - * Some requests are only valid on IPC$
92 + * If output is possible, setup the output mbuf_chain
106 93 */
107 - if ((te->te_flags & ITF_IPC_ONLY) != 0 &&
108 - !STYPE_ISIPC(sr->tid_tree->t_res_type)) {
109 - status = NT_STATUS_INVALID_DEVICE_REQUEST;
110 - goto errout;
111 - }
94 + if (fsctl.MaxOutputResp > smb2_max_trans)
95 + fsctl.MaxOutputResp = smb2_max_trans;
96 + sr->raw_data.max_bytes = fsctl.MaxOutputResp;
97 + fsctl.out_mbc = &sr->raw_data;
112 98
113 99 /*
114 - * Note: some ioctl commands don't need a FID.
100 + * [MS-SMB2] 3.3.5.15
101 + *
102 + * If the Flags field of the request is not SMB2_0_IOCTL_IS_FSCTL
103 + * the server MUST fail the request with STATUS_NOT_SUPPORTED.
104 + *
105 + * If the CtlCode is any of (... see switch below...) and the
106 + * value of FileId in the SMB2 Header of the request is not
107 + * 0xFFFFFFFFFFFFFFFF, then the server MUST fail the request
108 + * with STATUS_INVALID_PARAMETER. (Otherwise lookup the FID.)
115 109 */
116 - if (te->te_flags & ITF_NO_FID) {
117 - if (smb2fid.temporal != ~0LL) {
110 + if (Flags != SMB2_0_IOCTL_IS_FSCTL) {
111 + status = NT_STATUS_NOT_SUPPORTED;
112 + } else switch (fsctl.CtlCode) {
113 + case FSCTL_DFS_GET_REFERRALS:
114 + case FSCTL_DFS_GET_REFERRALS_EX:
115 + case FSCTL_QUERY_NETWORK_INTERFACE_INFO:
116 + case FSCTL_VALIDATE_NEGOTIATE_INFO:
117 + case FSCTL_PIPE_WAIT:
118 + if (smb2fid.temporal != ~0LL ||
119 + smb2fid.persistent != ~0LL) {
118 120 status = NT_STATUS_INVALID_PARAMETER;
119 - goto errout;
120 121 }
121 - } else {
122 + break;
123 + default:
122 124 status = smb2sr_lookup_fid(sr, &smb2fid);
123 125 if (status) {
124 126 status = NT_STATUS_FILE_CLOSED;
125 - goto errout;
126 127 }
128 + break;
127 129 }
128 130
129 131 /*
130 - * Note: some ioctls require a "disk" fid.
132 + * Keep FID lookup before the start probe.
131 133 */
132 - if (te->te_flags & ITF_DISK_FID) {
133 - if (sr->fid_ofile == NULL ||
134 - !SMB_FTYPE_IS_DISK(sr->fid_ofile->f_ftype)) {
135 - status = NT_STATUS_INVALID_PARAMETER;
136 - goto errout;
137 - }
138 - }
134 + DTRACE_SMB2_START(op__Ioctl, smb_request_t *, sr);
139 135
136 + if (status)
137 + goto errout;
138 +
140 139 /*
141 - * If there's an input buffer, setup a shadow.
140 + * Dispatch to the handler for CtlCode
141 + * See CTL_CODE() in winioctl.h
142 142 */
143 - if (fsctl.InputCount) {
144 - if (InputOffset < (SMB2_HDR_SIZE + 56)) {
145 - status = NT_STATUS_INVALID_PARAMETER;
146 - goto errout;
147 - }
148 - rc = MBC_SHADOW_CHAIN(&in_mbc, &sr->smb_data,
149 - sr->smb2_cmd_hdr + InputOffset, fsctl.InputCount);
150 - if (rc) {
151 - status = NT_STATUS_INVALID_PARAMETER;
152 - goto errout;
153 - }
143 + DeviceType = fsctl.CtlCode >> 16;
144 + switch (DeviceType) {
145 + case FILE_DEVICE_DFS: /* 6 */
146 + status = smb_dfs_fsctl(sr, &fsctl);
147 + break;
148 + case FILE_DEVICE_FILE_SYSTEM: /* 9 */
149 + status = smb2_fsctl_fs(sr, &fsctl);
150 + break;
151 + case FILE_DEVICE_NAMED_PIPE: /* 17 */
152 + status = smb_opipe_fsctl(sr, &fsctl);
153 + break;
154 + case FILE_DEVICE_NETWORK_FILE_SYSTEM: /* 20 */
155 + status = smb2_fsctl_netfs(sr, &fsctl);
156 + break;
157 + default:
158 + status = NT_STATUS_NOT_SUPPORTED;
159 + break;
154 160 }
155 - fsctl.in_mbc = &in_mbc;
156 161
157 - /*
158 - * If output is possible, setup the output mbuf_chain
159 - */
160 - if (fsctl.MaxOutputResp > smb2_max_trans)
161 - fsctl.MaxOutputResp = smb2_max_trans;
162 - sr->raw_data.max_bytes = fsctl.MaxOutputResp;
163 - fsctl.out_mbc = &sr->raw_data;
162 +errout:
163 + sr->smb2_status = status;
164 + DTRACE_SMB2_DONE(op__Ioctl, smb_request_t *, sr);
164 165
165 - /*
166 - * Dispatch to the handler for CtlCode
167 - */
168 - status = (te->te_func)(sr, &fsctl);
169 166 if (status != 0) {
170 - sr->smb2_status = status;
171 - if (NT_SC_SEVERITY(status) == NT_STATUS_SEVERITY_ERROR)
172 - goto errout;
173 - /* Warnings like NT_STATUS_BUFFER_OVERFLOW are OK. */
167 + /*
168 + * NT status codes with severity "error" normally cause
169 + * an error response with no data. However, there are
170 + * exceptions like smb2_fsctl_copychunk that may return
171 + * severity==error _with_ a data part.
172 + */
173 + if ((NT_SC_SEVERITY(status) == NT_STATUS_SEVERITY_ERROR) &&
174 + (fsctl.CtlCode != FSCTL_SRV_COPYCHUNK) &&
175 + (fsctl.CtlCode != FSCTL_SRV_COPYCHUNK_WRITE)) {
176 + /* no error data */
177 + smb2sr_put_error(sr, status);
178 + return (SDRC_SUCCESS);
179 + }
180 + /* Else, error response _with_ data. */
174 181 }
175 182
176 183 fsctl.InputCount = 0;
177 184 InputOffset = SMB2_HDR_SIZE + 48;
178 185
179 186 fsctl.OutputCount = MBC_LENGTH(&sr->raw_data);
180 187 OutputOffset = (fsctl.OutputCount) ? InputOffset : 0;
181 188
182 189 /*
183 - * SMB2 Ioctl reply
190 + * Encode SMB2 Ioctl reply
184 191 */
185 192 StructSize = 49;
186 193 rc = smb_mbc_encodef(
187 194 &sr->reply, "w..lqqlllll4.#C",
188 195 StructSize, /* w */
189 196 /* reserved .. */
190 197 fsctl.CtlCode, /* l */
191 198 smb2fid.persistent, /* q */
192 199 smb2fid.temporal, /* q */
193 200 InputOffset, /* l */
194 201 fsctl.InputCount, /* l */
195 202 OutputOffset, /* l */
196 203 fsctl.OutputCount, /* l */
197 - Flags, /* l */
204 + 0, /* Flags l */
198 205 /* reserved2 4. */
199 206 fsctl.OutputCount, /* # */
200 207 &sr->raw_data); /* C */
201 - return ((rc) ? SDRC_ERROR : SDRC_SUCCESS);
208 + if (rc)
209 + sr->smb2_status = NT_STATUS_INTERNAL_ERROR;
202 210
203 -errout:
204 - smb2sr_put_error(sr, status);
205 211 return (SDRC_SUCCESS);
206 212 }
207 -
208 -/* ARGSUSED */
209 -static uint32_t
210 -smb2_fsctl_notsup(smb_request_t *sr, smb_fsctl_t *fsctl)
211 -{
212 - return (NT_STATUS_NOT_SUPPORTED);
213 -}
214 -
215 -static struct smb2_ioctbl_ent
216 -smb2_ioc_tbl[] = {
217 -
218 - /*
219 - * FILE_DEVICE_DFS (6)
220 - */
221 - { FSCTL_DFS_GET_REFERRALS,
222 - ITF_IPC_ONLY | ITF_NO_FID, smb_dfs_get_referrals },
223 - { FSCTL_DFS_GET_REFERRALS_EX,
224 - ITF_IPC_ONLY | ITF_NO_FID, smb_dfs_get_referrals },
225 -
226 - /*
227 - * FILE_DEVICE_FILE_SYSTEM (9)
228 - */
229 - { FSCTL_SET_REPARSE_POINT, 0, smb2_fsctl_notsup },
230 - { FSCTL_CREATE_OR_GET_OBJECT_ID, 0, smb2_fsctl_notsup },
231 - { FSCTL_FILE_LEVEL_TRIM, 0, smb2_fsctl_notsup },
232 -
233 - /*
234 - * FILE_DEVICE_NAMED_PIPE (17)
235 - */
236 - { FSCTL_PIPE_PEEK,
237 - ITF_IPC_ONLY, smb_opipe_fsctl },
238 - { FSCTL_PIPE_TRANSCEIVE,
239 - ITF_IPC_ONLY, smb_opipe_fsctl },
240 - { FSCTL_PIPE_WAIT,
241 - ITF_IPC_ONLY | ITF_NO_FID, smb_opipe_fsctl },
242 -
243 - /*
244 - * FILE_DEVICE_NETWORK_FILE_SYSTEM (20)
245 - */
246 - { FSCTL_SRV_ENUMERATE_SNAPSHOTS,
247 - ITF_DISK_FID, smb_vss_enum_snapshots },
248 - { FSCTL_SRV_REQUEST_RESUME_KEY, 0, smb2_fsctl_notsup },
249 - { FSCTL_SRV_COPYCHUNK, 0, smb2_fsctl_notsup },
250 - { FSCTL_SRV_COPYCHUNK_WRITE, 0, smb2_fsctl_notsup },
251 - { FSCTL_SRV_READ_HASH, 0, smb2_fsctl_notsup },
252 -
253 - { FSCTL_LMR_REQUEST_RESILIENCY,
254 - ITF_NO_FID, smb2_fsctl_notsup },
255 - { FSCTL_QUERY_NETWORK_INTERFACE_INFO,
256 - ITF_NO_FID, smb2_fsctl_notsup },
257 - { FSCTL_VALIDATE_NEGOTIATE_INFO,
258 - ITF_NO_FID, smb2_fsctl_vneginfo },
259 -
260 - /*
261 - * End marker
262 - */
263 - { 0, 0, 0 }
264 -};
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX