xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_read.c (revision 694c35faa87b858ecdadfe4fc592615f4eefbb07)
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  */
24 
25 #include <smbsrv/smb_kproto.h>
26 #include <smbsrv/smb_fsops.h>
27 
28 /*
29  * There may be oplock break requests waiting to be sent after
30  * a read raw request completes.
31  */
32 #define	SMB_OPLOCK_BREAKS_PENDING(sr) \
33 	!list_is_empty(&(sr)->session->s_oplock_brkreqs)
34 
35 /*
36  * The maximum number of bytes to return from SMB Core
37  * SmbRead or SmbLockAndRead.
38  */
39 #define	SMB_CORE_READ_MAX	4432
40 
41 /*
42  * The limit in bytes for SmbReadX.
43  */
44 #define	SMB_READX_MAX		0x10000
45 
46 int smb_common_read(smb_request_t *, smb_rw_param_t *);
47 
48 /*
49  * Read bytes from a file or named pipe (SMB Core).
50  *
51  * The requested count specifies the number of bytes desired.  Offset
52  * is limited to 32 bits, so this client request is inappropriate for
53  * files with 64 bit offsets.
54  *
55  * On return, count is the number of bytes actually being returned, which
56  * may be less than the count requested only if a read specifies bytes
57  * beyond the current file size.  In this case only the bytes that exist
58  * are returned.  A read completely beyond the end of file results in a
59  * response of length zero.  This is the only circumstance when a zero
60  * length response is generated.  A count returned which is less than the
61  * count requested is the end of file indicator.
62  */
63 smb_sdrc_t
64 smb_pre_read(smb_request_t *sr)
65 {
66 	smb_rw_param_t *param;
67 	uint32_t off_low;
68 	uint16_t count;
69 	uint16_t remcnt;
70 	int rc;
71 
72 	param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
73 	sr->arg.rw = param;
74 
75 	rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid,
76 	    &count, &off_low, &remcnt);
77 
78 	param->rw_offset = (uint64_t)off_low;
79 	param->rw_count = (uint32_t)count;
80 	param->rw_mincnt = 0;
81 
82 	DTRACE_SMB_2(op__Read__start, smb_request_t *, sr,
83 	    smb_rw_param_t *, param);
84 
85 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
86 }
87 
88 void
89 smb_post_read(smb_request_t *sr)
90 {
91 	DTRACE_SMB_2(op__Read__done, smb_request_t *, sr,
92 	    smb_rw_param_t *, sr->arg.rw);
93 
94 	kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
95 }
96 
97 smb_sdrc_t
98 smb_com_read(smb_request_t *sr)
99 {
100 	smb_rw_param_t *param = sr->arg.rw;
101 	uint16_t count;
102 	int rc;
103 
104 	smbsr_lookup_file(sr);
105 	if (sr->fid_ofile == NULL) {
106 		smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
107 		return (SDRC_ERROR);
108 	}
109 
110 	sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
111 
112 	if (param->rw_count > SMB_CORE_READ_MAX)
113 		param->rw_count = SMB_CORE_READ_MAX;
114 
115 	if ((rc = smb_common_read(sr, param)) != 0) {
116 		smbsr_errno(sr, rc);
117 		return (SDRC_ERROR);
118 	}
119 
120 	count = (uint16_t)param->rw_count;
121 	rc = smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC",
122 	    5, count, VAR_BCC, 0x01, count, &sr->raw_data);
123 
124 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
125 }
126 
127 /*
128  * Lock and read bytes from a file (SMB Core Plus).  The SmbLockAndRead/
129  * SmbLockAndWrite sub-dialect is only valid on disk files: reject any
130  * attempt to use it on non-disk shares.
131  *
132  * The requested count specifies the number of bytes desired.  Offset
133  * specifies the offset in the file of the first byte to be locked then
134  * read. Note that offset is limited to 32 bits, so this client request
135  * is inappropriate for files with 64 bit offsets.
136  *
137  * As with SMB_LOCK_BYTE_RANGE request, if the lock cannot be granted
138  * immediately an error should be returned to the client.  If an error
139  * occurs on the lock, the bytes should not be read.
140  *
141  * On return, count is the number of bytes actually being returned, which
142  * may be less than the count requested only if a read specifies bytes
143  * beyond the current file size.  In this case only the bytes that exist
144  * are returned.  A read completely beyond the end of file results in a
145  * response of length zero.  This is the only circumstance when a zero
146  * length response is generated.  A count returned which is less than the
147  * count requested is the end of file indicator.
148  */
149 smb_sdrc_t
150 smb_pre_lock_and_read(smb_request_t *sr)
151 {
152 	smb_rw_param_t *param;
153 	uint32_t off_low;
154 	uint16_t count;
155 	uint16_t remcnt;
156 	int rc;
157 
158 	param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
159 	sr->arg.rw = param;
160 
161 	rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid,
162 	    &count, &off_low, &remcnt);
163 
164 	param->rw_offset = (uint64_t)off_low;
165 	param->rw_count = (uint32_t)count;
166 	param->rw_mincnt = 0;
167 
168 	DTRACE_SMB_2(op__LockAndRead__start, smb_request_t *, sr,
169 	    smb_rw_param_t *, param);
170 
171 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
172 }
173 
174 void
175 smb_post_lock_and_read(smb_request_t *sr)
176 {
177 	DTRACE_SMB_2(op__LockAndRead__done, smb_request_t *, sr,
178 	    smb_rw_param_t *, sr->arg.rw);
179 
180 	kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
181 }
182 
183 smb_sdrc_t
184 smb_com_lock_and_read(smb_request_t *sr)
185 {
186 	smb_rw_param_t *param = sr->arg.rw;
187 	DWORD status;
188 	uint16_t count;
189 	int rc;
190 
191 	if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) {
192 		smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess);
193 		return (SDRC_ERROR);
194 	}
195 
196 	smbsr_lookup_file(sr);
197 	if (sr->fid_ofile == NULL) {
198 		smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
199 		return (SDRC_ERROR);
200 	}
201 
202 	sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
203 
204 	status = smb_lock_range(sr, param->rw_offset, (uint64_t)param->rw_count,
205 	    0, SMB_LOCK_TYPE_READWRITE);
206 
207 	if (status != NT_STATUS_SUCCESS) {
208 		smb_lock_range_error(sr, status);
209 		return (SDRC_ERROR);
210 	}
211 
212 	if (param->rw_count > SMB_CORE_READ_MAX)
213 		param->rw_count = SMB_CORE_READ_MAX;
214 
215 	if ((rc = smb_common_read(sr, param)) != 0) {
216 		smbsr_errno(sr, rc);
217 		return (SDRC_ERROR);
218 	}
219 
220 	count = (uint16_t)param->rw_count;
221 	rc = smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC",
222 	    5, count, VAR_BCC, 0x1, count, &sr->raw_data);
223 
224 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
225 }
226 
227 /*
228  * The SMB_COM_READ_RAW protocol is a negotiated option introduced in
229  * SMB Core Plus to maximize performance when reading a large block
230  * of data from a server.  This request was extended in LM 0.12 to
231  * support 64-bit offsets; the server can indicate support by setting
232  * CAP_LARGE_FILES in the negotiated capabilities.
233  *
234  * The client must guarantee that there is (and will be) no other request
235  * to the server for the duration of the SMB_COM_READ_RAW, since the
236  * server response has no header or trailer. To help ensure that there
237  * are no interruptions, we block all I/O for the session during read raw.
238  *
239  * If this is the first SMB request received since we sent an oplock break
240  * to this client, we don't know if it's safe to send the raw data because
241  * the requests may have crossed on the wire and the client may have
242  * interpreted the oplock break as part of the raw data. To avoid problems,
243  * we send a zero length session packet, which will force the client to
244  * retry the read.
245  *
246  * Do not return errors from SmbReadRaw.
247  * Read errors are handled by sending a zero length response.
248  */
249 smb_sdrc_t
250 smb_pre_read_raw(smb_request_t *sr)
251 {
252 	smb_rw_param_t *param;
253 	uint32_t off_low;
254 	uint32_t off_high;
255 	uint32_t timeout;
256 	uint16_t count;
257 	int rc;
258 
259 	param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
260 	sr->arg.rw = param;
261 
262 	if (sr->smb_wct == 8) {
263 		rc = smbsr_decode_vwv(sr, "wlwwl2.", &sr->smb_fid,
264 		    &off_low, &count, &param->rw_mincnt, &timeout);
265 		if (rc == 0) {
266 			param->rw_offset = (uint64_t)off_low;
267 			param->rw_count = (uint32_t)count;
268 		}
269 	} else {
270 		rc = smbsr_decode_vwv(sr, "wlwwl2.l", &sr->smb_fid,
271 		    &off_low, &count, &param->rw_mincnt, &timeout, &off_high);
272 		if (rc == 0) {
273 			param->rw_offset = ((uint64_t)off_high << 32) | off_low;
274 			param->rw_count = (uint32_t)count;
275 		}
276 	}
277 
278 	DTRACE_SMB_2(op__ReadRaw__start, smb_request_t *, sr,
279 	    smb_rw_param_t *, param);
280 
281 	smb_rwx_rwenter(&sr->session->s_lock, RW_WRITER);
282 	return (SDRC_SUCCESS);
283 }
284 
285 void
286 smb_post_read_raw(smb_request_t *sr)
287 {
288 	mbuf_chain_t	*mbc;
289 
290 	if (sr->session->s_state == SMB_SESSION_STATE_READ_RAW_ACTIVE) {
291 		if (SMB_OPLOCK_BREAKS_PENDING(sr)) {
292 			sr->session->s_state =
293 			    SMB_SESSION_STATE_OPLOCK_BREAKING;
294 		} else {
295 			sr->session->s_state = SMB_SESSION_STATE_NEGOTIATED;
296 		}
297 
298 		while ((mbc = list_head(&sr->session->s_oplock_brkreqs)) !=
299 		    NULL) {
300 			SMB_MBC_VALID(mbc);
301 			list_remove(&sr->session->s_oplock_brkreqs, mbc);
302 			(void) smb_session_send(sr->session, 0, mbc);
303 			smb_mbc_free(mbc);
304 		}
305 	}
306 
307 	DTRACE_SMB_2(op__ReadRaw__done, smb_request_t *, sr,
308 	    smb_rw_param_t *, sr->arg.rw);
309 
310 	smb_rwx_rwexit(&sr->session->s_lock);
311 	kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
312 }
313 
314 smb_sdrc_t
315 smb_com_read_raw(smb_request_t *sr)
316 {
317 	smb_rw_param_t *param = sr->arg.rw;
318 
319 	if (!smb_raw_mode)
320 		return (SDRC_DROP_VC);
321 
322 	switch (sr->session->s_state) {
323 	case SMB_SESSION_STATE_NEGOTIATED:
324 		sr->session->s_state = SMB_SESSION_STATE_READ_RAW_ACTIVE;
325 		break;
326 
327 	case SMB_SESSION_STATE_OPLOCK_BREAKING:
328 		(void) smb_session_send(sr->session, 0, NULL);
329 		return (SDRC_NO_REPLY);
330 
331 	case SMB_SESSION_STATE_TERMINATED:
332 	case SMB_SESSION_STATE_DISCONNECTED:
333 		return (SDRC_NO_REPLY);
334 
335 	case SMB_SESSION_STATE_READ_RAW_ACTIVE:
336 		sr->session->s_state = SMB_SESSION_STATE_NEGOTIATED;
337 		return (SDRC_DROP_VC);
338 
339 	case SMB_SESSION_STATE_WRITE_RAW_ACTIVE:
340 	case SMB_SESSION_STATE_CONNECTED:
341 	case SMB_SESSION_STATE_ESTABLISHED:
342 	default:
343 		return (SDRC_DROP_VC);
344 	}
345 
346 	smbsr_lookup_file(sr);
347 	if (sr->fid_ofile == NULL) {
348 		(void) smb_session_send(sr->session, 0, NULL);
349 		return (SDRC_NO_REPLY);
350 	}
351 
352 	sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
353 
354 	if (param->rw_mincnt > param->rw_count)
355 		param->rw_mincnt = 0;
356 
357 	if ((smb_common_read(sr, param) != 0) ||
358 	    (SMB_OPLOCK_BREAKS_PENDING(sr))) {
359 		(void) smb_session_send(sr->session, 0, NULL);
360 		m_freem(sr->raw_data.chain);
361 		sr->raw_data.chain = NULL;
362 	} else {
363 		(void) smb_session_send(sr->session, 0, &sr->raw_data);
364 	}
365 
366 	return (SDRC_NO_REPLY);
367 }
368 
369 /*
370  * Read bytes from a file (SMB Core).  This request was extended in
371  * LM 0.12 to support 64-bit offsets, indicated by sending a wct of
372  * 12 and including additional offset information.
373  *
374  * MS-SMB 3.3.5.7 update to LM 0.12 4.2.4:
375  * If wct is 12 and CAP_LARGE_READX is set, the count may be larger
376  * than the negotiated buffer size.  If maxcnt_high is 0xFF, it must
377  * be ignored.  Otherwise, maxcnt_high represents the upper 16 bits
378  * of rw_count.
379  */
380 smb_sdrc_t
381 smb_pre_read_andx(smb_request_t *sr)
382 {
383 	smb_rw_param_t *param;
384 	uint32_t off_low;
385 	uint32_t off_high;
386 	uint32_t maxcnt_high;
387 	uint16_t maxcnt_low;
388 	uint16_t mincnt;
389 	uint16_t remcnt;
390 	int rc;
391 
392 	param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
393 	sr->arg.rw = param;
394 
395 	if (sr->smb_wct == 12) {
396 		rc = smbsr_decode_vwv(sr, "b3.wlwwlwl", &param->rw_andx,
397 		    &sr->smb_fid, &off_low, &maxcnt_low, &mincnt, &maxcnt_high,
398 		    &remcnt, &off_high);
399 
400 		param->rw_offset = ((uint64_t)off_high << 32) |
401 		    (uint64_t)off_low;
402 
403 		param->rw_count = (uint32_t)maxcnt_low;
404 
405 		if ((sr->session->capabilities & CAP_LARGE_READX) &&
406 		    (maxcnt_high < 0xFF))
407 			param->rw_count |= maxcnt_high << 16;
408 	} else {
409 		rc = smbsr_decode_vwv(sr, "b3.wlwwlw", &param->rw_andx,
410 		    &sr->smb_fid, &off_low, &maxcnt_low, &mincnt, &maxcnt_high,
411 		    &remcnt);
412 
413 		param->rw_offset = (uint64_t)off_low;
414 		param->rw_count = (uint32_t)maxcnt_low;
415 	}
416 
417 	param->rw_mincnt = 0;
418 
419 	DTRACE_SMB_2(op__ReadX__start, smb_request_t *, sr,
420 	    smb_rw_param_t *, param);
421 
422 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
423 }
424 
425 void
426 smb_post_read_andx(smb_request_t *sr)
427 {
428 	DTRACE_SMB_2(op__ReadX__done, smb_request_t *, sr,
429 	    smb_rw_param_t *, sr->arg.rw);
430 
431 	kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
432 }
433 
434 smb_sdrc_t
435 smb_com_read_andx(smb_request_t *sr)
436 {
437 	smb_rw_param_t *param = sr->arg.rw;
438 	uint16_t datalen_high;
439 	uint16_t datalen_low;
440 	uint16_t data_offset;
441 	uint16_t offset2;
442 	int rc;
443 
444 	smbsr_lookup_file(sr);
445 	if (sr->fid_ofile == NULL) {
446 		smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
447 		return (SDRC_ERROR);
448 	}
449 
450 	sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
451 
452 	if (param->rw_count >= SMB_READX_MAX)
453 		param->rw_count = 0;
454 
455 	if ((rc = smb_common_read(sr, param)) != 0) {
456 		smbsr_errno(sr, rc);
457 		return (SDRC_ERROR);
458 	}
459 
460 	datalen_low = param->rw_count & 0xFFFF;
461 	datalen_high = (param->rw_count >> 16) & 0xFF;
462 
463 	/*
464 	 * If this is a secondary command, the data offset
465 	 * includes the previous wct + sizeof(wct).
466 	 */
467 	data_offset = (sr->andx_prev_wct == 0) ? 0 : sr->andx_prev_wct + 1;
468 
469 	if (STYPE_ISIPC(sr->tid_tree->t_res_type)) {
470 		data_offset += 60;
471 		offset2 = (param->rw_andx == 0xFF) ? 0 : param->rw_count + 60;
472 
473 		rc = smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.www8.wbC",
474 		    12,			/* wct */
475 		    param->rw_andx,	/* secondary andx command */
476 		    offset2,		/* offset to next command */
477 		    0,			/* set to 0 for named pipes */
478 		    datalen_low,	/* data byte count */
479 		    data_offset,	/* offset from start to data */
480 		    datalen_high,	/* data byte count */
481 		    VAR_BCC,		/* BCC marker */
482 		    0x00,		/* padding */
483 		    &sr->raw_data);
484 	} else {
485 		data_offset += 59;
486 		offset2 = (param->rw_andx == 0xFF) ? 0 : param->rw_count + 59;
487 
488 		rc = smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.www8.wC",
489 		    12,			/* wct */
490 		    param->rw_andx,	/* secondary andx command */
491 		    offset2,		/* offset to next command */
492 		    -1,			/* must be -1 for regular files */
493 		    datalen_low,	/* data byte count */
494 		    data_offset,	/* offset from start to data */
495 		    datalen_high,	/* data byte count */
496 		    VAR_BCC,		/* BCC marker */
497 		    &sr->raw_data);
498 	}
499 
500 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
501 }
502 
503 /*
504  * Common function for reading files or IPC/MSRPC named pipes.  All
505  * protocol read functions should lookup the fid before calling this
506  * function.  We can't move the fid lookup here because lock-and-read
507  * requires the fid to do locking before attempting the read.
508  *
509  * Reading from a file should break oplocks on the file to LEVEL_II.
510  * A call to smb_oplock_break(SMB_OPLOCK_BREAK_TO_LEVEL_II) is not
511  * required as it is a no-op. If there's anything greater than a
512  * LEVEL_II oplock on the file, the oplock MUST be owned by the ofile
513  * on which the read is occuring and therefore would not be broken.
514  *
515  * Returns errno values.
516  */
517 int
518 smb_common_read(smb_request_t *sr, smb_rw_param_t *param)
519 {
520 	smb_ofile_t *ofile = sr->fid_ofile;
521 	smb_node_t *node;
522 	smb_vdb_t *vdb = &param->rw_vdb;
523 	struct mbuf *top;
524 	int rc;
525 
526 	vdb->vdb_tag = 0;
527 	vdb->vdb_uio.uio_iov = &vdb->vdb_iovec[0];
528 	vdb->vdb_uio.uio_iovcnt = MAX_IOVEC;
529 	vdb->vdb_uio.uio_resid = param->rw_count;
530 	vdb->vdb_uio.uio_loffset = (offset_t)param->rw_offset;
531 	vdb->vdb_uio.uio_segflg = UIO_SYSSPACE;
532 	vdb->vdb_uio.uio_extflg = UIO_COPY_DEFAULT;
533 
534 	switch (sr->tid_tree->t_res_type & STYPE_MASK) {
535 	case STYPE_DISKTREE:
536 		node = ofile->f_node;
537 
538 		if (!smb_node_is_dir(node)) {
539 			rc = smb_lock_range_access(sr, node, param->rw_offset,
540 			    param->rw_count, B_FALSE);
541 			if (rc != NT_STATUS_SUCCESS) {
542 				rc = ERANGE;
543 				break;
544 			}
545 		}
546 
547 		if ((ofile->f_flags & SMB_OFLAGS_EXECONLY) &&
548 		    !(sr->smb_flg2 & SMB_FLAGS2_READ_IF_EXECUTE)) {
549 			/*
550 			 * SMB_FLAGS2_READ_IF_EXECUTE: permit execute-only
551 			 * reads.
552 			 *
553 			 * Reject request if the file has been opened
554 			 * execute-only and SMB_FLAGS2_READ_IF_EXECUTE is not
555 			 * set.
556 			 */
557 			rc = EACCES;
558 			break;
559 		}
560 
561 		sr->raw_data.max_bytes = vdb->vdb_uio.uio_resid;
562 		top = smb_mbuf_allocate(&vdb->vdb_uio);
563 
564 		rc = smb_fsop_read(sr, sr->user_cr, node, &vdb->vdb_uio);
565 
566 		sr->raw_data.max_bytes -= vdb->vdb_uio.uio_resid;
567 		smb_mbuf_trim(top, sr->raw_data.max_bytes);
568 		MBC_ATTACH_MBUF(&sr->raw_data, top);
569 		break;
570 
571 	case STYPE_IPC:
572 		rc = smb_opipe_read(sr, &vdb->vdb_uio);
573 		break;
574 
575 	default:
576 		rc = EACCES;
577 		break;
578 	}
579 
580 	param->rw_count -= vdb->vdb_uio.uio_resid;
581 
582 	if (rc != 0)
583 		return (rc);
584 
585 	if (param->rw_mincnt != 0 && param->rw_count < param->rw_mincnt) {
586 		/*
587 		 * mincnt is only used by read-raw and is typically
588 		 * zero.  If mincnt is greater than zero and the
589 		 * number of bytes read is less than mincnt, tell
590 		 * the client that we read nothing.
591 		 */
592 		param->rw_count = 0;
593 	}
594 
595 	param->rw_offset += param->rw_count;
596 	mutex_enter(&sr->fid_ofile->f_mutex);
597 	ofile->f_seek_pos = param->rw_offset;
598 	mutex_exit(&sr->fid_ofile->f_mutex);
599 	return (rc);
600 }
601