xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_read.c (revision 0897f7fbb62326e60e858c62a1654b2ca3e2667e)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23  * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
24  */
25 
26 #include <smbsrv/smb_kproto.h>
27 #include <smbsrv/smb_fsops.h>
28 
29 /*
30  * The maximum number of bytes to return from SMB Core
31  * SmbRead or SmbLockAndRead.
32  */
33 #define	SMB_CORE_READ_MAX	4432
34 
35 /*
36  * The limit in bytes for SmbReadX.
37  */
38 #define	SMB_READX_MAX		0x10000
39 
40 int smb_common_read(smb_request_t *, smb_rw_param_t *);
41 
42 /*
43  * Read bytes from a file or named pipe (SMB Core).
44  *
45  * The requested count specifies the number of bytes desired.  Offset
46  * is limited to 32 bits, so this client request is inappropriate for
47  * files with 64 bit offsets.
48  *
49  * On return, count is the number of bytes actually being returned, which
50  * may be less than the count requested only if a read specifies bytes
51  * beyond the current file size.  In this case only the bytes that exist
52  * are returned.  A read completely beyond the end of file results in a
53  * response of length zero.  This is the only circumstance when a zero
54  * length response is generated.  A count returned which is less than the
55  * count requested is the end of file indicator.
56  */
57 smb_sdrc_t
58 smb_pre_read(smb_request_t *sr)
59 {
60 	smb_rw_param_t *param;
61 	uint32_t off_low;
62 	uint16_t count;
63 	uint16_t remcnt;
64 	int rc;
65 
66 	param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
67 	sr->arg.rw = param;
68 
69 	rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid,
70 	    &count, &off_low, &remcnt);
71 
72 	param->rw_offset = (uint64_t)off_low;
73 	param->rw_count = (uint32_t)count;
74 	param->rw_mincnt = 0;
75 
76 	DTRACE_SMB_2(op__Read__start, smb_request_t *, sr,
77 	    smb_rw_param_t *, param);
78 
79 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
80 }
81 
82 void
83 smb_post_read(smb_request_t *sr)
84 {
85 	DTRACE_SMB_2(op__Read__done, smb_request_t *, sr,
86 	    smb_rw_param_t *, sr->arg.rw);
87 
88 	kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
89 }
90 
91 smb_sdrc_t
92 smb_com_read(smb_request_t *sr)
93 {
94 	smb_rw_param_t *param = sr->arg.rw;
95 	uint16_t count;
96 	int rc;
97 
98 	smbsr_lookup_file(sr);
99 	if (sr->fid_ofile == NULL) {
100 		smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
101 		return (SDRC_ERROR);
102 	}
103 
104 	sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
105 
106 	if (param->rw_count > SMB_CORE_READ_MAX)
107 		param->rw_count = SMB_CORE_READ_MAX;
108 
109 	if ((rc = smb_common_read(sr, param)) != 0) {
110 		smbsr_errno(sr, rc);
111 		return (SDRC_ERROR);
112 	}
113 
114 	count = (uint16_t)param->rw_count;
115 	rc = smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC",
116 	    5, count, VAR_BCC, 0x01, count, &sr->raw_data);
117 
118 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
119 }
120 
121 /*
122  * Lock and read bytes from a file (SMB Core Plus).  The SmbLockAndRead/
123  * SmbLockAndWrite sub-dialect is only valid on disk files: reject any
124  * attempt to use it on non-disk shares.
125  *
126  * The requested count specifies the number of bytes desired.  Offset
127  * specifies the offset in the file of the first byte to be locked then
128  * read. Note that offset is limited to 32 bits, so this client request
129  * is inappropriate for files with 64 bit offsets.
130  *
131  * As with SMB_LOCK_BYTE_RANGE request, if the lock cannot be granted
132  * immediately an error should be returned to the client.  If an error
133  * occurs on the lock, the bytes should not be read.
134  *
135  * On return, count is the number of bytes actually being returned, which
136  * may be less than the count requested only if a read specifies bytes
137  * beyond the current file size.  In this case only the bytes that exist
138  * are returned.  A read completely beyond the end of file results in a
139  * response of length zero.  This is the only circumstance when a zero
140  * length response is generated.  A count returned which is less than the
141  * count requested is the end of file indicator.
142  */
143 smb_sdrc_t
144 smb_pre_lock_and_read(smb_request_t *sr)
145 {
146 	smb_rw_param_t *param;
147 	uint32_t off_low;
148 	uint16_t count;
149 	uint16_t remcnt;
150 	int rc;
151 
152 	param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
153 	sr->arg.rw = param;
154 
155 	rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid,
156 	    &count, &off_low, &remcnt);
157 
158 	param->rw_offset = (uint64_t)off_low;
159 	param->rw_count = (uint32_t)count;
160 	param->rw_mincnt = 0;
161 
162 	DTRACE_SMB_2(op__LockAndRead__start, smb_request_t *, sr,
163 	    smb_rw_param_t *, param);
164 
165 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
166 }
167 
168 void
169 smb_post_lock_and_read(smb_request_t *sr)
170 {
171 	DTRACE_SMB_2(op__LockAndRead__done, smb_request_t *, sr,
172 	    smb_rw_param_t *, sr->arg.rw);
173 
174 	kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
175 }
176 
177 smb_sdrc_t
178 smb_com_lock_and_read(smb_request_t *sr)
179 {
180 	smb_rw_param_t *param = sr->arg.rw;
181 	DWORD status;
182 	uint32_t lk_pid;
183 	uint16_t count;
184 	int rc;
185 
186 	if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) {
187 		smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess);
188 		return (SDRC_ERROR);
189 	}
190 
191 	smbsr_lookup_file(sr);
192 	if (sr->fid_ofile == NULL) {
193 		smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
194 		return (SDRC_ERROR);
195 	}
196 
197 	sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
198 
199 	/* Note: SMB1 locking uses 16-bit PIDs. */
200 	lk_pid = sr->smb_pid & 0xFFFF;
201 
202 	status = smb_lock_range(sr, param->rw_offset, (uint64_t)param->rw_count,
203 	    lk_pid, SMB_LOCK_TYPE_READWRITE, 0);
204 
205 	if (status != NT_STATUS_SUCCESS) {
206 		smb_lock_range_error(sr, status);
207 		return (SDRC_ERROR);
208 	}
209 
210 	if (param->rw_count > SMB_CORE_READ_MAX)
211 		param->rw_count = SMB_CORE_READ_MAX;
212 
213 	if ((rc = smb_common_read(sr, param)) != 0) {
214 		smbsr_errno(sr, rc);
215 		return (SDRC_ERROR);
216 	}
217 
218 	count = (uint16_t)param->rw_count;
219 	rc = smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC",
220 	    5, count, VAR_BCC, 0x1, count, &sr->raw_data);
221 
222 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
223 }
224 
225 /*
226  * Read bytes from a file (SMB Core).  This request was extended in
227  * LM 0.12 to support 64-bit offsets, indicated by sending a wct of
228  * 12 and including additional offset information.
229  *
230  * MS-SMB 3.3.5.7 update to LM 0.12 4.2.4:
231  * If wct is 12 and CAP_LARGE_READX is set, the count may be larger
232  * than the negotiated buffer size.  If maxcnt_high is 0xFF, it must
233  * be ignored.  Otherwise, maxcnt_high represents the upper 16 bits
234  * of rw_count.
235  */
236 smb_sdrc_t
237 smb_pre_read_andx(smb_request_t *sr)
238 {
239 	smb_rw_param_t *param;
240 	uint32_t off_low;
241 	uint32_t off_high;
242 	uint32_t maxcnt_high;
243 	uint16_t maxcnt_low;
244 	uint16_t mincnt;
245 	uint16_t remcnt;
246 	int rc;
247 
248 	param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
249 	sr->arg.rw = param;
250 
251 	if (sr->smb_wct == 12) {
252 		rc = smbsr_decode_vwv(sr, "b3.wlwwlwl", &param->rw_andx,
253 		    &sr->smb_fid, &off_low, &maxcnt_low, &mincnt, &maxcnt_high,
254 		    &remcnt, &off_high);
255 
256 		param->rw_offset = ((uint64_t)off_high << 32) |
257 		    (uint64_t)off_low;
258 
259 		param->rw_count = (uint32_t)maxcnt_low;
260 
261 		if ((sr->session->capabilities & CAP_LARGE_READX) &&
262 		    (maxcnt_high < 0xFF))
263 			param->rw_count |= maxcnt_high << 16;
264 	} else {
265 		rc = smbsr_decode_vwv(sr, "b3.wlwwlw", &param->rw_andx,
266 		    &sr->smb_fid, &off_low, &maxcnt_low, &mincnt, &maxcnt_high,
267 		    &remcnt);
268 
269 		param->rw_offset = (uint64_t)off_low;
270 		param->rw_count = (uint32_t)maxcnt_low;
271 	}
272 
273 	param->rw_mincnt = 0;
274 
275 	DTRACE_SMB_2(op__ReadX__start, smb_request_t *, sr,
276 	    smb_rw_param_t *, param);
277 
278 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
279 }
280 
281 void
282 smb_post_read_andx(smb_request_t *sr)
283 {
284 	DTRACE_SMB_2(op__ReadX__done, smb_request_t *, sr,
285 	    smb_rw_param_t *, sr->arg.rw);
286 
287 	kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
288 }
289 
290 smb_sdrc_t
291 smb_com_read_andx(smb_request_t *sr)
292 {
293 	smb_rw_param_t *param = sr->arg.rw;
294 	uint16_t datalen_high;
295 	uint16_t datalen_low;
296 	uint16_t data_offset;
297 	uint16_t offset2;
298 	int rc;
299 
300 	smbsr_lookup_file(sr);
301 	if (sr->fid_ofile == NULL) {
302 		smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
303 		return (SDRC_ERROR);
304 	}
305 
306 	sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
307 
308 	if (param->rw_count >= SMB_READX_MAX)
309 		param->rw_count = 0;
310 
311 	if ((rc = smb_common_read(sr, param)) != 0) {
312 		smbsr_errno(sr, rc);
313 		return (SDRC_ERROR);
314 	}
315 
316 	datalen_low = param->rw_count & 0xFFFF;
317 	datalen_high = (param->rw_count >> 16) & 0xFF;
318 
319 	/*
320 	 * If this is a secondary command, the data offset
321 	 * includes the previous wct + sizeof(wct).
322 	 */
323 	data_offset = (sr->andx_prev_wct == 0) ? 0 : sr->andx_prev_wct + 1;
324 
325 	if (STYPE_ISIPC(sr->tid_tree->t_res_type)) {
326 		data_offset += 60;
327 		offset2 = (param->rw_andx == 0xFF) ? 0 : param->rw_count + 60;
328 
329 		rc = smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.www8.wbC",
330 		    12,			/* wct */
331 		    param->rw_andx,	/* secondary andx command */
332 		    offset2,		/* offset to next command */
333 		    0,			/* set to 0 for named pipes */
334 		    datalen_low,	/* data byte count */
335 		    data_offset,	/* offset from start to data */
336 		    datalen_high,	/* data byte count */
337 		    VAR_BCC,		/* BCC marker */
338 		    0x00,		/* padding */
339 		    &sr->raw_data);
340 	} else {
341 		data_offset += 59;
342 		offset2 = (param->rw_andx == 0xFF) ? 0 : param->rw_count + 59;
343 
344 		rc = smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.www8.wC",
345 		    12,			/* wct */
346 		    param->rw_andx,	/* secondary andx command */
347 		    offset2,		/* offset to next command */
348 		    -1,			/* must be -1 for regular files */
349 		    datalen_low,	/* data byte count */
350 		    data_offset,	/* offset from start to data */
351 		    datalen_high,	/* data byte count */
352 		    VAR_BCC,		/* BCC marker */
353 		    &sr->raw_data);
354 	}
355 
356 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
357 }
358 
359 /*
360  * Common function for reading files or IPC/MSRPC named pipes.  All
361  * protocol read functions should lookup the fid before calling this
362  * function.  We can't move the fid lookup here because lock-and-read
363  * requires the fid to do locking before attempting the read.
364  *
365  * Reading from a file should break oplocks on the file to LEVEL_II.
366  * A call to smb_oplock_break(SMB_OPLOCK_BREAK_TO_LEVEL_II) is not
367  * required as it is a no-op. If there's anything greater than a
368  * LEVEL_II oplock on the file, the oplock MUST be owned by the ofile
369  * on which the read is occuring and therefore would not be broken.
370  *
371  * Returns errno values.
372  */
373 int
374 smb_common_read(smb_request_t *sr, smb_rw_param_t *param)
375 {
376 	smb_ofile_t *ofile = sr->fid_ofile;
377 	smb_node_t *node;
378 	smb_vdb_t *vdb = &param->rw_vdb;
379 	struct mbuf *top;
380 	int rc;
381 
382 	vdb->vdb_tag = 0;
383 	vdb->vdb_uio.uio_iov = &vdb->vdb_iovec[0];
384 	vdb->vdb_uio.uio_iovcnt = MAX_IOVEC;
385 	vdb->vdb_uio.uio_resid = param->rw_count;
386 	vdb->vdb_uio.uio_loffset = (offset_t)param->rw_offset;
387 	vdb->vdb_uio.uio_segflg = UIO_SYSSPACE;
388 	vdb->vdb_uio.uio_extflg = UIO_COPY_DEFAULT;
389 
390 	switch (sr->tid_tree->t_res_type & STYPE_MASK) {
391 	case STYPE_DISKTREE:
392 		node = ofile->f_node;
393 
394 		if (!smb_node_is_dir(node)) {
395 			rc = smb_lock_range_access(sr, node, param->rw_offset,
396 			    param->rw_count, B_FALSE);
397 			if (rc != NT_STATUS_SUCCESS) {
398 				rc = ERANGE;
399 				break;
400 			}
401 		}
402 
403 		if ((ofile->f_flags & SMB_OFLAGS_EXECONLY) &&
404 		    !(sr->smb_flg2 & SMB_FLAGS2_READ_IF_EXECUTE)) {
405 			/*
406 			 * SMB_FLAGS2_READ_IF_EXECUTE: permit execute-only
407 			 * reads.
408 			 *
409 			 * Reject request if the file has been opened
410 			 * execute-only and SMB_FLAGS2_READ_IF_EXECUTE is not
411 			 * set.
412 			 */
413 			rc = EACCES;
414 			break;
415 		}
416 
417 		sr->raw_data.max_bytes = vdb->vdb_uio.uio_resid;
418 		top = smb_mbuf_allocate(&vdb->vdb_uio);
419 
420 		rc = smb_fsop_read(sr, sr->user_cr, node, &vdb->vdb_uio);
421 
422 		sr->raw_data.max_bytes -= vdb->vdb_uio.uio_resid;
423 		smb_mbuf_trim(top, sr->raw_data.max_bytes);
424 		MBC_ATTACH_MBUF(&sr->raw_data, top);
425 		break;
426 
427 	case STYPE_IPC:
428 		sr->raw_data.max_bytes = vdb->vdb_uio.uio_resid;
429 		top = smb_mbuf_allocate(&vdb->vdb_uio);
430 
431 		rc = smb_opipe_read(sr, &vdb->vdb_uio);
432 
433 		sr->raw_data.max_bytes -= vdb->vdb_uio.uio_resid;
434 		smb_mbuf_trim(top, sr->raw_data.max_bytes);
435 		MBC_ATTACH_MBUF(&sr->raw_data, top);
436 		break;
437 
438 	default:
439 		rc = EACCES;
440 		break;
441 	}
442 
443 	param->rw_count -= vdb->vdb_uio.uio_resid;
444 
445 	if (rc != 0)
446 		return (rc);
447 
448 	if (param->rw_mincnt != 0 && param->rw_count < param->rw_mincnt) {
449 		/*
450 		 * mincnt is only used by read-raw and is typically
451 		 * zero.  If mincnt is greater than zero and the
452 		 * number of bytes read is less than mincnt, tell
453 		 * the client that we read nothing.
454 		 */
455 		param->rw_count = 0;
456 	}
457 
458 	param->rw_offset += param->rw_count;
459 	mutex_enter(&sr->fid_ofile->f_mutex);
460 	ofile->f_seek_pos = param->rw_offset;
461 	mutex_exit(&sr->fid_ofile->f_mutex);
462 	return (rc);
463 }
464