xref: /illumos-gate/usr/src/uts/common/syscall/rw.c (revision 3d393ee6c37fa10ac512ed6d36109ad616dc7c1a)
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 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 /*
31  * Portions of this source code were derived from Berkeley 4.3 BSD
32  * under license from the Regents of the University of California.
33  */
34 
35 #pragma ident	"%Z%%M%	%I%	%E% SMI"
36 
37 #include <sys/param.h>
38 #include <sys/isa_defs.h>
39 #include <sys/types.h>
40 #include <sys/inttypes.h>
41 #include <sys/sysmacros.h>
42 #include <sys/cred.h>
43 #include <sys/user.h>
44 #include <sys/systm.h>
45 #include <sys/errno.h>
46 #include <sys/vnode.h>
47 #include <sys/file.h>
48 #include <sys/proc.h>
49 #include <sys/cpuvar.h>
50 #include <sys/uio.h>
51 #include <sys/debug.h>
52 #include <sys/rctl.h>
53 #include <sys/nbmlock.h>
54 
55 #define	COPYOUT_MAX_CACHE	(1<<17)		/* 128K */
56 
57 size_t copyout_max_cached = COPYOUT_MAX_CACHE;	/* global so it's patchable */
58 
59 /*
60  * read, write, pread, pwrite, readv, and writev syscalls.
61  *
62  * 64-bit open:	all open's are large file opens.
63  * Large Files: the behaviour of read depends on whether the fd
64  *		corresponds to large open or not.
65  * 32-bit open:	FOFFMAX flag not set.
66  *		read until MAXOFF32_T - 1 and read at MAXOFF32_T returns
67  *		EOVERFLOW if count is non-zero and if size of file
68  *		is > MAXOFF32_T. If size of file is <= MAXOFF32_T read
69  *		at >= MAXOFF32_T returns EOF.
70  */
71 
72 /*
73  * Native system call
74  */
75 ssize_t
76 read(int fdes, void *cbuf, size_t count)
77 {
78 	struct uio auio;
79 	struct iovec aiov;
80 	file_t *fp;
81 	register vnode_t *vp;
82 	struct cpu *cp;
83 	int fflag, ioflag, rwflag;
84 	ssize_t cnt, bcount;
85 	int error = 0;
86 	u_offset_t fileoff;
87 	int in_crit = 0;
88 
89 	if ((cnt = (ssize_t)count) < 0)
90 		return (set_errno(EINVAL));
91 	if ((fp = getf(fdes)) == NULL)
92 		return (set_errno(EBADF));
93 	if (((fflag = fp->f_flag) & FREAD) == 0) {
94 		error = EBADF;
95 		goto out;
96 	}
97 	vp = fp->f_vnode;
98 
99 	if (vp->v_type == VREG && cnt == 0) {
100 		goto out;
101 	}
102 
103 	rwflag = 0;
104 	aiov.iov_base = cbuf;
105 	aiov.iov_len = cnt;
106 
107 	/*
108 	 * We have to enter the critical region before calling VOP_RWLOCK
109 	 * to avoid a deadlock with write() calls.
110 	 */
111 	if (nbl_need_check(vp)) {
112 		int svmand;
113 
114 		nbl_start_crit(vp, RW_READER);
115 		in_crit = 1;
116 		error = nbl_svmand(vp, fp->f_cred, &svmand);
117 		if (error != 0)
118 			goto out;
119 		if (nbl_conflict(vp, NBL_READ, fp->f_offset, cnt, svmand,
120 		    NULL)) {
121 			error = EACCES;
122 			goto out;
123 		}
124 	}
125 
126 	(void) VOP_RWLOCK(vp, rwflag, NULL);
127 
128 	/*
129 	 * We do the following checks inside VOP_RWLOCK so as to
130 	 * prevent file size from changing while these checks are
131 	 * being done. Also, we load fp's offset to the local
132 	 * variable fileoff because we can have a parallel lseek
133 	 * going on (f_offset is not protected by any lock) which
134 	 * could change f_offset. We need to see the value only
135 	 * once here and take a decision. Seeing it more than once
136 	 * can lead to incorrect functionality.
137 	 */
138 
139 	fileoff = (u_offset_t)fp->f_offset;
140 	if (fileoff >= OFFSET_MAX(fp) && (vp->v_type == VREG)) {
141 		struct vattr va;
142 		va.va_mask = AT_SIZE;
143 		if ((error = VOP_GETATTR(vp, &va, 0, fp->f_cred, NULL)))  {
144 			VOP_RWUNLOCK(vp, rwflag, NULL);
145 			goto out;
146 		}
147 		if (fileoff >= va.va_size) {
148 			cnt = 0;
149 			VOP_RWUNLOCK(vp, rwflag, NULL);
150 			goto out;
151 		} else {
152 			error = EOVERFLOW;
153 			VOP_RWUNLOCK(vp, rwflag, NULL);
154 			goto out;
155 		}
156 	}
157 	if ((vp->v_type == VREG) &&
158 	    (fileoff + cnt > OFFSET_MAX(fp))) {
159 		cnt = (ssize_t)(OFFSET_MAX(fp) - fileoff);
160 	}
161 	auio.uio_loffset = fileoff;
162 	auio.uio_iov = &aiov;
163 	auio.uio_iovcnt = 1;
164 	auio.uio_resid = bcount = cnt;
165 	auio.uio_segflg = UIO_USERSPACE;
166 	auio.uio_llimit = MAXOFFSET_T;
167 	auio.uio_fmode = fflag;
168 	/*
169 	 * Only use bypass caches when the count is large enough
170 	 */
171 	if (bcount <= copyout_max_cached)
172 		auio.uio_extflg = UIO_COPY_CACHED;
173 	else
174 		auio.uio_extflg = UIO_COPY_DEFAULT;
175 
176 	ioflag = auio.uio_fmode & (FAPPEND|FSYNC|FDSYNC|FRSYNC);
177 
178 	/* If read sync is not asked for, filter sync flags */
179 	if ((ioflag & FRSYNC) == 0)
180 		ioflag &= ~(FSYNC|FDSYNC);
181 	error = VOP_READ(vp, &auio, ioflag, fp->f_cred, NULL);
182 	cnt -= auio.uio_resid;
183 	CPU_STATS_ENTER_K();
184 	cp = CPU;
185 	CPU_STATS_ADDQ(cp, sys, sysread, 1);
186 	CPU_STATS_ADDQ(cp, sys, readch, (ulong_t)cnt);
187 	CPU_STATS_EXIT_K();
188 	ttolwp(curthread)->lwp_ru.ioch += (ulong_t)cnt;
189 
190 	if (vp->v_type == VFIFO)	/* Backward compatibility */
191 		fp->f_offset = cnt;
192 	else if (((fp->f_flag & FAPPEND) == 0) ||
193 	    (vp->v_type != VREG) || (bcount != 0))	/* POSIX */
194 		fp->f_offset = auio.uio_loffset;
195 	VOP_RWUNLOCK(vp, rwflag, NULL);
196 
197 	if (error == EINTR && cnt != 0)
198 		error = 0;
199 out:
200 	if (in_crit)
201 		nbl_end_crit(vp);
202 	releasef(fdes);
203 	if (error)
204 		return (set_errno(error));
205 	return (cnt);
206 }
207 
208 /*
209  * Native system call
210  */
211 ssize_t
212 write(int fdes, void *cbuf, size_t count)
213 {
214 	struct uio auio;
215 	struct iovec aiov;
216 	file_t *fp;
217 	register vnode_t *vp;
218 	struct cpu *cp;
219 	int fflag, ioflag, rwflag;
220 	ssize_t cnt, bcount;
221 	int error = 0;
222 	u_offset_t fileoff;
223 	int in_crit = 0;
224 
225 	if ((cnt = (ssize_t)count) < 0)
226 		return (set_errno(EINVAL));
227 	if ((fp = getf(fdes)) == NULL)
228 		return (set_errno(EBADF));
229 	if (((fflag = fp->f_flag) & FWRITE) == 0) {
230 		error = EBADF;
231 		goto out;
232 	}
233 	vp = fp->f_vnode;
234 
235 	if (vp->v_type == VREG && cnt == 0) {
236 		goto out;
237 	}
238 
239 	rwflag = 1;
240 	aiov.iov_base = cbuf;
241 	aiov.iov_len = cnt;
242 
243 	/*
244 	 * We have to enter the critical region before calling VOP_RWLOCK
245 	 * to avoid a deadlock with ufs.
246 	 */
247 	if (nbl_need_check(vp)) {
248 		int svmand;
249 
250 		nbl_start_crit(vp, RW_READER);
251 		in_crit = 1;
252 		error = nbl_svmand(vp, fp->f_cred, &svmand);
253 		if (error != 0)
254 			goto out;
255 		if (nbl_conflict(vp, NBL_WRITE, fp->f_offset, cnt, svmand,
256 		    NULL)) {
257 			error = EACCES;
258 			goto out;
259 		}
260 	}
261 
262 	(void) VOP_RWLOCK(vp, rwflag, NULL);
263 
264 	fileoff = fp->f_offset;
265 	if (vp->v_type == VREG) {
266 
267 		/*
268 		 * We raise psignal if write for >0 bytes causes
269 		 * it to exceed the ulimit.
270 		 */
271 		if (fileoff >= curproc->p_fsz_ctl) {
272 			VOP_RWUNLOCK(vp, rwflag, NULL);
273 
274 			mutex_enter(&curproc->p_lock);
275 			(void) rctl_action(rctlproc_legacy[RLIMIT_FSIZE],
276 			    curproc->p_rctls, curproc, RCA_UNSAFE_SIGINFO);
277 			mutex_exit(&curproc->p_lock);
278 
279 			error = EFBIG;
280 			goto out;
281 		}
282 		/*
283 		 * We return EFBIG if write is done at an offset
284 		 * greater than the offset maximum for this file structure.
285 		 */
286 
287 		if (fileoff >= OFFSET_MAX(fp)) {
288 			VOP_RWUNLOCK(vp, rwflag, NULL);
289 			error = EFBIG;
290 			goto out;
291 		}
292 		/*
293 		 * Limit the bytes to be written  upto offset maximum for
294 		 * this open file structure.
295 		 */
296 		if (fileoff + cnt > OFFSET_MAX(fp))
297 			cnt = (ssize_t)(OFFSET_MAX(fp) - fileoff);
298 	}
299 	auio.uio_loffset = fileoff;
300 	auio.uio_iov = &aiov;
301 	auio.uio_iovcnt = 1;
302 	auio.uio_resid = bcount = cnt;
303 	auio.uio_segflg = UIO_USERSPACE;
304 	auio.uio_llimit = curproc->p_fsz_ctl;
305 	auio.uio_fmode = fflag;
306 	auio.uio_extflg = UIO_COPY_DEFAULT;
307 
308 	ioflag = auio.uio_fmode & (FAPPEND|FSYNC|FDSYNC|FRSYNC);
309 
310 	error = VOP_WRITE(vp, &auio, ioflag, fp->f_cred, NULL);
311 	cnt -= auio.uio_resid;
312 	CPU_STATS_ENTER_K();
313 	cp = CPU;
314 	CPU_STATS_ADDQ(cp, sys, syswrite, 1);
315 	CPU_STATS_ADDQ(cp, sys, writech, (ulong_t)cnt);
316 	CPU_STATS_EXIT_K();
317 	ttolwp(curthread)->lwp_ru.ioch += (ulong_t)cnt;
318 
319 	if (vp->v_type == VFIFO)	/* Backward compatibility */
320 		fp->f_offset = cnt;
321 	else if (((fp->f_flag & FAPPEND) == 0) ||
322 	    (vp->v_type != VREG) || (bcount != 0))	/* POSIX */
323 		fp->f_offset = auio.uio_loffset;
324 	VOP_RWUNLOCK(vp, rwflag, NULL);
325 
326 	if (error == EINTR && cnt != 0)
327 		error = 0;
328 out:
329 	if (in_crit)
330 		nbl_end_crit(vp);
331 	releasef(fdes);
332 	if (error)
333 		return (set_errno(error));
334 	return (cnt);
335 }
336 
337 ssize_t
338 pread(int fdes, void *cbuf, size_t count, off_t offset)
339 {
340 	struct uio auio;
341 	struct iovec aiov;
342 	file_t *fp;
343 	register vnode_t *vp;
344 	struct cpu *cp;
345 	int fflag, ioflag, rwflag;
346 	ssize_t bcount;
347 	int error = 0;
348 	u_offset_t fileoff = (u_offset_t)(ulong_t)offset;
349 #ifdef _SYSCALL32_IMPL
350 	u_offset_t maxoff = get_udatamodel() == DATAMODEL_ILP32 ?
351 	    MAXOFF32_T : MAXOFFSET_T;
352 #else
353 	const u_offset_t maxoff = MAXOFF32_T;
354 #endif
355 	int in_crit = 0;
356 
357 	if ((bcount = (ssize_t)count) < 0)
358 		return (set_errno(EINVAL));
359 
360 	if ((fp = getf(fdes)) == NULL)
361 		return (set_errno(EBADF));
362 	if (((fflag = fp->f_flag) & (FREAD)) == 0) {
363 		error = EBADF;
364 		goto out;
365 	}
366 
367 	rwflag = 0;
368 	vp = fp->f_vnode;
369 
370 	if (vp->v_type == VREG) {
371 
372 		if (bcount == 0)
373 			goto out;
374 
375 		/*
376 		 * Return EINVAL if an invalid offset comes to pread.
377 		 * Negative offset from user will cause this error.
378 		 */
379 
380 		if (fileoff > maxoff) {
381 			error = EINVAL;
382 			goto out;
383 		}
384 		/*
385 		 * Limit offset such that we don't read or write
386 		 * a file beyond the maximum offset representable in
387 		 * an off_t structure.
388 		 */
389 		if (fileoff + bcount > maxoff)
390 			bcount = (ssize_t)((offset_t)maxoff - fileoff);
391 	} else if (vp->v_type == VFIFO) {
392 		error = ESPIPE;
393 		goto out;
394 	}
395 
396 	/*
397 	 * We have to enter the critical region before calling VOP_RWLOCK
398 	 * to avoid a deadlock with ufs.
399 	 */
400 	if (nbl_need_check(vp)) {
401 		int svmand;
402 
403 		nbl_start_crit(vp, RW_READER);
404 		in_crit = 1;
405 		error = nbl_svmand(vp, fp->f_cred, &svmand);
406 		if (error != 0)
407 			goto out;
408 		if (nbl_conflict(vp, NBL_READ, fileoff, bcount, svmand,
409 		    NULL)) {
410 			error = EACCES;
411 			goto out;
412 		}
413 	}
414 
415 	aiov.iov_base = cbuf;
416 	aiov.iov_len = bcount;
417 	(void) VOP_RWLOCK(vp, rwflag, NULL);
418 	if (vp->v_type == VREG && fileoff == (u_offset_t)maxoff) {
419 		struct vattr va;
420 		va.va_mask = AT_SIZE;
421 		if ((error = VOP_GETATTR(vp, &va, 0, fp->f_cred, NULL))) {
422 			VOP_RWUNLOCK(vp, rwflag, NULL);
423 			goto out;
424 		}
425 		VOP_RWUNLOCK(vp, rwflag, NULL);
426 
427 		/*
428 		 * We have to return EOF if fileoff is >= file size.
429 		 */
430 		if (fileoff >= va.va_size) {
431 			bcount = 0;
432 			goto out;
433 		}
434 
435 		/*
436 		 * File is greater than or equal to maxoff and therefore
437 		 * we return EOVERFLOW.
438 		 */
439 		error = EOVERFLOW;
440 		goto out;
441 	}
442 	auio.uio_loffset = fileoff;
443 	auio.uio_iov = &aiov;
444 	auio.uio_iovcnt = 1;
445 	auio.uio_resid = bcount;
446 	auio.uio_segflg = UIO_USERSPACE;
447 	auio.uio_llimit = MAXOFFSET_T;
448 	auio.uio_fmode = fflag;
449 	auio.uio_extflg = UIO_COPY_CACHED;
450 
451 	ioflag = auio.uio_fmode & (FAPPEND|FSYNC|FDSYNC|FRSYNC);
452 
453 	/* If read sync is not asked for, filter sync flags */
454 	if ((ioflag & FRSYNC) == 0)
455 		ioflag &= ~(FSYNC|FDSYNC);
456 	error = VOP_READ(vp, &auio, ioflag, fp->f_cred, NULL);
457 	bcount -= auio.uio_resid;
458 	CPU_STATS_ENTER_K();
459 	cp = CPU;
460 	CPU_STATS_ADDQ(cp, sys, sysread, 1);
461 	CPU_STATS_ADDQ(cp, sys, readch, (ulong_t)bcount);
462 	CPU_STATS_EXIT_K();
463 	ttolwp(curthread)->lwp_ru.ioch += (ulong_t)bcount;
464 	VOP_RWUNLOCK(vp, rwflag, NULL);
465 
466 	if (error == EINTR && bcount != 0)
467 		error = 0;
468 out:
469 	if (in_crit)
470 		nbl_end_crit(vp);
471 	releasef(fdes);
472 	if (error)
473 		return (set_errno(error));
474 	return (bcount);
475 }
476 
477 ssize_t
478 pwrite(int fdes, void *cbuf, size_t count, off_t offset)
479 {
480 	struct uio auio;
481 	struct iovec aiov;
482 	file_t *fp;
483 	register vnode_t *vp;
484 	struct cpu *cp;
485 	int fflag, ioflag, rwflag;
486 	ssize_t bcount;
487 	int error = 0;
488 	u_offset_t fileoff = (u_offset_t)(ulong_t)offset;
489 #ifdef _SYSCALL32_IMPL
490 	u_offset_t maxoff = get_udatamodel() == DATAMODEL_ILP32 ?
491 	    MAXOFF32_T : MAXOFFSET_T;
492 #else
493 	const u_offset_t maxoff = MAXOFF32_T;
494 #endif
495 	int in_crit = 0;
496 
497 	if ((bcount = (ssize_t)count) < 0)
498 		return (set_errno(EINVAL));
499 	if ((fp = getf(fdes)) == NULL)
500 		return (set_errno(EBADF));
501 	if (((fflag = fp->f_flag) & (FWRITE)) == 0) {
502 		error = EBADF;
503 		goto out;
504 	}
505 
506 	rwflag = 1;
507 	vp = fp->f_vnode;
508 
509 	if (vp->v_type == VREG) {
510 
511 		if (bcount == 0)
512 			goto out;
513 
514 		/*
515 		 * return EINVAL for offsets that cannot be
516 		 * represented in an off_t.
517 		 */
518 		if (fileoff > maxoff) {
519 			error = EINVAL;
520 			goto out;
521 		}
522 		/*
523 		 * Take appropriate action if we are trying to write above the
524 		 * resource limit.
525 		 */
526 		if (fileoff >= curproc->p_fsz_ctl) {
527 			mutex_enter(&curproc->p_lock);
528 			(void) rctl_action(rctlproc_legacy[RLIMIT_FSIZE],
529 			    curproc->p_rctls, curproc, RCA_UNSAFE_SIGINFO);
530 			mutex_exit(&curproc->p_lock);
531 
532 			error = EFBIG;
533 			goto out;
534 		}
535 		/*
536 		 * Don't allow pwrite to cause file sizes to exceed
537 		 * maxoff.
538 		 */
539 		if (fileoff == maxoff) {
540 			error = EFBIG;
541 			goto out;
542 		}
543 		if (fileoff + count > maxoff)
544 			bcount = (ssize_t)((u_offset_t)maxoff - fileoff);
545 	} else if (vp->v_type == VFIFO) {
546 		error = ESPIPE;
547 		goto out;
548 	}
549 
550 	/*
551 	 * We have to enter the critical region before calling VOP_RWLOCK
552 	 * to avoid a deadlock with ufs.
553 	 */
554 	if (nbl_need_check(vp)) {
555 		int svmand;
556 
557 		nbl_start_crit(vp, RW_READER);
558 		in_crit = 1;
559 		error = nbl_svmand(vp, fp->f_cred, &svmand);
560 		if (error != 0)
561 			goto out;
562 		if (nbl_conflict(vp, NBL_WRITE, fileoff, bcount, svmand,
563 		    NULL)) {
564 			error = EACCES;
565 			goto out;
566 		}
567 	}
568 
569 	aiov.iov_base = cbuf;
570 	aiov.iov_len = bcount;
571 	(void) VOP_RWLOCK(vp, rwflag, NULL);
572 	auio.uio_loffset = fileoff;
573 	auio.uio_iov = &aiov;
574 	auio.uio_iovcnt = 1;
575 	auio.uio_resid = bcount;
576 	auio.uio_segflg = UIO_USERSPACE;
577 	auio.uio_llimit = curproc->p_fsz_ctl;
578 	auio.uio_fmode = fflag;
579 	auio.uio_extflg = UIO_COPY_CACHED;
580 
581 	/*
582 	 * The SUSv4 POSIX specification states:
583 	 *	The pwrite() function shall be equivalent to write(), except
584 	 *	that it writes into a given position and does not change
585 	 *	the file offset (regardless of whether O_APPEND is set).
586 	 * To make this be true, we omit the FAPPEND flag from ioflag.
587 	 */
588 	ioflag = auio.uio_fmode & (FSYNC|FDSYNC|FRSYNC);
589 
590 	error = VOP_WRITE(vp, &auio, ioflag, fp->f_cred, NULL);
591 	bcount -= auio.uio_resid;
592 	CPU_STATS_ENTER_K();
593 	cp = CPU;
594 	CPU_STATS_ADDQ(cp, sys, syswrite, 1);
595 	CPU_STATS_ADDQ(cp, sys, writech, (ulong_t)bcount);
596 	CPU_STATS_EXIT_K();
597 	ttolwp(curthread)->lwp_ru.ioch += (ulong_t)bcount;
598 	VOP_RWUNLOCK(vp, rwflag, NULL);
599 
600 	if (error == EINTR && bcount != 0)
601 		error = 0;
602 out:
603 	if (in_crit)
604 		nbl_end_crit(vp);
605 	releasef(fdes);
606 	if (error)
607 		return (set_errno(error));
608 	return (bcount);
609 }
610 
611 /*
612  * XXX -- The SVID refers to IOV_MAX, but doesn't define it.  Grrrr....
613  * XXX -- However, SVVS expects readv() and writev() to fail if
614  * XXX -- iovcnt > 16 (yes, it's hard-coded in the SVVS source),
615  * XXX -- so I guess that's the "interface".
616  */
617 #define	DEF_IOV_MAX	16
618 
619 ssize_t
620 readv(int fdes, struct iovec *iovp, int iovcnt)
621 {
622 	struct uio auio;
623 	struct iovec aiov[DEF_IOV_MAX];
624 	file_t *fp;
625 	register vnode_t *vp;
626 	struct cpu *cp;
627 	int fflag, ioflag, rwflag;
628 	ssize_t count, bcount;
629 	int error = 0;
630 	int i;
631 	u_offset_t fileoff;
632 	int in_crit = 0;
633 
634 	if (iovcnt <= 0 || iovcnt > DEF_IOV_MAX)
635 		return (set_errno(EINVAL));
636 
637 #ifdef _SYSCALL32_IMPL
638 	/*
639 	 * 32-bit callers need to have their iovec expanded,
640 	 * while ensuring that they can't move more than 2Gbytes
641 	 * of data in a single call.
642 	 */
643 	if (get_udatamodel() == DATAMODEL_ILP32) {
644 		struct iovec32 aiov32[DEF_IOV_MAX];
645 		ssize32_t count32;
646 
647 		if (copyin(iovp, aiov32, iovcnt * sizeof (struct iovec32)))
648 			return (set_errno(EFAULT));
649 
650 		count32 = 0;
651 		for (i = 0; i < iovcnt; i++) {
652 			ssize32_t iovlen32 = aiov32[i].iov_len;
653 			count32 += iovlen32;
654 			if (iovlen32 < 0 || count32 < 0)
655 				return (set_errno(EINVAL));
656 			aiov[i].iov_len = iovlen32;
657 			aiov[i].iov_base =
658 			    (caddr_t)(uintptr_t)aiov32[i].iov_base;
659 		}
660 	} else
661 #endif
662 	if (copyin(iovp, aiov, iovcnt * sizeof (struct iovec)))
663 		return (set_errno(EFAULT));
664 
665 	count = 0;
666 	for (i = 0; i < iovcnt; i++) {
667 		ssize_t iovlen = aiov[i].iov_len;
668 		count += iovlen;
669 		if (iovlen < 0 || count < 0)
670 			return (set_errno(EINVAL));
671 	}
672 	if ((fp = getf(fdes)) == NULL)
673 		return (set_errno(EBADF));
674 	if (((fflag = fp->f_flag) & FREAD) == 0) {
675 		error = EBADF;
676 		goto out;
677 	}
678 	vp = fp->f_vnode;
679 	if (vp->v_type == VREG && count == 0) {
680 		goto out;
681 	}
682 
683 	rwflag = 0;
684 
685 	/*
686 	 * We have to enter the critical region before calling VOP_RWLOCK
687 	 * to avoid a deadlock with ufs.
688 	 */
689 	if (nbl_need_check(vp)) {
690 		int svmand;
691 
692 		nbl_start_crit(vp, RW_READER);
693 		in_crit = 1;
694 		error = nbl_svmand(vp, fp->f_cred, &svmand);
695 		if (error != 0)
696 			goto out;
697 		if (nbl_conflict(vp, NBL_READ, fp->f_offset, count, svmand,
698 		    NULL)) {
699 			error = EACCES;
700 			goto out;
701 		}
702 	}
703 
704 	(void) VOP_RWLOCK(vp, rwflag, NULL);
705 	fileoff = fp->f_offset;
706 
707 	/*
708 	 * Behaviour is same as read. Please see comments in read.
709 	 */
710 
711 	if ((vp->v_type == VREG) && (fileoff >= OFFSET_MAX(fp))) {
712 		struct vattr va;
713 		va.va_mask = AT_SIZE;
714 		if ((error = VOP_GETATTR(vp, &va, 0, fp->f_cred, NULL)))  {
715 			VOP_RWUNLOCK(vp, rwflag, NULL);
716 			goto out;
717 		}
718 		if (fileoff >= va.va_size) {
719 			VOP_RWUNLOCK(vp, rwflag, NULL);
720 			count = 0;
721 			goto out;
722 		} else {
723 			VOP_RWUNLOCK(vp, rwflag, NULL);
724 			error = EOVERFLOW;
725 			goto out;
726 		}
727 	}
728 	if ((vp->v_type == VREG) && (fileoff + count > OFFSET_MAX(fp))) {
729 		count = (ssize_t)(OFFSET_MAX(fp) - fileoff);
730 	}
731 	auio.uio_loffset = fileoff;
732 	auio.uio_iov = aiov;
733 	auio.uio_iovcnt = iovcnt;
734 	auio.uio_resid = bcount = count;
735 	auio.uio_segflg = UIO_USERSPACE;
736 	auio.uio_llimit = MAXOFFSET_T;
737 	auio.uio_fmode = fflag;
738 	if (bcount <= copyout_max_cached)
739 		auio.uio_extflg = UIO_COPY_CACHED;
740 	else
741 		auio.uio_extflg = UIO_COPY_DEFAULT;
742 
743 
744 	ioflag = auio.uio_fmode & (FAPPEND|FSYNC|FDSYNC|FRSYNC);
745 
746 	/* If read sync is not asked for, filter sync flags */
747 	if ((ioflag & FRSYNC) == 0)
748 		ioflag &= ~(FSYNC|FDSYNC);
749 	error = VOP_READ(vp, &auio, ioflag, fp->f_cred, NULL);
750 	count -= auio.uio_resid;
751 	CPU_STATS_ENTER_K();
752 	cp = CPU;
753 	CPU_STATS_ADDQ(cp, sys, sysread, 1);
754 	CPU_STATS_ADDQ(cp, sys, readch, (ulong_t)count);
755 	CPU_STATS_EXIT_K();
756 	ttolwp(curthread)->lwp_ru.ioch += (ulong_t)count;
757 
758 	if (vp->v_type == VFIFO)	/* Backward compatibility */
759 		fp->f_offset = count;
760 	else if (((fp->f_flag & FAPPEND) == 0) ||
761 	    (vp->v_type != VREG) || (bcount != 0))	/* POSIX */
762 		fp->f_offset = auio.uio_loffset;
763 
764 	VOP_RWUNLOCK(vp, rwflag, NULL);
765 
766 	if (error == EINTR && count != 0)
767 		error = 0;
768 out:
769 	if (in_crit)
770 		nbl_end_crit(vp);
771 	releasef(fdes);
772 	if (error)
773 		return (set_errno(error));
774 	return (count);
775 }
776 
777 ssize_t
778 writev(int fdes, struct iovec *iovp, int iovcnt)
779 {
780 	struct uio auio;
781 	struct iovec aiov[DEF_IOV_MAX];
782 	file_t *fp;
783 	register vnode_t *vp;
784 	struct cpu *cp;
785 	int fflag, ioflag, rwflag;
786 	ssize_t count, bcount;
787 	int error = 0;
788 	int i;
789 	u_offset_t fileoff;
790 	int in_crit = 0;
791 
792 	if (iovcnt <= 0 || iovcnt > DEF_IOV_MAX)
793 		return (set_errno(EINVAL));
794 
795 #ifdef _SYSCALL32_IMPL
796 	/*
797 	 * 32-bit callers need to have their iovec expanded,
798 	 * while ensuring that they can't move more than 2Gbytes
799 	 * of data in a single call.
800 	 */
801 	if (get_udatamodel() == DATAMODEL_ILP32) {
802 		struct iovec32 aiov32[DEF_IOV_MAX];
803 		ssize32_t count32;
804 
805 		if (copyin(iovp, aiov32, iovcnt * sizeof (struct iovec32)))
806 			return (set_errno(EFAULT));
807 
808 		count32 = 0;
809 		for (i = 0; i < iovcnt; i++) {
810 			ssize32_t iovlen = aiov32[i].iov_len;
811 			count32 += iovlen;
812 			if (iovlen < 0 || count32 < 0)
813 				return (set_errno(EINVAL));
814 			aiov[i].iov_len = iovlen;
815 			aiov[i].iov_base =
816 			    (caddr_t)(uintptr_t)aiov32[i].iov_base;
817 		}
818 	} else
819 #endif
820 	if (copyin(iovp, aiov, iovcnt * sizeof (struct iovec)))
821 		return (set_errno(EFAULT));
822 
823 	count = 0;
824 	for (i = 0; i < iovcnt; i++) {
825 		ssize_t iovlen = aiov[i].iov_len;
826 		count += iovlen;
827 		if (iovlen < 0 || count < 0)
828 			return (set_errno(EINVAL));
829 	}
830 	if ((fp = getf(fdes)) == NULL)
831 		return (set_errno(EBADF));
832 	if (((fflag = fp->f_flag) & FWRITE) == 0) {
833 		error = EBADF;
834 		goto out;
835 	}
836 	vp = fp->f_vnode;
837 	if (vp->v_type == VREG && count == 0) {
838 		goto out;
839 	}
840 
841 	rwflag = 1;
842 
843 	/*
844 	 * We have to enter the critical region before calling VOP_RWLOCK
845 	 * to avoid a deadlock with ufs.
846 	 */
847 	if (nbl_need_check(vp)) {
848 		int svmand;
849 
850 		nbl_start_crit(vp, RW_READER);
851 		in_crit = 1;
852 		error = nbl_svmand(vp, fp->f_cred, &svmand);
853 		if (error != 0)
854 			goto out;
855 		if (nbl_conflict(vp, NBL_WRITE, fp->f_offset, count, svmand,
856 		    NULL)) {
857 			error = EACCES;
858 			goto out;
859 		}
860 	}
861 
862 	(void) VOP_RWLOCK(vp, rwflag, NULL);
863 
864 	fileoff = fp->f_offset;
865 
866 	/*
867 	 * Behaviour is same as write. Please see comments for write.
868 	 */
869 
870 	if (vp->v_type == VREG) {
871 		if (fileoff >= curproc->p_fsz_ctl) {
872 			VOP_RWUNLOCK(vp, rwflag, NULL);
873 			mutex_enter(&curproc->p_lock);
874 			(void) rctl_action(rctlproc_legacy[RLIMIT_FSIZE],
875 			    curproc->p_rctls, curproc, RCA_UNSAFE_SIGINFO);
876 			mutex_exit(&curproc->p_lock);
877 			error = EFBIG;
878 			goto out;
879 		}
880 		if (fileoff >= OFFSET_MAX(fp)) {
881 			VOP_RWUNLOCK(vp, rwflag, NULL);
882 			error = EFBIG;
883 			goto out;
884 		}
885 		if (fileoff + count > OFFSET_MAX(fp))
886 			count = (ssize_t)(OFFSET_MAX(fp) - fileoff);
887 	}
888 	auio.uio_loffset = fileoff;
889 	auio.uio_iov = aiov;
890 	auio.uio_iovcnt = iovcnt;
891 	auio.uio_resid = bcount = count;
892 	auio.uio_segflg = UIO_USERSPACE;
893 	auio.uio_llimit = curproc->p_fsz_ctl;
894 	auio.uio_fmode = fflag;
895 	auio.uio_extflg = UIO_COPY_DEFAULT;
896 
897 	ioflag = auio.uio_fmode & (FAPPEND|FSYNC|FDSYNC|FRSYNC);
898 
899 	error = VOP_WRITE(vp, &auio, ioflag, fp->f_cred, NULL);
900 	count -= auio.uio_resid;
901 	CPU_STATS_ENTER_K();
902 	cp = CPU;
903 	CPU_STATS_ADDQ(cp, sys, syswrite, 1);
904 	CPU_STATS_ADDQ(cp, sys, writech, (ulong_t)count);
905 	CPU_STATS_EXIT_K();
906 	ttolwp(curthread)->lwp_ru.ioch += (ulong_t)count;
907 
908 	if (vp->v_type == VFIFO)	/* Backward compatibility */
909 		fp->f_offset = count;
910 	else if (((fp->f_flag & FAPPEND) == 0) ||
911 	    (vp->v_type != VREG) || (bcount != 0))	/* POSIX */
912 		fp->f_offset = auio.uio_loffset;
913 	VOP_RWUNLOCK(vp, rwflag, NULL);
914 
915 	if (error == EINTR && count != 0)
916 		error = 0;
917 out:
918 	if (in_crit)
919 		nbl_end_crit(vp);
920 	releasef(fdes);
921 	if (error)
922 		return (set_errno(error));
923 	return (count);
924 }
925 
926 #if defined(_SYSCALL32_IMPL) || defined(_ILP32)
927 
928 /*
929  * This syscall supplies 64-bit file offsets to 32-bit applications only.
930  */
931 ssize32_t
932 pread64(int fdes, void *cbuf, size32_t count, uint32_t offset_1,
933     uint32_t offset_2)
934 {
935 	struct uio auio;
936 	struct iovec aiov;
937 	file_t *fp;
938 	register vnode_t *vp;
939 	struct cpu *cp;
940 	int fflag, ioflag, rwflag;
941 	ssize_t bcount;
942 	int error = 0;
943 	u_offset_t fileoff;
944 	int in_crit = 0;
945 
946 #if defined(_LITTLE_ENDIAN)
947 	fileoff = ((u_offset_t)offset_2 << 32) | (u_offset_t)offset_1;
948 #else
949 	fileoff = ((u_offset_t)offset_1 << 32) | (u_offset_t)offset_2;
950 #endif
951 
952 	if ((bcount = (ssize_t)count) < 0 || bcount > INT32_MAX)
953 		return (set_errno(EINVAL));
954 
955 	if ((fp = getf(fdes)) == NULL)
956 		return (set_errno(EBADF));
957 	if (((fflag = fp->f_flag) & (FREAD)) == 0) {
958 		error = EBADF;
959 		goto out;
960 	}
961 
962 	rwflag = 0;
963 	vp = fp->f_vnode;
964 
965 	if (vp->v_type == VREG) {
966 
967 		if (bcount == 0)
968 			goto out;
969 
970 		/*
971 		 * Same as pread. See comments in pread.
972 		 */
973 
974 		if (fileoff > MAXOFFSET_T) {
975 			error = EINVAL;
976 			goto out;
977 		}
978 		if (fileoff + bcount > MAXOFFSET_T)
979 			bcount = (ssize_t)(MAXOFFSET_T - fileoff);
980 	} else if (vp->v_type == VFIFO) {
981 		error = ESPIPE;
982 		goto out;
983 	}
984 
985 	/*
986 	 * We have to enter the critical region before calling VOP_RWLOCK
987 	 * to avoid a deadlock with ufs.
988 	 */
989 	if (nbl_need_check(vp)) {
990 		int svmand;
991 
992 		nbl_start_crit(vp, RW_READER);
993 		in_crit = 1;
994 		error = nbl_svmand(vp, fp->f_cred, &svmand);
995 		if (error != 0)
996 			goto out;
997 		if (nbl_conflict(vp, NBL_READ, fileoff, bcount, svmand,
998 		    NULL)) {
999 			error = EACCES;
1000 			goto out;
1001 		}
1002 	}
1003 
1004 	aiov.iov_base = cbuf;
1005 	aiov.iov_len = bcount;
1006 	(void) VOP_RWLOCK(vp, rwflag, NULL);
1007 	auio.uio_loffset = fileoff;
1008 
1009 	/*
1010 	 * Note: File size can never be greater than MAXOFFSET_T.
1011 	 * If ever we start supporting 128 bit files the code
1012 	 * similar to the one in pread at this place should be here.
1013 	 * Here we avoid the unnecessary VOP_GETATTR() when we
1014 	 * know that fileoff == MAXOFFSET_T implies that it is always
1015 	 * greater than or equal to file size.
1016 	 */
1017 	auio.uio_iov = &aiov;
1018 	auio.uio_iovcnt = 1;
1019 	auio.uio_resid = bcount;
1020 	auio.uio_segflg = UIO_USERSPACE;
1021 	auio.uio_llimit = MAXOFFSET_T;
1022 	auio.uio_fmode = fflag;
1023 	auio.uio_extflg = UIO_COPY_CACHED;
1024 
1025 	ioflag = auio.uio_fmode & (FAPPEND|FSYNC|FDSYNC|FRSYNC);
1026 
1027 	/* If read sync is not asked for, filter sync flags */
1028 	if ((ioflag & FRSYNC) == 0)
1029 		ioflag &= ~(FSYNC|FDSYNC);
1030 	error = VOP_READ(vp, &auio, ioflag, fp->f_cred, NULL);
1031 	bcount -= auio.uio_resid;
1032 	CPU_STATS_ENTER_K();
1033 	cp = CPU;
1034 	CPU_STATS_ADDQ(cp, sys, sysread, 1);
1035 	CPU_STATS_ADDQ(cp, sys, readch, (ulong_t)bcount);
1036 	CPU_STATS_EXIT_K();
1037 	ttolwp(curthread)->lwp_ru.ioch += (ulong_t)bcount;
1038 	VOP_RWUNLOCK(vp, rwflag, NULL);
1039 
1040 	if (error == EINTR && bcount != 0)
1041 		error = 0;
1042 out:
1043 	if (in_crit)
1044 		nbl_end_crit(vp);
1045 	releasef(fdes);
1046 	if (error)
1047 		return (set_errno(error));
1048 	return (bcount);
1049 }
1050 
1051 /*
1052  * This syscall supplies 64-bit file offsets to 32-bit applications only.
1053  */
1054 ssize32_t
1055 pwrite64(int fdes, void *cbuf, size32_t count, uint32_t offset_1,
1056     uint32_t offset_2)
1057 {
1058 	struct uio auio;
1059 	struct iovec aiov;
1060 	file_t *fp;
1061 	register vnode_t *vp;
1062 	struct cpu *cp;
1063 	int fflag, ioflag, rwflag;
1064 	ssize_t bcount;
1065 	int error = 0;
1066 	u_offset_t fileoff;
1067 	int in_crit = 0;
1068 
1069 #if defined(_LITTLE_ENDIAN)
1070 	fileoff = ((u_offset_t)offset_2 << 32) | (u_offset_t)offset_1;
1071 #else
1072 	fileoff = ((u_offset_t)offset_1 << 32) | (u_offset_t)offset_2;
1073 #endif
1074 
1075 	if ((bcount = (ssize_t)count) < 0 || bcount > INT32_MAX)
1076 		return (set_errno(EINVAL));
1077 	if ((fp = getf(fdes)) == NULL)
1078 		return (set_errno(EBADF));
1079 	if (((fflag = fp->f_flag) & (FWRITE)) == 0) {
1080 		error = EBADF;
1081 		goto out;
1082 	}
1083 
1084 	rwflag = 1;
1085 	vp = fp->f_vnode;
1086 
1087 	if (vp->v_type == VREG) {
1088 
1089 		if (bcount == 0)
1090 			goto out;
1091 
1092 		/*
1093 		 * See comments in pwrite.
1094 		 */
1095 		if (fileoff > MAXOFFSET_T) {
1096 			error = EINVAL;
1097 			goto out;
1098 		}
1099 		if (fileoff >= curproc->p_fsz_ctl) {
1100 			mutex_enter(&curproc->p_lock);
1101 			(void) rctl_action(rctlproc_legacy[RLIMIT_FSIZE],
1102 			    curproc->p_rctls, curproc, RCA_SAFE);
1103 			mutex_exit(&curproc->p_lock);
1104 			error = EFBIG;
1105 			goto out;
1106 		}
1107 		if (fileoff == MAXOFFSET_T) {
1108 			error = EFBIG;
1109 			goto out;
1110 		}
1111 		if (fileoff + bcount > MAXOFFSET_T)
1112 			bcount = (ssize_t)((u_offset_t)MAXOFFSET_T - fileoff);
1113 	} else if (vp->v_type == VFIFO) {
1114 		error = ESPIPE;
1115 		goto out;
1116 	}
1117 
1118 	/*
1119 	 * We have to enter the critical region before calling VOP_RWLOCK
1120 	 * to avoid a deadlock with ufs.
1121 	 */
1122 	if (nbl_need_check(vp)) {
1123 		int svmand;
1124 
1125 		nbl_start_crit(vp, RW_READER);
1126 		in_crit = 1;
1127 		error = nbl_svmand(vp, fp->f_cred, &svmand);
1128 		if (error != 0)
1129 			goto out;
1130 		if (nbl_conflict(vp, NBL_WRITE, fileoff, bcount, svmand,
1131 		    NULL)) {
1132 			error = EACCES;
1133 			goto out;
1134 		}
1135 	}
1136 
1137 	aiov.iov_base = cbuf;
1138 	aiov.iov_len = bcount;
1139 	(void) VOP_RWLOCK(vp, rwflag, NULL);
1140 	auio.uio_loffset = fileoff;
1141 	auio.uio_iov = &aiov;
1142 	auio.uio_iovcnt = 1;
1143 	auio.uio_resid = bcount;
1144 	auio.uio_segflg = UIO_USERSPACE;
1145 	auio.uio_llimit = curproc->p_fsz_ctl;
1146 	auio.uio_fmode = fflag;
1147 	auio.uio_extflg = UIO_COPY_CACHED;
1148 
1149 	/*
1150 	 * The SUSv4 POSIX specification states:
1151 	 *	The pwrite() function shall be equivalent to write(), except
1152 	 *	that it writes into a given position and does not change
1153 	 *	the file offset (regardless of whether O_APPEND is set).
1154 	 * To make this be true, we omit the FAPPEND flag from ioflag.
1155 	 */
1156 	ioflag = auio.uio_fmode & (FSYNC|FDSYNC|FRSYNC);
1157 
1158 	error = VOP_WRITE(vp, &auio, ioflag, fp->f_cred, NULL);
1159 	bcount -= auio.uio_resid;
1160 	CPU_STATS_ENTER_K();
1161 	cp = CPU;
1162 	CPU_STATS_ADDQ(cp, sys, syswrite, 1);
1163 	CPU_STATS_ADDQ(cp, sys, writech, (ulong_t)bcount);
1164 	CPU_STATS_EXIT_K();
1165 	ttolwp(curthread)->lwp_ru.ioch += (ulong_t)bcount;
1166 	VOP_RWUNLOCK(vp, rwflag, NULL);
1167 
1168 	if (error == EINTR && bcount != 0)
1169 		error = 0;
1170 out:
1171 	if (in_crit)
1172 		nbl_end_crit(vp);
1173 	releasef(fdes);
1174 	if (error)
1175 		return (set_errno(error));
1176 	return (bcount);
1177 }
1178 
1179 #endif	/* _SYSCALL32_IMPL || _ILP32 */
1180 
1181 #ifdef _SYSCALL32_IMPL
1182 /*
1183  * Tail-call elimination of xxx32() down to xxx()
1184  *
1185  * A number of xxx32 system calls take a len (or count) argument and
1186  * return a number in the range [0,len] or -1 on error.
1187  * Given an ssize32_t input len, the downcall xxx() will return
1188  * a 64-bit value that is -1 or in the range [0,len] which actually
1189  * is a proper return value for the xxx32 call. So even if the xxx32
1190  * calls can be considered as returning a ssize32_t, they are currently
1191  * declared as returning a ssize_t as this enables tail-call elimination.
1192  *
1193  * The cast of len (or count) to ssize32_t is needed to ensure we pass
1194  * down negative input values as such and let the downcall handle error
1195  * reporting. Functions covered by this comments are:
1196  *
1197  * rw.c:           read32, write32, pread32, pwrite32, readv32, writev32.
1198  * socksyscall.c:  recv32, recvfrom32, send32, sendto32.
1199  * readlink.c:     readlink32.
1200  */
1201 
1202 ssize_t
1203 read32(int32_t fdes, caddr32_t cbuf, size32_t count)
1204 {
1205 	return (read(fdes,
1206 	    (void *)(uintptr_t)cbuf, (ssize32_t)count));
1207 }
1208 
1209 ssize_t
1210 write32(int32_t fdes, caddr32_t cbuf, size32_t count)
1211 {
1212 	return (write(fdes,
1213 	    (void *)(uintptr_t)cbuf, (ssize32_t)count));
1214 }
1215 
1216 ssize_t
1217 pread32(int32_t fdes, caddr32_t cbuf, size32_t count, off32_t offset)
1218 {
1219 	return (pread(fdes,
1220 	    (void *)(uintptr_t)cbuf, (ssize32_t)count,
1221 	    (off_t)(uint32_t)offset));
1222 }
1223 
1224 ssize_t
1225 pwrite32(int32_t fdes, caddr32_t cbuf, size32_t count, off32_t offset)
1226 {
1227 	return (pwrite(fdes,
1228 	    (void *)(uintptr_t)cbuf, (ssize32_t)count,
1229 	    (off_t)(uint32_t)offset));
1230 }
1231 
1232 ssize_t
1233 readv32(int32_t fdes, caddr32_t iovp, int32_t iovcnt)
1234 {
1235 	return (readv(fdes, (void *)(uintptr_t)iovp, iovcnt));
1236 }
1237 
1238 ssize_t
1239 writev32(int32_t fdes, caddr32_t iovp, int32_t iovcnt)
1240 {
1241 	return (writev(fdes, (void *)(uintptr_t)iovp, iovcnt));
1242 }
1243 
1244 #endif	/* _SYSCALL32_IMPL */
1245