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 /* ONC_PLUS EXTRACT START */
23 /*
24 * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
25 * Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved.
26 */
27
28 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
30
31 /*
32 * Portions of this source code were derived from Berkeley 4.3 BSD
33 * under license from the Regents of the University of California.
34 */
35
36
37 /* ONC_PLUS EXTRACT END */
38
39 #include <sys/param.h>
40 #include <sys/isa_defs.h>
41 #include <sys/types.h>
42 #include <sys/sysmacros.h>
43 #include <sys/systm.h>
44 #include <sys/errno.h>
45 #include <sys/fcntl.h>
46 /* ONC_PLUS EXTRACT START */
47 #include <sys/flock.h>
48 /* ONC_PLUS EXTRACT END */
49 #include <sys/vnode.h>
50 #include <sys/file.h>
51 #include <sys/mode.h>
52 #include <sys/proc.h>
53 #include <sys/filio.h>
54 #include <sys/share.h>
55 #include <sys/debug.h>
56 #include <sys/rctl.h>
57 #include <sys/nbmlock.h>
58
59 #include <sys/cmn_err.h>
60
61 /* ONC_PLUS EXTRACT START */
62 static int flock_check(vnode_t *, flock64_t *, offset_t, offset_t);
63 static int flock_get_start(vnode_t *, flock64_t *, offset_t, u_offset_t *);
64 static void fd_too_big(proc_t *);
65
66 /*
67 * File control.
68 */
69 int
70 fcntl(int fdes, int cmd, intptr_t arg)
71 {
72 int iarg;
73 int error = 0;
74 int retval;
75 proc_t *p;
76 file_t *fp;
77 vnode_t *vp;
78 u_offset_t offset;
79 u_offset_t start;
80 struct vattr vattr;
81 int in_crit;
133 }
134 goto out;
135
136 case F_BADFD:
137 if ((error = f_badfd(fdes, &fdres, (int)arg)) == 0)
138 retval = fdres;
139 goto out;
140 }
141
142 /*
143 * Second, for speed, deal with the subset of cases that
144 * require getf() / releasef() but do not require copyin.
145 */
146 if ((fp = getf(fdes)) == NULL) {
147 error = EBADF;
148 goto out;
149 }
150 iarg = (int)arg;
151
152 switch (cmd) {
153 /* ONC_PLUS EXTRACT END */
154
155 case F_DUPFD:
156 case F_DUPFD_CLOEXEC:
157 p = curproc;
158 if ((uint_t)iarg >= p->p_fno_ctl) {
159 if (iarg >= 0)
160 fd_too_big(p);
161 error = EINVAL;
162 goto done;
163 }
164 /*
165 * We need to increment the f_count reference counter
166 * before allocating a new file descriptor.
167 * Doing it other way round opens a window for race condition
168 * with closeandsetf() on the target file descriptor which can
169 * close the file still referenced by the original
170 * file descriptor.
171 */
172 mutex_enter(&fp->f_tlock);
173 fp->f_count++;
174 mutex_exit(&fp->f_tlock);
258 goto done;
259 }
260
261 /*
262 * Finally, deal with the expensive cases.
263 */
264 retval = 0;
265 in_crit = 0;
266 maxoffset = MAXOFF_T;
267 datamodel = DATAMODEL_NATIVE;
268 #if defined(_SYSCALL32_IMPL)
269 if ((datamodel = get_udatamodel()) == DATAMODEL_ILP32)
270 maxoffset = MAXOFF32_T;
271 #endif
272
273 vp = fp->f_vnode;
274 flag = fp->f_flag;
275 offset = fp->f_offset;
276
277 switch (cmd) {
278 /* ONC_PLUS EXTRACT START */
279 /*
280 * The file system and vnode layers understand and implement
281 * locking with flock64 structures. So here once we pass through
282 * the test for compatibility as defined by LFS API, (for F_SETLK,
283 * F_SETLKW, F_GETLK, F_GETLKW, F_FREESP) we transform
284 * the flock structure to a flock64 structure and send it to the
285 * lower layers. Similarly in case of GETLK the returned flock64
286 * structure is transformed to a flock structure if everything fits
287 * in nicely, otherwise we return EOVERFLOW.
288 */
289
290 case F_GETLK:
291 case F_O_GETLK:
292 case F_SETLK:
293 case F_SETLKW:
294 case F_SETLK_NBMAND:
295
296 /*
297 * Copy in input fields only.
298 */
433 if (bf.l_start > MAXOFF32_T ||
434 bf.l_len > MAXOFF32_T) {
435 error = EOVERFLOW;
436 break;
437 }
438 for (i = 0; i < 4; i++)
439 sbf32.l_pad[i] = 0;
440 sbf32.l_type = (int16_t)bf.l_type;
441 sbf32.l_whence = (int16_t)bf.l_whence;
442 sbf32.l_start = (off32_t)bf.l_start;
443 sbf32.l_len = (off32_t)bf.l_len;
444 sbf32.l_sysid = (int32_t)bf.l_sysid;
445 sbf32.l_pid = (pid32_t)bf.l_pid;
446 if (copyout(&sbf32,
447 (void *)arg, sizeof (sbf32)))
448 error = EFAULT;
449 }
450 #endif
451 }
452 break;
453 /* ONC_PLUS EXTRACT END */
454
455 case F_CHKFL:
456 /*
457 * This is for internal use only, to allow the vnode layer
458 * to validate a flags setting before applying it. User
459 * programs can't issue it.
460 */
461 error = EINVAL;
462 break;
463
464 case F_ALLOCSP:
465 case F_FREESP:
466 case F_ALLOCSP64:
467 case F_FREESP64:
468 /*
469 * Test for not-a-regular-file (and returning EINVAL)
470 * before testing for open-for-writing (and returning EBADF).
471 * This is relied upon by posix_fallocate() in libc.
472 */
473 if (vp->v_type != VREG) {
580 begin = start > vattr.va_size ? vattr.va_size : start;
581 length = vattr.va_size > start ? vattr.va_size - start :
582 start - vattr.va_size;
583 if (nbl_conflict(vp, NBL_WRITE, begin, length, 0,
584 NULL)) {
585 error = EACCES;
586 break;
587 }
588 }
589
590 if (cmd == F_ALLOCSP64)
591 cmd = F_ALLOCSP;
592 else if (cmd == F_FREESP64)
593 cmd = F_FREESP;
594
595 error = VOP_SPACE(vp, cmd, &bf, flag, offset, fp->f_cred, NULL);
596
597 break;
598
599 #if !defined(_LP64) || defined(_SYSCALL32_IMPL)
600 /* ONC_PLUS EXTRACT START */
601 case F_GETLK64:
602 case F_SETLK64:
603 case F_SETLKW64:
604 case F_SETLK64_NBMAND:
605 /*
606 * Large Files: Here we set cmd as *LK and send it to
607 * lower layers. *LK64 is only for the user land.
608 * Most of the comments described above for F_SETLK
609 * applies here too.
610 * Large File support is only needed for ILP32 apps!
611 */
612 if (datamodel != DATAMODEL_ILP32) {
613 error = EINVAL;
614 break;
615 }
616
617 if (cmd == F_GETLK64)
618 cmd = F_GETLK;
619 else if (cmd == F_SETLK64)
620 cmd = F_SETLK;
663
664 /*
665 * We do not want to assume that the flock64 structure
666 * is laid out in the same in ILP32 and LP64
667 * environments, so we will copy out the ILP32 version
668 * of flock64 explicitly after copying the native
669 * flock64 structure to it.
670 */
671 for (i = 0; i < 4; i++)
672 bf64_32.l_pad[i] = 0;
673 bf64_32.l_type = (int16_t)bf.l_type;
674 bf64_32.l_whence = (int16_t)bf.l_whence;
675 bf64_32.l_start = bf.l_start;
676 bf64_32.l_len = bf.l_len;
677 bf64_32.l_sysid = (int32_t)bf.l_sysid;
678 bf64_32.l_pid = (pid32_t)bf.l_pid;
679 if (copyout(&bf64_32, (void *)arg, sizeof (bf64_32)))
680 error = EFAULT;
681 }
682 break;
683 /* ONC_PLUS EXTRACT END */
684 #endif /* !defined(_LP64) || defined(_SYSCALL32_IMPL) */
685
686 /* ONC_PLUS EXTRACT START */
687 case F_SHARE:
688 case F_SHARE_NBMAND:
689 case F_UNSHARE:
690
691 /*
692 * Copy in input fields only.
693 */
694 if (copyin((void *)arg, &fsh, sizeof (fsh))) {
695 error = EFAULT;
696 break;
697 }
698
699 /*
700 * Local share reservations always have this simple form
701 */
702 shr.s_access = fsh.f_access;
703 shr.s_deny = fsh.f_deny;
704 shr.s_sysid = 0;
705 shr.s_pid = ttoproc(curthread)->p_pid;
706 shr_own.sl_pid = shr.s_pid;
707 shr_own.sl_id = fsh.f_id;
708 shr.s_own_len = sizeof (shr_own);
709 shr.s_owner = (caddr_t)&shr_own;
710 error = VOP_SHRLOCK(vp, cmd, &shr, flag, fp->f_cred, NULL);
711 /* ONC_PLUS EXTRACT END */
712 break;
713
714 default:
715 error = EINVAL;
716 break;
717 }
718
719 if (in_crit)
720 nbl_end_crit(vp);
721
722 done:
723 releasef(fdes);
724 out:
725 if (error)
726 return (set_errno(error));
727 return (retval);
728 }
729
730 /* ONC_PLUS EXTRACT START */
731 int
732 flock_check(vnode_t *vp, flock64_t *flp, offset_t offset, offset_t max)
733 {
734 struct vattr vattr;
735 int error;
736 u_offset_t start, end;
737
738 /*
739 * Determine the starting point of the request
740 */
741 switch (flp->l_whence) {
742 case 0: /* SEEK_SET */
743 start = (u_offset_t)flp->l_start;
744 if (start > max)
745 return (EINVAL);
746 break;
747 case 1: /* SEEK_CUR */
748 if (flp->l_start > (max - offset))
749 return (EOVERFLOW);
750 start = (u_offset_t)(flp->l_start + offset);
822 *start = (u_offset_t)(flp->l_start + (offset_t)vattr.va_size);
823 break;
824 default:
825 return (EINVAL);
826 }
827
828 return (0);
829 }
830
831 /*
832 * Take rctl action when the requested file descriptor is too big.
833 */
834 static void
835 fd_too_big(proc_t *p)
836 {
837 mutex_enter(&p->p_lock);
838 (void) rctl_action(rctlproc_legacy[RLIMIT_NOFILE],
839 p->p_rctls, p, RCA_SAFE);
840 mutex_exit(&p->p_lock);
841 }
842 /* ONC_PLUS EXTRACT END */
|
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 (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved.
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
36 #include <sys/param.h>
37 #include <sys/isa_defs.h>
38 #include <sys/types.h>
39 #include <sys/sysmacros.h>
40 #include <sys/systm.h>
41 #include <sys/errno.h>
42 #include <sys/fcntl.h>
43 #include <sys/flock.h>
44 #include <sys/vnode.h>
45 #include <sys/file.h>
46 #include <sys/mode.h>
47 #include <sys/proc.h>
48 #include <sys/filio.h>
49 #include <sys/share.h>
50 #include <sys/debug.h>
51 #include <sys/rctl.h>
52 #include <sys/nbmlock.h>
53
54 #include <sys/cmn_err.h>
55
56 static int flock_check(vnode_t *, flock64_t *, offset_t, offset_t);
57 static int flock_get_start(vnode_t *, flock64_t *, offset_t, u_offset_t *);
58 static void fd_too_big(proc_t *);
59
60 /*
61 * File control.
62 */
63 int
64 fcntl(int fdes, int cmd, intptr_t arg)
65 {
66 int iarg;
67 int error = 0;
68 int retval;
69 proc_t *p;
70 file_t *fp;
71 vnode_t *vp;
72 u_offset_t offset;
73 u_offset_t start;
74 struct vattr vattr;
75 int in_crit;
127 }
128 goto out;
129
130 case F_BADFD:
131 if ((error = f_badfd(fdes, &fdres, (int)arg)) == 0)
132 retval = fdres;
133 goto out;
134 }
135
136 /*
137 * Second, for speed, deal with the subset of cases that
138 * require getf() / releasef() but do not require copyin.
139 */
140 if ((fp = getf(fdes)) == NULL) {
141 error = EBADF;
142 goto out;
143 }
144 iarg = (int)arg;
145
146 switch (cmd) {
147 case F_DUPFD:
148 case F_DUPFD_CLOEXEC:
149 p = curproc;
150 if ((uint_t)iarg >= p->p_fno_ctl) {
151 if (iarg >= 0)
152 fd_too_big(p);
153 error = EINVAL;
154 goto done;
155 }
156 /*
157 * We need to increment the f_count reference counter
158 * before allocating a new file descriptor.
159 * Doing it other way round opens a window for race condition
160 * with closeandsetf() on the target file descriptor which can
161 * close the file still referenced by the original
162 * file descriptor.
163 */
164 mutex_enter(&fp->f_tlock);
165 fp->f_count++;
166 mutex_exit(&fp->f_tlock);
250 goto done;
251 }
252
253 /*
254 * Finally, deal with the expensive cases.
255 */
256 retval = 0;
257 in_crit = 0;
258 maxoffset = MAXOFF_T;
259 datamodel = DATAMODEL_NATIVE;
260 #if defined(_SYSCALL32_IMPL)
261 if ((datamodel = get_udatamodel()) == DATAMODEL_ILP32)
262 maxoffset = MAXOFF32_T;
263 #endif
264
265 vp = fp->f_vnode;
266 flag = fp->f_flag;
267 offset = fp->f_offset;
268
269 switch (cmd) {
270 /*
271 * The file system and vnode layers understand and implement
272 * locking with flock64 structures. So here once we pass through
273 * the test for compatibility as defined by LFS API, (for F_SETLK,
274 * F_SETLKW, F_GETLK, F_GETLKW, F_FREESP) we transform
275 * the flock structure to a flock64 structure and send it to the
276 * lower layers. Similarly in case of GETLK the returned flock64
277 * structure is transformed to a flock structure if everything fits
278 * in nicely, otherwise we return EOVERFLOW.
279 */
280
281 case F_GETLK:
282 case F_O_GETLK:
283 case F_SETLK:
284 case F_SETLKW:
285 case F_SETLK_NBMAND:
286
287 /*
288 * Copy in input fields only.
289 */
424 if (bf.l_start > MAXOFF32_T ||
425 bf.l_len > MAXOFF32_T) {
426 error = EOVERFLOW;
427 break;
428 }
429 for (i = 0; i < 4; i++)
430 sbf32.l_pad[i] = 0;
431 sbf32.l_type = (int16_t)bf.l_type;
432 sbf32.l_whence = (int16_t)bf.l_whence;
433 sbf32.l_start = (off32_t)bf.l_start;
434 sbf32.l_len = (off32_t)bf.l_len;
435 sbf32.l_sysid = (int32_t)bf.l_sysid;
436 sbf32.l_pid = (pid32_t)bf.l_pid;
437 if (copyout(&sbf32,
438 (void *)arg, sizeof (sbf32)))
439 error = EFAULT;
440 }
441 #endif
442 }
443 break;
444
445 case F_CHKFL:
446 /*
447 * This is for internal use only, to allow the vnode layer
448 * to validate a flags setting before applying it. User
449 * programs can't issue it.
450 */
451 error = EINVAL;
452 break;
453
454 case F_ALLOCSP:
455 case F_FREESP:
456 case F_ALLOCSP64:
457 case F_FREESP64:
458 /*
459 * Test for not-a-regular-file (and returning EINVAL)
460 * before testing for open-for-writing (and returning EBADF).
461 * This is relied upon by posix_fallocate() in libc.
462 */
463 if (vp->v_type != VREG) {
570 begin = start > vattr.va_size ? vattr.va_size : start;
571 length = vattr.va_size > start ? vattr.va_size - start :
572 start - vattr.va_size;
573 if (nbl_conflict(vp, NBL_WRITE, begin, length, 0,
574 NULL)) {
575 error = EACCES;
576 break;
577 }
578 }
579
580 if (cmd == F_ALLOCSP64)
581 cmd = F_ALLOCSP;
582 else if (cmd == F_FREESP64)
583 cmd = F_FREESP;
584
585 error = VOP_SPACE(vp, cmd, &bf, flag, offset, fp->f_cred, NULL);
586
587 break;
588
589 #if !defined(_LP64) || defined(_SYSCALL32_IMPL)
590 case F_GETLK64:
591 case F_SETLK64:
592 case F_SETLKW64:
593 case F_SETLK64_NBMAND:
594 /*
595 * Large Files: Here we set cmd as *LK and send it to
596 * lower layers. *LK64 is only for the user land.
597 * Most of the comments described above for F_SETLK
598 * applies here too.
599 * Large File support is only needed for ILP32 apps!
600 */
601 if (datamodel != DATAMODEL_ILP32) {
602 error = EINVAL;
603 break;
604 }
605
606 if (cmd == F_GETLK64)
607 cmd = F_GETLK;
608 else if (cmd == F_SETLK64)
609 cmd = F_SETLK;
652
653 /*
654 * We do not want to assume that the flock64 structure
655 * is laid out in the same in ILP32 and LP64
656 * environments, so we will copy out the ILP32 version
657 * of flock64 explicitly after copying the native
658 * flock64 structure to it.
659 */
660 for (i = 0; i < 4; i++)
661 bf64_32.l_pad[i] = 0;
662 bf64_32.l_type = (int16_t)bf.l_type;
663 bf64_32.l_whence = (int16_t)bf.l_whence;
664 bf64_32.l_start = bf.l_start;
665 bf64_32.l_len = bf.l_len;
666 bf64_32.l_sysid = (int32_t)bf.l_sysid;
667 bf64_32.l_pid = (pid32_t)bf.l_pid;
668 if (copyout(&bf64_32, (void *)arg, sizeof (bf64_32)))
669 error = EFAULT;
670 }
671 break;
672 #endif /* !defined(_LP64) || defined(_SYSCALL32_IMPL) */
673
674 case F_SHARE:
675 case F_SHARE_NBMAND:
676 case F_UNSHARE:
677
678 /*
679 * Copy in input fields only.
680 */
681 if (copyin((void *)arg, &fsh, sizeof (fsh))) {
682 error = EFAULT;
683 break;
684 }
685
686 /*
687 * Local share reservations always have this simple form
688 */
689 shr.s_access = fsh.f_access;
690 shr.s_deny = fsh.f_deny;
691 shr.s_sysid = 0;
692 shr.s_pid = ttoproc(curthread)->p_pid;
693 shr_own.sl_pid = shr.s_pid;
694 shr_own.sl_id = fsh.f_id;
695 shr.s_own_len = sizeof (shr_own);
696 shr.s_owner = (caddr_t)&shr_own;
697 error = VOP_SHRLOCK(vp, cmd, &shr, flag, fp->f_cred, NULL);
698 break;
699
700 default:
701 error = EINVAL;
702 break;
703 }
704
705 if (in_crit)
706 nbl_end_crit(vp);
707
708 done:
709 releasef(fdes);
710 out:
711 if (error)
712 return (set_errno(error));
713 return (retval);
714 }
715
716 int
717 flock_check(vnode_t *vp, flock64_t *flp, offset_t offset, offset_t max)
718 {
719 struct vattr vattr;
720 int error;
721 u_offset_t start, end;
722
723 /*
724 * Determine the starting point of the request
725 */
726 switch (flp->l_whence) {
727 case 0: /* SEEK_SET */
728 start = (u_offset_t)flp->l_start;
729 if (start > max)
730 return (EINVAL);
731 break;
732 case 1: /* SEEK_CUR */
733 if (flp->l_start > (max - offset))
734 return (EOVERFLOW);
735 start = (u_offset_t)(flp->l_start + offset);
807 *start = (u_offset_t)(flp->l_start + (offset_t)vattr.va_size);
808 break;
809 default:
810 return (EINVAL);
811 }
812
813 return (0);
814 }
815
816 /*
817 * Take rctl action when the requested file descriptor is too big.
818 */
819 static void
820 fd_too_big(proc_t *p)
821 {
822 mutex_enter(&p->p_lock);
823 (void) rctl_action(rctlproc_legacy[RLIMIT_NOFILE],
824 p->p_rctls, p, RCA_SAFE);
825 mutex_exit(&p->p_lock);
826 }
|