2 * Copyright (c) 2000-2013 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
28 /* Copyright (c) 1995, 1997 Apple Computer, Inc. All Rights Reserved */
30 * Copyright (c) 1982, 1986, 1989, 1991, 1993
31 * The Regents of the University of California. All rights reserved.
32 * (c) UNIX System Laboratories, Inc.
33 * All or some portions of this file are derived from material licensed
34 * to the University of California by American Telephone and Telegraph
35 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
36 * the permission of UNIX System Laboratories, Inc.
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. All advertising materials mentioning features or use of this software
47 * must display the following acknowledgement:
48 * This product includes software developed by the University of
49 * California, Berkeley and its contributors.
50 * 4. Neither the name of the University nor the names of its contributors
51 * may be used to endorse or promote products derived from this software
52 * without specific prior written permission.
54 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66 * @(#)kern_descrip.c 8.8 (Berkeley) 2/14/95
69 * NOTICE: This file was modified by SPARTA, Inc. in 2006 to introduce
70 * support for mandatory and extensible security protections. This notice
71 * is included in support of clause 2.2 (b) of the Apple Public License,
75 #include <sys/param.h>
76 #include <sys/systm.h>
77 #include <sys/filedesc.h>
78 #include <sys/kernel.h>
79 #include <sys/vnode_internal.h>
80 #include <sys/proc_internal.h>
81 #include <sys/kauth.h>
82 #include <sys/file_internal.h>
83 #include <sys/guarded.h>
84 #include <sys/socket.h>
85 #include <sys/socketvar.h>
87 #include <sys/ioctl.h>
88 #include <sys/fcntl.h>
89 #include <sys/malloc.h>
91 #include <sys/syslog.h>
92 #include <sys/unistd.h>
93 #include <sys/resourcevar.h>
94 #include <sys/aio_kern.h>
96 #include <kern/lock.h>
97 #include <sys/uio_internal.h>
98 #include <sys/codesign.h>
100 #include <security/audit/audit.h>
102 #include <sys/mount_internal.h>
103 #include <sys/kdebug.h>
104 #include <sys/sysproto.h>
105 #include <sys/pipe.h>
106 #include <sys/spawn.h>
107 #include <kern/kern_types.h>
108 #include <kern/kalloc.h>
109 #include <libkern/OSAtomic.h>
111 #include <sys/ubc_internal.h>
113 #include <kern/ipc_misc.h>
114 #include <vm/vm_protos.h>
116 #include <mach/mach_port.h>
119 #include <sys/cprotect.h>
123 kern_return_t
ipc_object_copyin(ipc_space_t
, mach_port_name_t
,
124 mach_msg_type_name_t
, ipc_port_t
*);
125 void ipc_port_release_send(ipc_port_t
);
130 static int finishdup(proc_t p
,
131 struct filedesc
*fdp
, int old
, int new, int flags
, int32_t *retval
);
133 int falloc_locked(proc_t p
, struct fileproc
**resultfp
, int *resultfd
, vfs_context_t ctx
, int locked
);
134 void fg_drop(struct fileproc
* fp
);
135 void fg_free(struct fileglob
*fg
);
136 void fg_ref(struct fileproc
* fp
);
137 void fileport_releasefg(struct fileglob
*fg
);
139 /* flags for close_internal_locked */
140 #define FD_DUP2RESV 1
142 /* We don't want these exported */
145 int unlink1(vfs_context_t
, struct nameidata
*, int);
147 static void _fdrelse(struct proc
* p
, int fd
);
150 extern void file_lock_init(void);
151 extern int kqueue_stat(struct fileproc
*fp
, void *ub
, int isstat4
, proc_t p
);
153 extern kauth_scope_t kauth_scope_fileop
;
155 /* Conflict wait queue for when selects collide (opaque type) */
156 extern struct wait_queue select_conflict_queue
;
158 #define f_flag f_fglob->fg_flag
159 #define f_type f_fglob->fg_ops->fo_type
160 #define f_msgcount f_fglob->fg_msgcount
161 #define f_cred f_fglob->fg_cred
162 #define f_ops f_fglob->fg_ops
163 #define f_offset f_fglob->fg_offset
164 #define f_data f_fglob->fg_data
165 #define CHECK_ADD_OVERFLOW_INT64L(x, y) \
166 (((((x) > 0) && ((y) > 0) && ((x) > LLONG_MAX - (y))) || \
167 (((x) < 0) && ((y) < 0) && ((x) < LLONG_MIN - (y)))) \
170 * Descriptor management.
172 struct fmsglist fmsghead
; /* head of list of open files */
173 struct fmsglist fmsg_ithead
; /* head of list of open files */
174 int nfiles
; /* actual number of open files */
177 lck_grp_attr_t
* file_lck_grp_attr
;
178 lck_grp_t
* file_lck_grp
;
179 lck_attr_t
* file_lck_attr
;
181 lck_mtx_t
* uipc_lock
;
185 * check_file_seek_range
187 * Description: Checks if seek offsets are in the range of 0 to LLONG_MAX.
189 * Parameters: fl Flock structure.
190 * cur_file_offset Current offset in the file.
192 * Returns: 0 on Success.
193 * EOVERFLOW on overflow.
194 * EINVAL on offset less than zero.
198 check_file_seek_range(struct flock
*fl
, off_t cur_file_offset
)
200 if (fl
->l_whence
== SEEK_CUR
) {
201 /* Check if the start marker is beyond LLONG_MAX. */
202 if (CHECK_ADD_OVERFLOW_INT64L(fl
->l_start
, cur_file_offset
)) {
203 /* Check if start marker is negative */
204 if (fl
->l_start
< 0) {
209 /* Check if the start marker is negative. */
210 if (fl
->l_start
+ cur_file_offset
< 0) {
213 /* Check if end marker is beyond LLONG_MAX. */
214 if ((fl
->l_len
> 0) && (CHECK_ADD_OVERFLOW_INT64L(fl
->l_start
+
215 cur_file_offset
, fl
->l_len
- 1))) {
218 /* Check if the end marker is negative. */
219 if ((fl
->l_len
<= 0) && (fl
->l_start
+ cur_file_offset
+
223 } else if (fl
->l_whence
== SEEK_SET
) {
224 /* Check if the start marker is negative. */
225 if (fl
->l_start
< 0) {
228 /* Check if the end marker is beyond LLONG_MAX. */
229 if ((fl
->l_len
> 0) &&
230 CHECK_ADD_OVERFLOW_INT64L(fl
->l_start
, fl
->l_len
- 1)) {
233 /* Check if the end marker is negative. */
234 if ((fl
->l_len
< 0) && fl
->l_start
+ fl
->l_len
< 0) {
245 * Description: Initialize the file lock group and the uipc and flist locks
251 * Notes: Called at system startup from bsd_init().
256 /* allocate file lock group attribute and group */
257 file_lck_grp_attr
= lck_grp_attr_alloc_init();
259 file_lck_grp
= lck_grp_alloc_init("file", file_lck_grp_attr
);
261 /* Allocate file lock attribute */
262 file_lck_attr
= lck_attr_alloc_init();
264 uipc_lock
= lck_mtx_alloc_init(file_lck_grp
, file_lck_attr
);
269 * proc_fdlock, proc_fdlock_spin
271 * Description: Lock to control access to the per process struct fileproc
272 * and struct filedesc
274 * Parameters: p Process to take the lock on
278 * Notes: The lock is initialized in forkproc() and destroyed in
279 * reap_child_process().
282 proc_fdlock(proc_t p
)
284 lck_mtx_lock(&p
->p_fdmlock
);
288 proc_fdlock_spin(proc_t p
)
290 lck_mtx_lock_spin(&p
->p_fdmlock
);
294 proc_fdlock_assert(proc_t p
, int assertflags
)
296 lck_mtx_assert(&p
->p_fdmlock
, assertflags
);
303 * Description: Unlock the lock previously locked by a call to proc_fdlock()
305 * Parameters: p Process to drop the lock on
310 proc_fdunlock(proc_t p
)
312 lck_mtx_unlock(&p
->p_fdmlock
);
317 * System calls on descriptors.
324 * Description: Returns the per process maximum size of the descriptor table
326 * Parameters: p Process being queried
327 * retval Pointer to the call return area
332 * *retval (modified) Size of dtable
335 getdtablesize(proc_t p
, __unused
struct getdtablesize_args
*uap
, int32_t *retval
)
338 *retval
= min((int)p
->p_rlimit
[RLIMIT_NOFILE
].rlim_cur
, maxfiles
);
346 procfdtbl_reservefd(struct proc
* p
, int fd
)
348 p
->p_fd
->fd_ofiles
[fd
] = NULL
;
349 p
->p_fd
->fd_ofileflags
[fd
] |= UF_RESERVED
;
353 procfdtbl_markclosefd(struct proc
* p
, int fd
)
355 p
->p_fd
->fd_ofileflags
[fd
] |= (UF_RESERVED
| UF_CLOSING
);
359 procfdtbl_releasefd(struct proc
* p
, int fd
, struct fileproc
* fp
)
362 p
->p_fd
->fd_ofiles
[fd
] = fp
;
363 p
->p_fd
->fd_ofileflags
[fd
] &= ~UF_RESERVED
;
364 if ((p
->p_fd
->fd_ofileflags
[fd
] & UF_RESVWAIT
) == UF_RESVWAIT
) {
365 p
->p_fd
->fd_ofileflags
[fd
] &= ~UF_RESVWAIT
;
371 procfdtbl_waitfd(struct proc
* p
, int fd
)
373 p
->p_fd
->fd_ofileflags
[fd
] |= UF_RESVWAIT
;
374 msleep(&p
->p_fd
, &p
->p_fdmlock
, PRIBIO
, "ftbl_waitfd", NULL
);
379 procfdtbl_clearfd(struct proc
* p
, int fd
)
383 waiting
= (p
->p_fd
->fd_ofileflags
[fd
] & UF_RESVWAIT
);
384 p
->p_fd
->fd_ofiles
[fd
] = NULL
;
385 p
->p_fd
->fd_ofileflags
[fd
] = 0;
386 if ( waiting
== UF_RESVWAIT
) {
394 * Description: Inline utility function to free an fd in a filedesc
396 * Parameters: fdp Pointer to filedesc fd lies in
398 * reserv fd should be reserved
402 * Locks: Assumes proc_fdlock for process pointing to fdp is held by
406 _fdrelse(struct proc
* p
, int fd
)
408 struct filedesc
*fdp
= p
->p_fd
;
411 if (fd
< fdp
->fd_freefile
)
412 fdp
->fd_freefile
= fd
;
414 if (fd
> fdp
->fd_lastfile
)
415 panic("fdrelse: fd_lastfile inconsistent");
417 procfdtbl_clearfd(p
, fd
);
419 while ((nfd
= fdp
->fd_lastfile
) > 0 &&
420 fdp
->fd_ofiles
[nfd
] == NULL
&&
421 !(fdp
->fd_ofileflags
[nfd
] & UF_RESERVED
))
443 char uio_buf
[ UIO_SIZEOF(1) ];
444 struct vfs_context context
= *(vfs_context_current());
448 error
= fp_lookup(p
, fd
, &fp
, 0);
452 if (fp
->f_type
!= DTYPE_VNODE
&& fp
->f_type
!= DTYPE_PIPE
&& fp
->f_type
!= DTYPE_SOCKET
) {
456 if (rw
== UIO_WRITE
&& !(fp
->f_flag
& FWRITE
)) {
461 if (rw
== UIO_READ
&& !(fp
->f_flag
& FREAD
)) {
466 context
.vc_ucred
= fp
->f_fglob
->fg_cred
;
468 if (UIO_SEG_IS_USER_SPACE(segflg
))
469 spacetype
= proc_is64bit(p
) ? UIO_USERSPACE64
: UIO_USERSPACE32
;
471 spacetype
= UIO_SYSSPACE
;
473 auio
= uio_createwithbuffer(1, offset
, spacetype
, rw
, &uio_buf
[0], sizeof(uio_buf
));
475 uio_addiov(auio
, base
, len
);
477 if ( !(io_flg
& IO_APPEND
))
481 error
= fo_write(fp
, auio
, flags
, &context
);
483 error
= fo_read(fp
, auio
, flags
, &context
);
486 *aresid
= uio_resid(auio
);
488 if (uio_resid(auio
) && error
== 0)
492 if (rw
== UIO_WRITE
&& error
== 0)
493 fp_drop_written(p
, fd
, fp
);
495 fp_drop(p
, fd
, fp
, 0);
505 * Description: Duplicate a file descriptor.
507 * Parameters: p Process performing the dup
508 * uap->fd The fd to dup
509 * retval Pointer to the call return area
515 * *retval (modified) The new descriptor
518 dup(proc_t p
, struct dup_args
*uap
, int32_t *retval
)
520 struct filedesc
*fdp
= p
->p_fd
;
526 if ( (error
= fp_lookup(p
, old
, &fp
, 1)) ) {
530 if (FP_ISGUARDED(fp
, GUARD_DUP
)) {
531 error
= fp_guard_exception(p
, old
, fp
, kGUARD_EXC_DUP
);
532 (void) fp_drop(p
, old
, fp
, 1);
536 if ( (error
= fdalloc(p
, 0, &new)) ) {
537 fp_drop(p
, old
, fp
, 1);
541 error
= finishdup(p
, fdp
, old
, new, 0, retval
);
542 fp_drop(p
, old
, fp
, 1);
551 * Description: Duplicate a file descriptor to a particular value.
553 * Parameters: p Process performing the dup
554 * uap->from The fd to dup
555 * uap->to The fd to dup it to
556 * retval Pointer to the call return area
562 * *retval (modified) The new descriptor
565 dup2(proc_t p
, struct dup2_args
*uap
, int32_t *retval
)
567 struct filedesc
*fdp
= p
->p_fd
;
568 int old
= uap
->from
, new = uap
->to
;
570 struct fileproc
*fp
, *nfp
;
575 if ( (error
= fp_lookup(p
, old
, &fp
, 1)) ) {
579 if (FP_ISGUARDED(fp
, GUARD_DUP
)) {
580 error
= fp_guard_exception(p
, old
, fp
, kGUARD_EXC_DUP
);
581 (void) fp_drop(p
, old
, fp
, 1);
586 (rlim_t
)new >= p
->p_rlimit
[RLIMIT_NOFILE
].rlim_cur
||
588 fp_drop(p
, old
, fp
, 1);
593 fp_drop(p
, old
, fp
, 1);
598 if (new < 0 || new >= fdp
->fd_nfiles
) {
599 if ( (error
= fdalloc(p
, new, &i
)) ) {
600 fp_drop(p
, old
, fp
, 1);
610 while ((fdp
->fd_ofileflags
[new] & UF_RESERVED
) == UF_RESERVED
) {
611 fp_drop(p
, old
, fp
, 1);
612 procfdtbl_waitfd(p
, new);
614 proc_fdlock_assert(p
, LCK_MTX_ASSERT_OWNED
);
619 if ((fdp
->fd_ofiles
[new] != NULL
) &&
620 ((error
= fp_lookup(p
, new, &nfp
, 1)) == 0)) {
621 fp_drop(p
, old
, fp
, 1);
622 if (FP_ISGUARDED(nfp
, GUARD_CLOSE
)) {
623 error
= fp_guard_exception(p
,
624 new, nfp
, kGUARD_EXC_CLOSE
);
625 (void) fp_drop(p
, new, nfp
, 1);
629 (void)close_internal_locked(p
, new, nfp
, FD_DUP2RESV
);
631 proc_fdlock_assert(p
, LCK_MTX_ASSERT_OWNED
);
633 procfdtbl_clearfd(p
, new);
637 if (fdp
->fd_ofiles
[new] != NULL
)
638 panic("dup2: no ref on fileproc %d", new);
640 procfdtbl_reservefd(p
, new);
644 proc_fdlock_assert(p
, LCK_MTX_ASSERT_OWNED
);
649 if (fdp
->fd_ofiles
[new] != 0)
650 panic("dup2: overwriting fd_ofiles with new %d", new);
651 if ((fdp
->fd_ofileflags
[new] & UF_RESERVED
) == 0)
652 panic("dup2: unreserved fileflags with new %d", new);
654 error
= finishdup(p
, fdp
, old
, new, 0, retval
);
655 fp_drop(p
, old
, fp
, 1);
665 * Description: The file control system call.
667 * Parameters: p Process performing the fcntl
668 * uap->fd The fd to operate against
669 * uap->cmd The command to perform
670 * uap->arg Pointer to the command argument
671 * retval Pointer to the call return area
674 * !0 Errno (see fcntl_nocancel)
677 * *retval (modified) fcntl return value (if any)
679 * Notes: This system call differs from fcntl_nocancel() in that it
680 * tests for cancellation prior to performing a potentially
681 * blocking operation.
684 fcntl(proc_t p
, struct fcntl_args
*uap
, int32_t *retval
)
686 __pthread_testcancel(1);
687 return(fcntl_nocancel(p
, (struct fcntl_nocancel_args
*)uap
, retval
));
694 * Description: A non-cancel-testing file control system call.
696 * Parameters: p Process performing the fcntl
697 * uap->fd The fd to operate against
698 * uap->cmd The command to perform
699 * uap->arg Pointer to the command argument
700 * retval Pointer to the call return area
704 * fp_lookup:EBADF Bad file descriptor
716 * vnode_getwithref:???
724 * vnode_getwithref:???
731 * vnode_getwithref:???
733 * [F_SETSIZE,F_RDADVISE]
736 * vnode_getwithref:???
737 * [F_RDAHEAD,F_NOCACHE]
739 * vnode_getwithref:???
743 * *retval (modified) fcntl return value (if any)
746 fcntl_nocancel(proc_t p
, struct fcntl_nocancel_args
*uap
, int32_t *retval
)
749 struct filedesc
*fdp
= p
->p_fd
;
752 struct vnode
*vp
= NULLVP
; /* for AUDIT_ARG() at end */
753 int i
, tmp
, error
, error2
, flg
= F_POSIX
;
755 struct flocktimeout fltimeout
;
756 struct timespec
*timeout
= NULL
;
757 struct vfs_context context
;
765 AUDIT_ARG(fd
, uap
->fd
);
766 AUDIT_ARG(cmd
, uap
->cmd
);
769 if ( (error
= fp_lookup(p
, fd
, &fp
, 1)) ) {
773 context
.vc_thread
= current_thread();
774 context
.vc_ucred
= fp
->f_cred
;
776 is64bit
= proc_is64bit(p
);
782 * Since the arg parameter is defined as a long but may be
783 * either a long or a pointer we must take care to handle
784 * sign extension issues. Our sys call munger will sign
785 * extend a long when we are called from a 32-bit process.
786 * Since we can never have an address greater than 32-bits
787 * from a 32-bit process we lop off the top 32-bits to avoid
788 * getting the wrong address
790 argp
= CAST_USER_ADDR_T((uint32_t)uap
->arg
);
793 pop
= &fdp
->fd_ofileflags
[fd
];
796 error
= mac_file_check_fcntl(proc_ucred(p
), fp
->f_fglob
, uap
->cmd
,
805 case F_DUPFD_CLOEXEC
:
806 if (FP_ISGUARDED(fp
, GUARD_DUP
)) {
807 error
= fp_guard_exception(p
, fd
, fp
, kGUARD_EXC_DUP
);
810 newmin
= CAST_DOWN_EXPLICIT(int, uap
->arg
); /* arg is an int, so we won't lose bits */
811 AUDIT_ARG(value32
, newmin
);
812 if ((u_int
)newmin
>= p
->p_rlimit
[RLIMIT_NOFILE
].rlim_cur
||
813 newmin
>= maxfiles
) {
817 if ( (error
= fdalloc(p
, newmin
, &i
)) )
819 error
= finishdup(p
, fdp
, fd
, i
,
820 uap
->cmd
== F_DUPFD_CLOEXEC
? UF_EXCLOSE
: 0, retval
);
824 *retval
= (*pop
& UF_EXCLOSE
)? FD_CLOEXEC
: 0;
829 AUDIT_ARG(value32
, uap
->arg
);
830 if (uap
->arg
& FD_CLOEXEC
)
833 if (FILEPROC_TYPE(fp
) == FTYPE_GUARDED
) {
834 error
= fp_guard_exception(p
,
835 fd
, fp
, kGUARD_EXC_NOCLOEXEC
);
844 *retval
= OFLAGS(fp
->f_flag
);
849 fp
->f_flag
&= ~FCNTLFLAGS
;
850 tmp
= CAST_DOWN_EXPLICIT(int, uap
->arg
); /* arg is an int, so we won't lose bits */
851 AUDIT_ARG(value32
, tmp
);
852 fp
->f_flag
|= FFLAGS(tmp
) & FCNTLFLAGS
;
853 tmp
= fp
->f_flag
& FNONBLOCK
;
854 error
= fo_ioctl(fp
, FIONBIO
, (caddr_t
)&tmp
, &context
);
857 tmp
= fp
->f_flag
& FASYNC
;
858 error
= fo_ioctl(fp
, FIOASYNC
, (caddr_t
)&tmp
, &context
);
861 fp
->f_flag
&= ~FNONBLOCK
;
863 (void)fo_ioctl(fp
, FIONBIO
, (caddr_t
)&tmp
, &context
);
867 if (fp
->f_type
== DTYPE_SOCKET
) {
868 *retval
= ((struct socket
*)fp
->f_data
)->so_pgid
;
872 error
= fo_ioctl(fp
, (int)TIOCGPGRP
, (caddr_t
)retval
, &context
);
877 tmp
= CAST_DOWN_EXPLICIT(pid_t
, uap
->arg
); /* arg is an int, so we won't lose bits */
878 AUDIT_ARG(value32
, tmp
);
879 if (fp
->f_type
== DTYPE_SOCKET
) {
880 ((struct socket
*)fp
->f_data
)->so_pgid
= tmp
;
884 if (fp
->f_type
== DTYPE_PIPE
) {
885 error
= fo_ioctl(fp
, TIOCSPGRP
, (caddr_t
)&tmp
, &context
);
892 proc_t p1
= proc_find(tmp
);
897 tmp
= (int)p1
->p_pgrpid
;
900 error
= fo_ioctl(fp
, (int)TIOCSPGRP
, (caddr_t
)&tmp
, &context
);
904 tmp
= CAST_DOWN_EXPLICIT(int, uap
->arg
);
905 if (fp
->f_type
== DTYPE_SOCKET
) {
907 error
= sock_setsockopt((struct socket
*)fp
->f_data
,
908 SOL_SOCKET
, SO_NOSIGPIPE
, &tmp
, sizeof (tmp
));
913 struct fileglob
*fg
= fp
->f_fglob
;
915 lck_mtx_lock_spin(&fg
->fg_lock
);
917 fg
->fg_lflags
|= FG_NOSIGPIPE
;
919 fg
->fg_lflags
&= FG_NOSIGPIPE
;
920 lck_mtx_unlock(&fg
->fg_lock
);
926 if (fp
->f_type
== DTYPE_SOCKET
) {
928 int retsize
= sizeof (*retval
);
929 error
= sock_getsockopt((struct socket
*)fp
->f_data
,
930 SOL_SOCKET
, SO_NOSIGPIPE
, retval
, &retsize
);
935 *retval
= (fp
->f_fglob
->fg_lflags
& FG_NOSIGPIPE
) ?
941 case F_SETLKWTIMEOUT
:
944 /* Fall into F_SETLK */
947 if (fp
->f_type
!= DTYPE_VNODE
) {
951 vp
= (struct vnode
*)fp
->f_data
;
954 offset
= fp
->f_offset
;
957 /* Copy in the lock structure */
958 if (uap
->cmd
== F_SETLKWTIMEOUT
) {
959 error
= copyin(argp
, (caddr_t
) &fltimeout
, sizeof(fltimeout
));
964 timeout
= &fltimeout
.timeout
;
966 error
= copyin(argp
, (caddr_t
)&fl
, sizeof(fl
));
972 /* Check starting byte and ending byte for EOVERFLOW in SEEK_CUR */
973 /* and ending byte for EOVERFLOW in SEEK_SET */
974 error
= check_file_seek_range(&fl
, offset
);
979 if ( (error
= vnode_getwithref(vp
)) ) {
982 if (fl
.l_whence
== SEEK_CUR
)
983 fl
.l_start
+= offset
;
986 error
= mac_file_check_lock(proc_ucred(p
), fp
->f_fglob
,
996 if ((fflag
& FREAD
) == 0) {
1001 // XXX UInt32 unsafe for LP64 kernel
1002 OSBitOrAtomic(P_LADVLOCK
, &p
->p_ladvflag
);
1003 error
= VNOP_ADVLOCK(vp
, (caddr_t
)p
, F_SETLK
, &fl
, flg
, &context
, timeout
);
1004 (void)vnode_put(vp
);
1008 if ((fflag
& FWRITE
) == 0) {
1009 (void)vnode_put(vp
);
1013 // XXX UInt32 unsafe for LP64 kernel
1014 OSBitOrAtomic(P_LADVLOCK
, &p
->p_ladvflag
);
1015 error
= VNOP_ADVLOCK(vp
, (caddr_t
)p
, F_SETLK
, &fl
, flg
, &context
, timeout
);
1016 (void)vnode_put(vp
);
1020 error
= VNOP_ADVLOCK(vp
, (caddr_t
)p
, F_UNLCK
, &fl
,
1021 F_POSIX
, &context
, timeout
);
1022 (void)vnode_put(vp
);
1026 (void)vnode_put(vp
);
1032 if (fp
->f_type
!= DTYPE_VNODE
) {
1036 vp
= (struct vnode
*)fp
->f_data
;
1038 offset
= fp
->f_offset
;
1041 /* Copy in the lock structure */
1042 error
= copyin(argp
, (caddr_t
)&fl
, sizeof(fl
));
1046 /* Check starting byte and ending byte for EOVERFLOW in SEEK_CUR */
1047 /* and ending byte for EOVERFLOW in SEEK_SET */
1048 error
= check_file_seek_range(&fl
, offset
);
1053 if ((fl
.l_whence
== SEEK_SET
) && (fl
.l_start
< 0)) {
1058 switch (fl
.l_type
) {
1068 switch (fl
.l_whence
) {
1078 if ( (error
= vnode_getwithref(vp
)) == 0 ) {
1079 if (fl
.l_whence
== SEEK_CUR
)
1080 fl
.l_start
+= offset
;
1083 error
= mac_file_check_lock(proc_ucred(p
), fp
->f_fglob
,
1087 error
= VNOP_ADVLOCK(vp
, (caddr_t
)p
, uap
->cmd
, &fl
, F_POSIX
, &context
, NULL
);
1089 (void)vnode_put(vp
);
1092 error
= copyout((caddr_t
)&fl
, argp
, sizeof(fl
));
1096 case F_PREALLOCATE
: {
1097 fstore_t alloc_struct
; /* structure for allocate command */
1098 u_int32_t alloc_flags
= 0;
1100 if (fp
->f_type
!= DTYPE_VNODE
) {
1105 vp
= (struct vnode
*)fp
->f_data
;
1108 /* make sure that we have write permission */
1109 if ((fp
->f_flag
& FWRITE
) == 0) {
1114 error
= copyin(argp
, (caddr_t
)&alloc_struct
, sizeof(alloc_struct
));
1118 /* now set the space allocated to 0 */
1119 alloc_struct
.fst_bytesalloc
= 0;
1122 * Do some simple parameter checking
1125 /* set up the flags */
1127 alloc_flags
|= PREALLOCATE
;
1129 if (alloc_struct
.fst_flags
& F_ALLOCATECONTIG
)
1130 alloc_flags
|= ALLOCATECONTIG
;
1132 if (alloc_struct
.fst_flags
& F_ALLOCATEALL
)
1133 alloc_flags
|= ALLOCATEALL
;
1136 * Do any position mode specific stuff. The only
1137 * position mode supported now is PEOFPOSMODE
1140 switch (alloc_struct
.fst_posmode
) {
1143 if (alloc_struct
.fst_offset
!= 0) {
1148 alloc_flags
|= ALLOCATEFROMPEOF
;
1152 if (alloc_struct
.fst_offset
<= 0) {
1157 alloc_flags
|= ALLOCATEFROMVOL
;
1165 if ( (error
= vnode_getwithref(vp
)) == 0 ) {
1167 * call allocate to get the space
1169 error
= VNOP_ALLOCATE(vp
,alloc_struct
.fst_length
,alloc_flags
,
1170 &alloc_struct
.fst_bytesalloc
, alloc_struct
.fst_offset
,
1172 (void)vnode_put(vp
);
1174 error2
= copyout((caddr_t
)&alloc_struct
, argp
, sizeof(alloc_struct
));
1183 if (fp
->f_type
!= DTYPE_VNODE
) {
1187 vp
= (struct vnode
*)fp
->f_data
;
1190 error
= copyin(argp
, (caddr_t
)&offset
, sizeof (off_t
));
1193 AUDIT_ARG(value64
, offset
);
1195 error
= vnode_getwithref(vp
);
1200 error
= mac_vnode_check_truncate(&context
,
1201 fp
->f_fglob
->fg_cred
, vp
);
1203 (void)vnode_put(vp
);
1208 * Make sure that we are root. Growing a file
1209 * without zero filling the data is a security hole
1210 * root would have access anyway so we'll allow it
1212 if (!kauth_cred_issuser(kauth_cred_get())) {
1218 error
= vnode_setsize(vp
, offset
, IO_NOZEROFILL
,
1222 (void)vnode_put(vp
);
1226 if (fp
->f_type
!= DTYPE_VNODE
) {
1231 fp
->f_fglob
->fg_flag
&= ~FNORDAHEAD
;
1233 fp
->f_fglob
->fg_flag
|= FNORDAHEAD
;
1238 if (fp
->f_type
!= DTYPE_VNODE
) {
1243 fp
->f_fglob
->fg_flag
|= FNOCACHE
;
1245 fp
->f_fglob
->fg_flag
&= ~FNOCACHE
;
1250 if (fp
->f_type
!= DTYPE_VNODE
) {
1255 fp
->f_fglob
->fg_flag
|= FNODIRECT
;
1257 fp
->f_fglob
->fg_flag
&= ~FNODIRECT
;
1261 case F_SINGLE_WRITER
:
1262 if (fp
->f_type
!= DTYPE_VNODE
) {
1267 fp
->f_fglob
->fg_flag
|= FSINGLE_WRITER
;
1269 fp
->f_fglob
->fg_flag
&= ~FSINGLE_WRITER
;
1273 case F_GLOBAL_NOCACHE
:
1274 if (fp
->f_type
!= DTYPE_VNODE
) {
1278 vp
= (struct vnode
*)fp
->f_data
;
1281 if ( (error
= vnode_getwithref(vp
)) == 0 ) {
1283 *retval
= vnode_isnocache(vp
);
1286 vnode_setnocache(vp
);
1288 vnode_clearnocache(vp
);
1290 (void)vnode_put(vp
);
1294 case F_CHECK_OPENEVT
:
1295 if (fp
->f_type
!= DTYPE_VNODE
) {
1299 vp
= (struct vnode
*)fp
->f_data
;
1302 if ( (error
= vnode_getwithref(vp
)) == 0 ) {
1304 *retval
= vnode_is_openevt(vp
);
1307 vnode_set_openevt(vp
);
1309 vnode_clear_openevt(vp
);
1311 (void)vnode_put(vp
);
1316 struct radvisory ra_struct
;
1318 if (fp
->f_type
!= DTYPE_VNODE
) {
1322 vp
= (struct vnode
*)fp
->f_data
;
1325 if ( (error
= copyin(argp
, (caddr_t
)&ra_struct
, sizeof(ra_struct
))) )
1327 if ( (error
= vnode_getwithref(vp
)) == 0 ) {
1328 error
= VNOP_IOCTL(vp
, F_RDADVISE
, (caddr_t
)&ra_struct
, 0, &context
);
1330 (void)vnode_put(vp
);
1337 if (fp
->f_type
!= DTYPE_VNODE
) {
1341 vp
= (struct vnode
*)fp
->f_data
;
1344 if ( (error
= vnode_getwithref(vp
)) == 0 ) {
1345 error
= cluster_push(vp
, 0);
1347 (void)vnode_put(vp
);
1352 case F_LOG2PHYS_EXT
: {
1353 struct log2phys l2p_struct
; /* structure for allocate command */
1356 off_t file_offset
= 0;
1360 if (uap
->cmd
== F_LOG2PHYS_EXT
) {
1361 error
= copyin(argp
, (caddr_t
)&l2p_struct
, sizeof(l2p_struct
));
1364 file_offset
= l2p_struct
.l2p_devoffset
;
1366 file_offset
= fp
->f_offset
;
1368 if (fp
->f_type
!= DTYPE_VNODE
) {
1372 vp
= (struct vnode
*)fp
->f_data
;
1374 if ( (error
= vnode_getwithref(vp
)) ) {
1377 error
= VNOP_OFFTOBLK(vp
, file_offset
, &lbn
);
1379 (void)vnode_put(vp
);
1382 error
= VNOP_BLKTOOFF(vp
, lbn
, &offset
);
1384 (void)vnode_put(vp
);
1387 devBlockSize
= vfs_devblocksize(vnode_mount(vp
));
1388 if (uap
->cmd
== F_LOG2PHYS_EXT
) {
1389 #if defined(__LP64__)
1390 a_size
= l2p_struct
.l2p_contigbytes
;
1392 if ((l2p_struct
.l2p_contigbytes
> SIZE_MAX
) || (l2p_struct
.l2p_contigbytes
< 0)) {
1393 /* size_t is 32-bit on a 32-bit kernel, therefore
1394 * assigning l2p_contigbytes to a_size may have
1395 * caused integer overflow. We, therefore, return
1396 * an error here instead of calculating incorrect
1399 printf ("fcntl: F_LOG2PHYS_EXT: l2p_contigbytes=%lld will overflow, returning error\n", l2p_struct
.l2p_contigbytes
);
1403 a_size
= l2p_struct
.l2p_contigbytes
;
1407 a_size
= devBlockSize
;
1410 error
= VNOP_BLOCKMAP(vp
, offset
, a_size
, &bn
, &run
, NULL
, 0, &context
);
1412 (void)vnode_put(vp
);
1415 l2p_struct
.l2p_flags
= 0; /* for now */
1416 if (uap
->cmd
== F_LOG2PHYS_EXT
) {
1417 l2p_struct
.l2p_contigbytes
= run
- (file_offset
- offset
);
1419 l2p_struct
.l2p_contigbytes
= 0; /* for now */
1423 * The block number being -1 suggests that the file offset is not backed
1424 * by any real blocks on-disk. As a result, just let it be passed back up wholesale.
1427 /* Don't multiply it by the block size */
1428 l2p_struct
.l2p_devoffset
= bn
;
1431 l2p_struct
.l2p_devoffset
= bn
* devBlockSize
;
1432 l2p_struct
.l2p_devoffset
+= file_offset
- offset
;
1434 error
= copyout((caddr_t
)&l2p_struct
, argp
, sizeof(l2p_struct
));
1442 if (fp
->f_type
!= DTYPE_VNODE
) {
1446 vp
= (struct vnode
*)fp
->f_data
;
1449 pathlen
= MAXPATHLEN
;
1450 MALLOC(pathbufp
, char *, pathlen
, M_TEMP
, M_WAITOK
);
1451 if (pathbufp
== NULL
) {
1455 if ( (error
= vnode_getwithref(vp
)) == 0 ) {
1456 error
= vn_getpath(vp
, pathbufp
, &pathlen
);
1457 (void)vnode_put(vp
);
1460 error
= copyout((caddr_t
)pathbufp
, argp
, pathlen
);
1462 FREE(pathbufp
, M_TEMP
);
1466 case F_PATHPKG_CHECK
: {
1470 if (fp
->f_type
!= DTYPE_VNODE
) {
1474 vp
= (struct vnode
*)fp
->f_data
;
1477 pathlen
= MAXPATHLEN
;
1478 pathbufp
= kalloc(MAXPATHLEN
);
1480 if ( (error
= copyinstr(argp
, pathbufp
, MAXPATHLEN
, &pathlen
)) == 0 ) {
1481 if ( (error
= vnode_getwithref(vp
)) == 0 ) {
1482 AUDIT_ARG(text
, pathbufp
);
1483 error
= vn_path_package_check(vp
, pathbufp
, pathlen
, retval
);
1485 (void)vnode_put(vp
);
1488 kfree(pathbufp
, MAXPATHLEN
);
1492 case F_CHKCLEAN
: // used by regression tests to see if all dirty pages got cleaned by fsync()
1493 case F_FULLFSYNC
: // fsync + flush the journal + DKIOCSYNCHRONIZECACHE
1494 case F_FREEZE_FS
: // freeze all other fs operations for the fs of this fd
1495 case F_THAW_FS
: { // thaw all frozen fs operations for the fs of this fd
1496 if (fp
->f_type
!= DTYPE_VNODE
) {
1500 vp
= (struct vnode
*)fp
->f_data
;
1503 if ( (error
= vnode_getwithref(vp
)) == 0 ) {
1504 error
= VNOP_IOCTL(vp
, uap
->cmd
, (caddr_t
)NULL
, 0, &context
);
1506 (void)vnode_put(vp
);
1512 * SPI (private) for opening a file starting from a dir fd
1515 struct user_fopenfrom fopen
;
1516 struct vnode_attr va
;
1517 struct nameidata nd
;
1520 /* Check if this isn't a valid file descriptor */
1521 if ((fp
->f_type
!= DTYPE_VNODE
) ||
1522 (fp
->f_flag
& FREAD
) == 0) {
1526 vp
= (struct vnode
*)fp
->f_data
;
1529 if (vnode_getwithref(vp
)) {
1534 /* Only valid for directories */
1535 if (vp
->v_type
!= VDIR
) {
1541 /* Get flags, mode and pathname arguments. */
1542 if (IS_64BIT_PROCESS(p
)) {
1543 error
= copyin(argp
, &fopen
, sizeof(fopen
));
1545 struct user32_fopenfrom fopen32
;
1547 error
= copyin(argp
, &fopen32
, sizeof(fopen32
));
1548 fopen
.o_flags
= fopen32
.o_flags
;
1549 fopen
.o_mode
= fopen32
.o_mode
;
1550 fopen
.o_pathname
= CAST_USER_ADDR_T(fopen32
.o_pathname
);
1556 AUDIT_ARG(fflags
, fopen
.o_flags
);
1557 AUDIT_ARG(mode
, fopen
.o_mode
);
1559 /* Mask off all but regular access permissions */
1560 cmode
= ((fopen
.o_mode
&~ fdp
->fd_cmask
) & ALLPERMS
) & ~S_ISTXT
;
1561 VATTR_SET(&va
, va_mode
, cmode
& ACCESSPERMS
);
1563 /* Start the lookup relative to the file descriptor's vnode. */
1564 NDINIT(&nd
, LOOKUP
, OP_OPEN
, USEDVP
| FOLLOW
| AUDITVNPATH1
, UIO_USERSPACE
,
1565 fopen
.o_pathname
, &context
);
1568 error
= open1(&context
, &nd
, fopen
.o_flags
, &va
,
1569 fileproc_alloc_init
, NULL
, retval
);
1575 * SPI (private) for unlinking a file starting from a dir fd
1577 case F_UNLINKFROM
: {
1578 struct nameidata nd
;
1579 user_addr_t pathname
;
1581 /* Check if this isn't a valid file descriptor */
1582 if ((fp
->f_type
!= DTYPE_VNODE
) ||
1583 (fp
->f_flag
& FREAD
) == 0) {
1587 vp
= (struct vnode
*)fp
->f_data
;
1590 if (vnode_getwithref(vp
)) {
1595 /* Only valid for directories */
1596 if (vp
->v_type
!= VDIR
) {
1602 /* Get flags, mode and pathname arguments. */
1603 if (IS_64BIT_PROCESS(p
)) {
1604 pathname
= (user_addr_t
)argp
;
1606 pathname
= CAST_USER_ADDR_T(argp
);
1609 /* Start the lookup relative to the file descriptor's vnode. */
1610 NDINIT(&nd
, DELETE
, OP_UNLINK
, USEDVP
| AUDITVNPATH1
, UIO_USERSPACE
,
1611 pathname
, &context
);
1614 error
= unlink1(&context
, &nd
, 0);
1624 struct user_fsignatures fs
;
1626 off_t kernel_blob_offset
;
1627 vm_offset_t kernel_blob_addr
;
1628 vm_size_t kernel_blob_size
;
1630 if (fp
->f_type
!= DTYPE_VNODE
) {
1634 vp
= (struct vnode
*)fp
->f_data
;
1636 error
= vnode_getwithref(vp
);
1640 if (IS_64BIT_PROCESS(p
)) {
1641 error
= copyin(argp
, &fs
, sizeof (fs
));
1643 struct user32_fsignatures fs32
;
1645 error
= copyin(argp
, &fs32
, sizeof (fs32
));
1646 fs
.fs_file_start
= fs32
.fs_file_start
;
1647 fs
.fs_blob_start
= CAST_USER_ADDR_T(fs32
.fs_blob_start
);
1648 fs
.fs_blob_size
= fs32
.fs_blob_size
;
1656 if(ubc_cs_blob_get(vp
, CPU_TYPE_ANY
, fs
.fs_file_start
))
1661 #if defined(__LP64__)
1662 #define CS_MAX_BLOB_SIZE (2560ULL * 1024ULL) /* max shared cache file XXX ? */
1664 #define CS_MAX_BLOB_SIZE (1600ULL * 1024ULL) /* max shared cache file XXX ? */
1666 if (fs
.fs_blob_size
> CS_MAX_BLOB_SIZE
) {
1672 kernel_blob_size
= CAST_DOWN(vm_size_t
, fs
.fs_blob_size
);
1673 kr
= ubc_cs_blob_allocate(&kernel_blob_addr
, &kernel_blob_size
);
1674 if (kr
!= KERN_SUCCESS
) {
1680 if(uap
->cmd
== F_ADDSIGS
) {
1681 kernel_blob_offset
= 0;
1682 error
= copyin(fs
.fs_blob_start
,
1683 (void *) kernel_blob_addr
,
1685 } else /* F_ADDFILESIGS */ {
1686 kernel_blob_offset
= fs
.fs_blob_start
;
1687 error
= vn_rdwr(UIO_READ
,
1689 (caddr_t
) kernel_blob_addr
,
1691 fs
.fs_file_start
+ fs
.fs_blob_start
,
1700 ubc_cs_blob_deallocate(kernel_blob_addr
,
1706 error
= ubc_cs_blob_add(
1708 CPU_TYPE_ANY
, /* not for a specific architecture */
1714 ubc_cs_blob_deallocate(kernel_blob_addr
,
1717 /* ubc_blob_add() has consumed "kernel_blob_addr" */
1718 #if CHECK_CS_VALIDATION_BITMAP
1719 ubc_cs_validation_bitmap_allocate( vp
);
1723 (void) vnode_put(vp
);
1727 #ifdef SECURE_KERNEL
1729 #else /* !SECURE_KERNEL */
1732 if (fp
->f_type
!= DTYPE_VNODE
) {
1736 vp
= (struct vnode
*)fp
->f_data
;
1738 error
= vnode_getwithref(vp
);
1742 error
= copyin(argp
, &offsetMacho
, sizeof(offsetMacho
));
1744 (void)vnode_put(vp
);
1749 error
= mac_vnode_find_sigs(p
, vp
, offsetMacho
);
1754 (void)vnode_put(vp
);
1757 #endif /* SECURE_KERNEL */
1761 case F_GETPROTECTIONCLASS
: {
1764 if (fp
->f_type
!= DTYPE_VNODE
) {
1768 vp
= (struct vnode
*)fp
->f_data
;
1772 if (vnode_getwithref(vp
)) {
1777 error
= cp_vnode_getclass (vp
, &class);
1786 case F_SETPROTECTIONCLASS
: {
1787 /* tmp must be a valid PROTECTION_CLASS_* */
1788 tmp
= CAST_DOWN_EXPLICIT(uint32_t, uap
->arg
);
1790 if (fp
->f_type
!= DTYPE_VNODE
) {
1794 vp
= (struct vnode
*)fp
->f_data
;
1798 if (vnode_getwithref(vp
)) {
1803 /* Only go forward if you have write access */
1804 vfs_context_t ctx
= vfs_context_current();
1805 if(vnode_authorize(vp
, NULLVP
, (KAUTH_VNODE_ACCESS
| KAUTH_VNODE_WRITE_DATA
), ctx
) != 0) {
1810 error
= cp_vnode_setclass (vp
, tmp
);
1815 case F_TRANSCODEKEY
: {
1817 if (fp
->f_type
!= DTYPE_VNODE
) {
1822 vp
= (struct vnode
*)fp
->f_data
;
1825 if (vnode_getwithref(vp
)) {
1830 error
= cp_vnode_transcode (vp
);
1835 case F_GETPROTECTIONLEVEL
: {
1836 uint32_t cp_version
= 0;
1838 if (fp
->f_type
!= DTYPE_VNODE
) {
1843 vp
= (struct vnode
*) fp
->f_data
;
1846 if (vnode_getwithref(vp
)) {
1852 * if cp_get_major_vers fails, error will be set to proper errno
1853 * and cp_version will still be 0.
1856 error
= cp_get_root_major_vers (vp
, &cp_version
);
1857 *retval
= cp_version
;
1863 case F_GETDEFAULTPROTLEVEL
: {
1864 uint32_t cp_default
= 0;
1866 if (fp
->f_type
!= DTYPE_VNODE
) {
1871 vp
= (struct vnode
*) fp
->f_data
;
1874 if (vnode_getwithref(vp
)) {
1880 * if cp_get_major_vers fails, error will be set to proper errno
1881 * and cp_version will still be 0.
1884 error
= cp_get_default_level(vp
, &cp_default
);
1885 *retval
= cp_default
;
1892 #endif /* CONFIG_PROTECT */
1894 case F_MOVEDATAEXTENTS
: {
1895 struct fileproc
*fp2
= NULL
;
1896 struct vnode
*src_vp
= NULLVP
;
1897 struct vnode
*dst_vp
= NULLVP
;
1898 /* We need to grab the 2nd FD out of the argments before moving on. */
1899 int fd2
= CAST_DOWN_EXPLICIT(int32_t, uap
->arg
);
1901 if (fp
->f_type
!= DTYPE_VNODE
) {
1906 /* For now, special case HFS+ only, since this is SPI. */
1907 src_vp
= (struct vnode
*)fp
->f_data
;
1908 if (src_vp
->v_tag
!= VT_HFS
) {
1914 * Get the references before we start acquiring iocounts on the vnodes,
1915 * while we still hold the proc fd lock
1917 if ( (error
= fp_lookup(p
, fd2
, &fp2
, 1)) ) {
1921 if (fp2
->f_type
!= DTYPE_VNODE
) {
1922 fp_drop(p
, fd2
, fp2
, 1);
1926 dst_vp
= (struct vnode
*)fp2
->f_data
;
1927 if (dst_vp
->v_tag
!= VT_HFS
) {
1928 fp_drop(p
, fd2
, fp2
, 1);
1934 /* Re-do MAC checks against the new FD, pass in a fake argument */
1935 error
= mac_file_check_fcntl(proc_ucred(p
), fp2
->f_fglob
, uap
->cmd
, 0);
1937 fp_drop(p
, fd2
, fp2
, 1);
1941 /* Audit the 2nd FD */
1946 if (vnode_getwithref(src_vp
)) {
1947 fp_drop(p
, fd2
, fp2
, 0);
1951 if (vnode_getwithref(dst_vp
)) {
1953 fp_drop(p
, fd2
, fp2
, 0);
1959 * Basic asserts; validate they are not the same and that
1960 * both live on the same filesystem.
1962 if (dst_vp
== src_vp
) {
1965 fp_drop (p
, fd2
, fp2
, 0);
1970 if (dst_vp
->v_mount
!= src_vp
->v_mount
) {
1973 fp_drop (p
, fd2
, fp2
, 0);
1978 /* Now we have a legit pair of FDs. Go to work */
1980 /* Now check for write access to the target files */
1981 if(vnode_authorize(src_vp
, NULLVP
,
1982 (KAUTH_VNODE_ACCESS
| KAUTH_VNODE_WRITE_DATA
), &context
) != 0) {
1985 fp_drop(p
, fd2
, fp2
, 0);
1990 if(vnode_authorize(dst_vp
, NULLVP
,
1991 (KAUTH_VNODE_ACCESS
| KAUTH_VNODE_WRITE_DATA
), &context
) != 0) {
1994 fp_drop(p
, fd2
, fp2
, 0);
1999 /* Verify that both vps point to files and not directories */
2000 if ( !vnode_isreg(src_vp
) || !vnode_isreg(dst_vp
)) {
2004 fp_drop (p
, fd2
, fp2
, 0);
2009 * The exchangedata syscall handler passes in 0 for the flags to VNOP_EXCHANGE.
2010 * We'll pass in our special bit indicating that the new behavior is expected
2013 error
= VNOP_EXCHANGE(src_vp
, dst_vp
, FSOPT_EXCHANGE_DATA_ONLY
, &context
);
2017 fp_drop(p
, fd2
, fp2
, 0);
2022 * SPI for making a file compressed.
2024 case F_MAKECOMPRESSED
: {
2025 uint32_t gcounter
= CAST_DOWN_EXPLICIT(uint32_t, uap
->arg
);
2027 if (fp
->f_type
!= DTYPE_VNODE
) {
2032 vp
= (struct vnode
*) fp
->f_data
;
2036 if (vnode_getwithref(vp
)) {
2042 if ((vnode_isreg(vp
) == 0) && (vnode_islnk(vp
) == 0)) {
2048 /* invoke ioctl to pass off to FS */
2049 /* Only go forward if you have write access */
2050 vfs_context_t ctx
= vfs_context_current();
2051 if(vnode_authorize(vp
, NULLVP
, (KAUTH_VNODE_ACCESS
| KAUTH_VNODE_WRITE_DATA
), ctx
) != 0) {
2057 error
= VNOP_IOCTL(vp
, uap
->cmd
, (caddr_t
)&gcounter
, 0, &context
);
2064 * SPI (private) for indicating to a filesystem that subsequent writes to
2065 * the open FD will written to the Fastflow.
2067 case F_SET_GREEDY_MODE
:
2068 /* intentionally drop through to the same handler as F_SETSTATIC.
2069 * both fcntls should pass the argument and their selector into VNOP_IOCTL.
2073 * SPI (private) for indicating to a filesystem that subsequent writes to
2074 * the open FD will represent static content.
2076 case F_SETSTATICCONTENT
: {
2077 caddr_t ioctl_arg
= NULL
;
2080 ioctl_arg
= (caddr_t
) 1;
2083 if (fp
->f_type
!= DTYPE_VNODE
) {
2087 vp
= (struct vnode
*)fp
->f_data
;
2090 error
= vnode_getwithref(vp
);
2096 /* Only go forward if you have write access */
2097 vfs_context_t ctx
= vfs_context_current();
2098 if(vnode_authorize(vp
, NULLVP
, (KAUTH_VNODE_ACCESS
| KAUTH_VNODE_WRITE_DATA
), ctx
) != 0) {
2104 error
= VNOP_IOCTL(vp
, uap
->cmd
, ioctl_arg
, 0, &context
);
2105 (void)vnode_put(vp
);
2111 * Set the vnode pointed to by 'fd'
2112 * and tag it as the (potentially future) backing store
2113 * for another filesystem
2115 case F_SETBACKINGSTORE
: {
2116 if (fp
->f_type
!= DTYPE_VNODE
) {
2121 vp
= (struct vnode
*)fp
->f_data
;
2123 if (vp
->v_tag
!= VT_HFS
) {
2129 if (vnode_getwithref(vp
)) {
2134 /* only proceed if you have write access */
2135 vfs_context_t ctx
= vfs_context_current();
2136 if(vnode_authorize(vp
, NULLVP
, (KAUTH_VNODE_ACCESS
| KAUTH_VNODE_WRITE_DATA
), ctx
) != 0) {
2143 /* If arg != 0, set, otherwise unset */
2145 error
= VNOP_IOCTL (vp
, uap
->cmd
, (caddr_t
)1, 0, &context
);
2148 error
= VNOP_IOCTL (vp
, uap
->cmd
, (caddr_t
)NULL
, 0, &context
);
2156 * like F_GETPATH, but special semantics for
2157 * the mobile time machine handler.
2159 case F_GETPATH_MTMINFO
: {
2163 if (fp
->f_type
!= DTYPE_VNODE
) {
2167 vp
= (struct vnode
*)fp
->f_data
;
2170 pathlen
= MAXPATHLEN
;
2171 MALLOC(pathbufp
, char *, pathlen
, M_TEMP
, M_WAITOK
);
2172 if (pathbufp
== NULL
) {
2176 if ( (error
= vnode_getwithref(vp
)) == 0 ) {
2177 int backingstore
= 0;
2179 /* Check for error from vn_getpath before moving on */
2180 if ((error
= vn_getpath(vp
, pathbufp
, &pathlen
)) == 0) {
2181 if (vp
->v_tag
== VT_HFS
) {
2182 error
= VNOP_IOCTL (vp
, uap
->cmd
, (caddr_t
) &backingstore
, 0, &context
);
2184 (void)vnode_put(vp
);
2187 error
= copyout((caddr_t
)pathbufp
, argp
, pathlen
);
2191 * If the copyout was successful, now check to ensure
2192 * that this vnode is not a BACKINGSTORE vnode. mtmd
2193 * wants the path regardless.
2200 (void)vnode_put(vp
);
2202 FREE(pathbufp
, M_TEMP
);
2208 * This is an fcntl() that we d not recognize at this level;
2209 * if this is a vnode, we send it down into the VNOP_IOCTL
2210 * for this vnode; this can include special devices, and will
2211 * effectively overload fcntl() to send ioctl()'s.
2213 if((uap
->cmd
& IOC_VOID
) && (uap
->cmd
& IOC_INOUT
)){
2218 /* Catch any now-invalid fcntl() selectors */
2220 case F_MARKDEPENDENCY
:
2227 if (fp
->f_type
!= DTYPE_VNODE
) {
2231 vp
= (struct vnode
*)fp
->f_data
;
2234 if ( (error
= vnode_getwithref(vp
)) == 0 ) {
2235 #define STK_PARAMS 128
2236 char stkbuf
[STK_PARAMS
];
2240 * For this to work properly, we have to copy in the
2241 * ioctl() cmd argument if there is one; we must also
2242 * check that a command parameter, if present, does
2243 * not exceed the maximum command length dictated by
2244 * the number of bits we have available in the command
2245 * to represent a structure length. Finally, we have
2246 * to copy the results back out, if it is that type of
2249 size
= IOCPARM_LEN(uap
->cmd
);
2250 if (size
> IOCPARM_MAX
) {
2251 (void)vnode_put(vp
);
2257 if (size
> sizeof (stkbuf
)) {
2258 if ((memp
= (caddr_t
)kalloc(size
)) == 0) {
2259 (void)vnode_put(vp
);
2268 if (uap
->cmd
& IOC_IN
) {
2271 error
= copyin(argp
, data
, size
);
2273 (void)vnode_put(vp
);
2279 /* Bzero the section beyond that which was needed */
2280 if (size
<= sizeof(stkbuf
)) {
2281 bzero ( (((uint8_t*)data
) + size
), (sizeof(stkbuf
) - size
));
2286 *(user_addr_t
*)data
= argp
;
2288 *(uint32_t *)data
= (uint32_t)argp
;
2291 } else if ((uap
->cmd
& IOC_OUT
) && size
) {
2293 * Zero the buffer so the user always
2294 * gets back something deterministic.
2297 } else if (uap
->cmd
& IOC_VOID
) {
2299 *(user_addr_t
*)data
= argp
;
2301 *(uint32_t *)data
= (uint32_t)argp
;
2305 error
= VNOP_IOCTL(vp
, uap
->cmd
, CAST_DOWN(caddr_t
, data
), 0, &context
);
2307 (void)vnode_put(vp
);
2309 /* Copy any output data to user */
2310 if (error
== 0 && (uap
->cmd
& IOC_OUT
) && size
)
2311 error
= copyout(data
, argp
, size
);
2319 AUDIT_ARG(vnpath_withref
, vp
, ARG_VNODE1
);
2320 fp_drop(p
, fd
, fp
, 0);
2323 fp_drop(p
, fd
, fp
, 1);
2332 * Description: Common code for dup, dup2, and fcntl(F_DUPFD).
2334 * Parameters: p Process performing the dup
2336 * new The fd to dup it to
2337 * fd_flags Flags to augment the new fd
2338 * retval Pointer to the call return area
2340 * Returns: 0 Success
2345 * *retval (modified) The new descriptor
2347 * Locks: Assumes proc_fdlock for process pointing to fdp is held by
2350 * Notes: This function may drop and reacquire this lock; it is unsafe
2351 * for a caller to assume that other state protected by the lock
2352 * has not been subsequently changed out from under it.
2356 struct filedesc
*fdp
, int old
, int new, int fd_flags
, int32_t *retval
)
2358 struct fileproc
*nfp
;
2359 struct fileproc
*ofp
;
2365 proc_fdlock_assert(p
, LCK_MTX_ASSERT_OWNED
);
2367 if ((ofp
= fdp
->fd_ofiles
[old
]) == NULL
||
2368 (fdp
->fd_ofileflags
[old
] & UF_RESERVED
)) {
2375 error
= mac_file_check_dup(proc_ucred(p
), ofp
->f_fglob
, new);
2385 nfp
= fileproc_alloc_init(NULL
);
2395 nfp
->f_fglob
= ofp
->f_fglob
;
2398 if (fdp
->fd_ofiles
[new] != 0)
2399 panic("finishdup: overwriting fd_ofiles with new %d", new);
2400 if ((fdp
->fd_ofileflags
[new] & UF_RESERVED
) == 0)
2401 panic("finishdup: unreserved fileflags with new %d", new);
2404 if (new > fdp
->fd_lastfile
)
2405 fdp
->fd_lastfile
= new;
2406 *fdflags(p
, new) |= fd_flags
;
2407 procfdtbl_releasefd(p
, new, nfp
);
2416 * Description: The implementation of the close(2) system call
2418 * Parameters: p Process in whose per process file table
2419 * the close is to occur
2420 * uap->fd fd to be closed
2423 * Returns: 0 Success
2424 * fp_lookup:EBADF Bad file descriptor
2425 * fp_guard_exception:??? Guarded file descriptor
2426 * close_internal:EBADF
2427 * close_internal:??? Anything returnable by a per-fileops
2431 close(proc_t p
, struct close_args
*uap
, int32_t *retval
)
2433 __pthread_testcancel(1);
2434 return(close_nocancel(p
, (struct close_nocancel_args
*)uap
, retval
));
2439 close_nocancel(proc_t p
, struct close_nocancel_args
*uap
, __unused
int32_t *retval
)
2441 struct fileproc
*fp
;
2445 AUDIT_SYSCLOSE(p
, fd
);
2449 if ( (error
= fp_lookup(p
,fd
,&fp
, 1)) ) {
2454 if (FP_ISGUARDED(fp
, GUARD_CLOSE
)) {
2455 error
= fp_guard_exception(p
, fd
, fp
, kGUARD_EXC_CLOSE
);
2456 (void) fp_drop(p
, fd
, fp
, 1);
2461 error
= close_internal_locked(p
, fd
, fp
, 0);
2470 * close_internal_locked
2472 * Close a file descriptor.
2474 * Parameters: p Process in whose per process file table
2475 * the close is to occur
2476 * fd fd to be closed
2477 * fp fileproc associated with the fd
2479 * Returns: 0 Success
2480 * EBADF fd already in close wait state
2481 * closef_locked:??? Anything returnable by a per-fileops
2484 * Locks: Assumes proc_fdlock for process is held by the caller and returns
2487 * Notes: This function may drop and reacquire this lock; it is unsafe
2488 * for a caller to assume that other state protected by the lock
2489 * has not been subsequently changed out from under it.
2492 close_internal_locked(proc_t p
, int fd
, struct fileproc
*fp
, int flags
)
2494 struct filedesc
*fdp
= p
->p_fd
;
2496 int resvfd
= flags
& FD_DUP2RESV
;
2500 proc_fdlock_assert(p
, LCK_MTX_ASSERT_OWNED
);
2503 /* Keep people from using the filedesc while we are closing it */
2504 procfdtbl_markclosefd(p
, fd
);
2507 if ((fp
->f_flags
& FP_CLOSING
) == FP_CLOSING
) {
2508 panic("close_internal_locked: being called on already closing fd");
2513 if ((fdp
->fd_ofileflags
[fd
] & UF_RESERVED
) == 0)
2514 panic("close_internal: unreserved fileflags with fd %d", fd
);
2517 fp
->f_flags
|= FP_CLOSING
;
2519 if ( (fp
->f_flags
& FP_AIOISSUED
) || kauth_authorize_fileop_has_listeners() ) {
2523 if ( (fp
->f_type
== DTYPE_VNODE
) && kauth_authorize_fileop_has_listeners() ) {
2525 * call out to allow 3rd party notification of close.
2526 * Ignore result of kauth_authorize_fileop call.
2528 if (vnode_getwithref((vnode_t
)fp
->f_data
) == 0) {
2529 u_int fileop_flags
= 0;
2530 if ((fp
->f_flags
& FP_WRITTEN
) != 0)
2531 fileop_flags
|= KAUTH_FILEOP_CLOSE_MODIFIED
;
2532 kauth_authorize_fileop(fp
->f_fglob
->fg_cred
, KAUTH_FILEOP_CLOSE
,
2533 (uintptr_t)fp
->f_data
, (uintptr_t)fileop_flags
);
2534 vnode_put((vnode_t
)fp
->f_data
);
2537 if (fp
->f_flags
& FP_AIOISSUED
)
2539 * cancel all async IO requests that can be cancelled.
2541 _aio_close( p
, fd
);
2546 if (fd
< fdp
->fd_knlistsize
)
2547 knote_fdclose(p
, fd
);
2549 if (fp
->f_flags
& FP_WAITEVENT
)
2550 (void)waitevent_close(p
, fp
);
2552 fileproc_drain(p
, fp
);
2557 procfdtbl_reservefd(p
, fd
);
2560 error
= closef_locked(fp
, fp
->f_fglob
, p
);
2561 if ((fp
->f_flags
& FP_WAITCLOSE
) == FP_WAITCLOSE
)
2562 wakeup(&fp
->f_flags
);
2563 fp
->f_flags
&= ~(FP_WAITCLOSE
| FP_CLOSING
);
2573 if ((fdp
->fd_ofileflags
[fd
] & UF_RESERVED
) == 0)
2574 panic("close with reserved fd returns with freed fd:%d: proc: %p", fd
, p
);
2585 * Description: Return status information about a file descriptor.
2587 * Parameters: p The process doing the fstat
2589 * ub The user stat buffer
2590 * xsecurity The user extended security
2591 * buffer, or 0 if none
2592 * xsecurity_size The size of xsecurity, or 0
2594 * isstat64 Flag to indicate 64 bit version
2595 * for inode size, etc.
2597 * Returns: 0 Success
2600 * fp_lookup:EBADF Bad file descriptor
2601 * vnode_getwithref:???
2603 * vnode_getwithref:???
2610 * Notes: Internal implementation for all other fstat() related
2613 * XXX switch on node type is bogus; need a stat in struct
2614 * XXX fileops instead.
2617 fstat1(proc_t p
, int fd
, user_addr_t ub
, user_addr_t xsecurity
, user_addr_t xsecurity_size
, int isstat64
)
2619 struct fileproc
*fp
;
2625 struct user64_stat user64_sb
;
2626 struct user32_stat user32_sb
;
2627 struct user64_stat64 user64_sb64
;
2628 struct user32_stat64 user32_sb64
;
2634 kauth_filesec_t fsec
;
2635 user_size_t xsecurity_bufsize
;
2636 vfs_context_t ctx
= vfs_context_current();
2642 if ((error
= fp_lookup(p
, fd
, &fp
, 0)) != 0) {
2647 fsec
= KAUTH_FILESEC_NONE
;
2649 sbptr
= (void *)&source
;
2654 if ((error
= vnode_getwithref((vnode_t
)data
)) == 0) {
2656 * If the caller has the file open, and is not
2657 * requesting extended security information, we are
2658 * going to let them get the basic stat information.
2660 if (xsecurity
== USER_ADDR_NULL
) {
2661 error
= vn_stat_noauth((vnode_t
)data
, sbptr
, NULL
, isstat64
, ctx
);
2663 error
= vn_stat((vnode_t
)data
, sbptr
, &fsec
, isstat64
, ctx
);
2666 AUDIT_ARG(vnpath
, (struct vnode
*)data
, ARG_VNODE1
);
2667 (void)vnode_put((vnode_t
)data
);
2673 error
= soo_stat((struct socket
*)data
, sbptr
, isstat64
);
2675 #endif /* SOCKETS */
2678 error
= pipe_stat((void *)data
, sbptr
, isstat64
);
2682 error
= pshm_stat((void *)data
, sbptr
, isstat64
);
2686 funnel_state
= thread_funnel_set(kernel_flock
, TRUE
);
2687 error
= kqueue_stat(fp
, sbptr
, isstat64
, p
);
2688 thread_funnel_set(kernel_flock
, funnel_state
);
2698 if (isstat64
!= 0) {
2699 source
.sb64
.st_lspare
= 0;
2700 source
.sb64
.st_qspare
[0] = 0LL;
2701 source
.sb64
.st_qspare
[1] = 0LL;
2703 if (IS_64BIT_PROCESS(current_proc())) {
2704 munge_user64_stat64(&source
.sb64
, &dest
.user64_sb64
);
2705 my_size
= sizeof(dest
.user64_sb64
);
2706 sbp
= (caddr_t
)&dest
.user64_sb64
;
2708 munge_user32_stat64(&source
.sb64
, &dest
.user32_sb64
);
2709 my_size
= sizeof(dest
.user32_sb64
);
2710 sbp
= (caddr_t
)&dest
.user32_sb64
;
2713 source
.sb
.st_lspare
= 0;
2714 source
.sb
.st_qspare
[0] = 0LL;
2715 source
.sb
.st_qspare
[1] = 0LL;
2716 if (IS_64BIT_PROCESS(current_proc())) {
2717 munge_user64_stat(&source
.sb
, &dest
.user64_sb
);
2718 my_size
= sizeof(dest
.user64_sb
);
2719 sbp
= (caddr_t
)&dest
.user64_sb
;
2721 munge_user32_stat(&source
.sb
, &dest
.user32_sb
);
2722 my_size
= sizeof(dest
.user32_sb
);
2723 sbp
= (caddr_t
)&dest
.user32_sb
;
2727 error
= copyout(sbp
, ub
, my_size
);
2730 /* caller wants extended security information? */
2731 if (xsecurity
!= USER_ADDR_NULL
) {
2733 /* did we get any? */
2734 if (fsec
== KAUTH_FILESEC_NONE
) {
2735 if (susize(xsecurity_size
, 0) != 0) {
2740 /* find the user buffer size */
2741 xsecurity_bufsize
= fusize(xsecurity_size
);
2743 /* copy out the actual data size */
2744 if (susize(xsecurity_size
, KAUTH_FILESEC_COPYSIZE(fsec
)) != 0) {
2749 /* if the caller supplied enough room, copy out to it */
2750 if (xsecurity_bufsize
>= KAUTH_FILESEC_COPYSIZE(fsec
))
2751 error
= copyout(fsec
, xsecurity
, KAUTH_FILESEC_COPYSIZE(fsec
));
2755 fp_drop(p
, fd
, fp
, 0);
2757 kauth_filesec_free(fsec
);
2765 * Description: Extended version of fstat supporting returning extended
2766 * security information
2768 * Parameters: p The process doing the fstat
2769 * uap->fd The fd to stat
2770 * uap->ub The user stat buffer
2771 * uap->xsecurity The user extended security
2772 * buffer, or 0 if none
2773 * uap->xsecurity_size The size of xsecurity, or 0
2775 * Returns: 0 Success
2776 * !0 Errno (see fstat1)
2779 fstat_extended(proc_t p
, struct fstat_extended_args
*uap
, __unused
int32_t *retval
)
2781 return(fstat1(p
, uap
->fd
, uap
->ub
, uap
->xsecurity
, uap
->xsecurity_size
, 0));
2788 * Description: Get file status for the file associated with fd
2790 * Parameters: p The process doing the fstat
2791 * uap->fd The fd to stat
2792 * uap->ub The user stat buffer
2794 * Returns: 0 Success
2795 * !0 Errno (see fstat1)
2798 fstat(proc_t p
, register struct fstat_args
*uap
, __unused
int32_t *retval
)
2800 return(fstat1(p
, uap
->fd
, uap
->ub
, 0, 0, 0));
2807 * Description: Extended version of fstat64 supporting returning extended
2808 * security information
2810 * Parameters: p The process doing the fstat
2811 * uap->fd The fd to stat
2812 * uap->ub The user stat buffer
2813 * uap->xsecurity The user extended security
2814 * buffer, or 0 if none
2815 * uap->xsecurity_size The size of xsecurity, or 0
2817 * Returns: 0 Success
2818 * !0 Errno (see fstat1)
2821 fstat64_extended(proc_t p
, struct fstat64_extended_args
*uap
, __unused
int32_t *retval
)
2823 return(fstat1(p
, uap
->fd
, uap
->ub
, uap
->xsecurity
, uap
->xsecurity_size
, 1));
2830 * Description: Get 64 bit version of the file status for the file associated
2833 * Parameters: p The process doing the fstat
2834 * uap->fd The fd to stat
2835 * uap->ub The user stat buffer
2837 * Returns: 0 Success
2838 * !0 Errno (see fstat1)
2841 fstat64(proc_t p
, register struct fstat64_args
*uap
, __unused
int32_t *retval
)
2843 return(fstat1(p
, uap
->fd
, uap
->ub
, 0, 0, 1));
2850 * Description: Return pathconf information about a file descriptor.
2852 * Parameters: p Process making the request
2853 * uap->fd fd to get information about
2854 * uap->name Name of information desired
2855 * retval Pointer to the call return area
2857 * Returns: 0 Success
2859 * fp_lookup:EBADF Bad file descriptor
2860 * vnode_getwithref:???
2864 * *retval (modified) Returned information (numeric)
2867 fpathconf(proc_t p
, struct fpathconf_args
*uap
, int32_t *retval
)
2870 struct fileproc
*fp
;
2877 AUDIT_ARG(fd
, uap
->fd
);
2878 if ( (error
= fp_lookup(p
, fd
, &fp
, 0)) )
2886 if (uap
->name
!= _PC_PIPE_BUF
) {
2895 if (uap
->name
!= _PC_PIPE_BUF
) {
2904 vp
= (struct vnode
*)data
;
2906 if ( (error
= vnode_getwithref(vp
)) == 0) {
2907 AUDIT_ARG(vnpath
, vp
, ARG_VNODE1
);
2909 error
= vn_pathconf(vp
, uap
->name
, retval
, vfs_context_current());
2911 (void)vnode_put(vp
);
2922 fp_drop(p
, fd
, fp
, 0);
2927 * Statistics counter for the number of times a process calling fdalloc()
2928 * has resulted in an expansion of the per process open file table.
2930 * XXX This would likely be of more use if it were per process
2938 * Description: Allocate a file descriptor for the process.
2940 * Parameters: p Process to allocate the fd in
2941 * want The fd we would prefer to get
2942 * result Pointer to fd we got
2944 * Returns: 0 Success
2949 * *result (modified) The fd which was allocated
2952 fdalloc(proc_t p
, int want
, int *result
)
2954 struct filedesc
*fdp
= p
->p_fd
;
2956 int lim
, last
, numfiles
, oldnfiles
;
2957 struct fileproc
**newofiles
, **ofiles
;
2958 char *newofileflags
;
2961 * Search for a free descriptor starting at the higher
2962 * of want or fd_freefile. If that fails, consider
2963 * expanding the ofile array.
2966 proc_fdlock_assert(p
, LCK_MTX_ASSERT_OWNED
);
2969 lim
= min((int)p
->p_rlimit
[RLIMIT_NOFILE
].rlim_cur
, maxfiles
);
2971 last
= min(fdp
->fd_nfiles
, lim
);
2972 if ((i
= want
) < fdp
->fd_freefile
)
2973 i
= fdp
->fd_freefile
;
2974 for (; i
< last
; i
++) {
2975 if (fdp
->fd_ofiles
[i
] == NULL
&& !(fdp
->fd_ofileflags
[i
] & UF_RESERVED
)) {
2976 procfdtbl_reservefd(p
, i
);
2977 if (i
> fdp
->fd_lastfile
)
2978 fdp
->fd_lastfile
= i
;
2979 if (want
<= fdp
->fd_freefile
)
2980 fdp
->fd_freefile
= i
;
2987 * No space in current array. Expand?
2989 if (fdp
->fd_nfiles
>= lim
)
2991 if (fdp
->fd_nfiles
< NDEXTENT
)
2992 numfiles
= NDEXTENT
;
2994 numfiles
= 2 * fdp
->fd_nfiles
;
2999 MALLOC_ZONE(newofiles
, struct fileproc
**,
3000 numfiles
* OFILESIZE
, M_OFILETABL
, M_WAITOK
);
3002 if (newofiles
== NULL
) {
3005 if (fdp
->fd_nfiles
>= numfiles
) {
3006 FREE_ZONE(newofiles
, numfiles
* OFILESIZE
, M_OFILETABL
);
3009 newofileflags
= (char *) &newofiles
[numfiles
];
3011 * Copy the existing ofile and ofileflags arrays
3012 * and zero the new portion of each array.
3014 oldnfiles
= fdp
->fd_nfiles
;
3015 (void) memcpy(newofiles
, fdp
->fd_ofiles
,
3016 oldnfiles
* sizeof(*fdp
->fd_ofiles
));
3017 (void) memset(&newofiles
[oldnfiles
], 0,
3018 (numfiles
- oldnfiles
) * sizeof(*fdp
->fd_ofiles
));
3020 (void) memcpy(newofileflags
, fdp
->fd_ofileflags
,
3021 oldnfiles
* sizeof(*fdp
->fd_ofileflags
));
3022 (void) memset(&newofileflags
[oldnfiles
], 0,
3023 (numfiles
- oldnfiles
) *
3024 sizeof(*fdp
->fd_ofileflags
));
3025 ofiles
= fdp
->fd_ofiles
;
3026 fdp
->fd_ofiles
= newofiles
;
3027 fdp
->fd_ofileflags
= newofileflags
;
3028 fdp
->fd_nfiles
= numfiles
;
3029 FREE_ZONE(ofiles
, oldnfiles
* OFILESIZE
, M_OFILETABL
);
3038 * Description: Check to see whether n user file descriptors are available
3041 * Parameters: p Process to check in
3042 * n The number of fd's desired
3047 * Locks: Assumes proc_fdlock for process is held by the caller
3049 * Notes: The answer only remains valid so long as the proc_fdlock is
3050 * held by the caller.
3053 fdavail(proc_t p
, int n
)
3055 struct filedesc
*fdp
= p
->p_fd
;
3056 struct fileproc
**fpp
;
3060 lim
= min((int)p
->p_rlimit
[RLIMIT_NOFILE
].rlim_cur
, maxfiles
);
3061 if ((i
= lim
- fdp
->fd_nfiles
) > 0 && (n
-= i
) <= 0)
3063 fpp
= &fdp
->fd_ofiles
[fdp
->fd_freefile
];
3064 flags
= &fdp
->fd_ofileflags
[fdp
->fd_freefile
];
3065 for (i
= fdp
->fd_nfiles
- fdp
->fd_freefile
; --i
>= 0; fpp
++, flags
++)
3066 if (*fpp
== NULL
&& !(*flags
& UF_RESERVED
) && --n
<= 0)
3075 * Description: Legacy KPI wrapper function for _fdrelse
3077 * Parameters: p Process in which fd lives
3082 * Locks: Assumes proc_fdlock for process is held by the caller
3085 fdrelse(proc_t p
, int fd
)
3094 * Description: Get the fileproc pointer for the given fd from the per process
3095 * open file table without taking an explicit reference on it.
3097 * Parameters: p Process containing fd
3098 * fd fd to obtain fileproc for
3099 * resultfp Pointer to pointer return area
3101 * Returns: 0 Success
3105 * *resultfp (modified) Pointer to fileproc pointer
3107 * Locks: Assumes proc_fdlock for process is held by the caller
3109 * Notes: Because there is no reference explicitly taken, the returned
3110 * fileproc pointer is only valid so long as the proc_fdlock
3111 * remains held by the caller.
3114 fdgetf_noref(proc_t p
, int fd
, struct fileproc
**resultfp
)
3116 struct filedesc
*fdp
= p
->p_fd
;
3117 struct fileproc
*fp
;
3119 if (fd
< 0 || fd
>= fdp
->fd_nfiles
||
3120 (fp
= fdp
->fd_ofiles
[fd
]) == NULL
||
3121 (fdp
->fd_ofileflags
[fd
] & UF_RESERVED
)) {
3133 * Description: Get fileproc and vnode pointer for a given fd from the per
3134 * process open file table of the specified process, and if
3135 * successful, increment the f_iocount
3137 * Parameters: p Process in which fd lives
3138 * fd fd to get information for
3139 * resultfp Pointer to result fileproc
3140 * pointer area, or 0 if none
3141 * resultvp Pointer to result vnode pointer
3142 * area, or 0 if none
3144 * Returns: 0 Success
3145 * EBADF Bad file descriptor
3146 * ENOTSUP fd does not refer to a vnode
3149 * *resultfp (modified) Fileproc pointer
3150 * *resultvp (modified) vnode pointer
3152 * Notes: The resultfp and resultvp fields are optional, and may be
3153 * independently specified as NULL to skip returning information
3155 * Locks: Internally takes and releases proc_fdlock
3158 fp_getfvp(proc_t p
, int fd
, struct fileproc
**resultfp
, struct vnode
**resultvp
)
3160 struct filedesc
*fdp
= p
->p_fd
;
3161 struct fileproc
*fp
;
3163 proc_fdlock_spin(p
);
3164 if (fd
< 0 || fd
>= fdp
->fd_nfiles
||
3165 (fp
= fdp
->fd_ofiles
[fd
]) == NULL
||
3166 (fdp
->fd_ofileflags
[fd
] & UF_RESERVED
)) {
3170 if (fp
->f_type
!= DTYPE_VNODE
) {
3179 *resultvp
= (struct vnode
*)fp
->f_data
;
3189 * Description: Get fileproc, vnode pointer, and vid for a given fd from the
3190 * per process open file table of the specified process, and if
3191 * successful, increment the f_iocount
3193 * Parameters: p Process in which fd lives
3194 * fd fd to get information for
3195 * resultfp Pointer to result fileproc
3196 * pointer area, or 0 if none
3197 * resultvp Pointer to result vnode pointer
3198 * area, or 0 if none
3199 * vidp Pointer to resuld vid area
3201 * Returns: 0 Success
3202 * EBADF Bad file descriptor
3203 * ENOTSUP fd does not refer to a vnode
3206 * *resultfp (modified) Fileproc pointer
3207 * *resultvp (modified) vnode pointer
3210 * Notes: The resultfp and resultvp fields are optional, and may be
3211 * independently specified as NULL to skip returning information
3213 * Locks: Internally takes and releases proc_fdlock
3216 fp_getfvpandvid(proc_t p
, int fd
, struct fileproc
**resultfp
,
3217 struct vnode
**resultvp
, uint32_t *vidp
)
3219 struct filedesc
*fdp
= p
->p_fd
;
3220 struct fileproc
*fp
;
3222 proc_fdlock_spin(p
);
3223 if (fd
< 0 || fd
>= fdp
->fd_nfiles
||
3224 (fp
= fdp
->fd_ofiles
[fd
]) == NULL
||
3225 (fdp
->fd_ofileflags
[fd
] & UF_RESERVED
)) {
3229 if (fp
->f_type
!= DTYPE_VNODE
) {
3238 *resultvp
= (struct vnode
*)fp
->f_data
;
3240 *vidp
= (uint32_t)vnode_vid((struct vnode
*)fp
->f_data
);
3250 * Description: Get fileproc and socket pointer for a given fd from the
3251 * per process open file table of the specified process, and if
3252 * successful, increment the f_iocount
3254 * Parameters: p Process in which fd lives
3255 * fd fd to get information for
3256 * resultfp Pointer to result fileproc
3257 * pointer area, or 0 if none
3258 * results Pointer to result socket
3259 * pointer area, or 0 if none
3261 * Returns: EBADF The file descriptor is invalid
3262 * EOPNOTSUPP The file descriptor is not a socket
3266 * *resultfp (modified) Fileproc pointer
3267 * *results (modified) socket pointer
3269 * Notes: EOPNOTSUPP should probably be ENOTSOCK; this function is only
3270 * ever called from accept1().
3273 fp_getfsock(proc_t p
, int fd
, struct fileproc
**resultfp
,
3274 struct socket
**results
)
3276 struct filedesc
*fdp
= p
->p_fd
;
3277 struct fileproc
*fp
;
3279 proc_fdlock_spin(p
);
3280 if (fd
< 0 || fd
>= fdp
->fd_nfiles
||
3281 (fp
= fdp
->fd_ofiles
[fd
]) == NULL
||
3282 (fdp
->fd_ofileflags
[fd
] & UF_RESERVED
)) {
3286 if (fp
->f_type
!= DTYPE_SOCKET
) {
3295 *results
= (struct socket
*)fp
->f_data
;
3305 * Description: Get fileproc and kqueue pointer for a given fd from the
3306 * per process open file table of the specified process, and if
3307 * successful, increment the f_iocount
3309 * Parameters: p Process in which fd lives
3310 * fd fd to get information for
3311 * resultfp Pointer to result fileproc
3312 * pointer area, or 0 if none
3313 * resultkq Pointer to result kqueue
3314 * pointer area, or 0 if none
3316 * Returns: EBADF The file descriptor is invalid
3317 * EBADF The file descriptor is not a socket
3321 * *resultfp (modified) Fileproc pointer
3322 * *resultkq (modified) kqueue pointer
3324 * Notes: The second EBADF should probably be something else to make
3325 * the error condition distinct.
3328 fp_getfkq(proc_t p
, int fd
, struct fileproc
**resultfp
,
3329 struct kqueue
**resultkq
)
3331 struct filedesc
*fdp
= p
->p_fd
;
3332 struct fileproc
*fp
;
3334 proc_fdlock_spin(p
);
3335 if ( fd
< 0 || fd
>= fdp
->fd_nfiles
||
3336 (fp
= fdp
->fd_ofiles
[fd
]) == NULL
||
3337 (fdp
->fd_ofileflags
[fd
] & UF_RESERVED
)) {
3341 if (fp
->f_type
!= DTYPE_KQUEUE
) {
3350 *resultkq
= (struct kqueue
*)fp
->f_data
;
3360 * Description: Get fileproc and POSIX shared memory pointer for a given fd
3361 * from the per process open file table of the specified process
3362 * and if successful, increment the f_iocount
3364 * Parameters: p Process in which fd lives
3365 * fd fd to get information for
3366 * resultfp Pointer to result fileproc
3367 * pointer area, or 0 if none
3368 * resultpshm Pointer to result POSIX
3369 * shared memory pointer
3370 * pointer area, or 0 if none
3372 * Returns: EBADF The file descriptor is invalid
3373 * EBADF The file descriptor is not a POSIX
3374 * shared memory area
3378 * *resultfp (modified) Fileproc pointer
3379 * *resultpshm (modified) POSIX shared memory pointer
3381 * Notes: The second EBADF should probably be something else to make
3382 * the error condition distinct.
3385 fp_getfpshm(proc_t p
, int fd
, struct fileproc
**resultfp
,
3386 struct pshmnode
**resultpshm
)
3388 struct filedesc
*fdp
= p
->p_fd
;
3389 struct fileproc
*fp
;
3391 proc_fdlock_spin(p
);
3392 if (fd
< 0 || fd
>= fdp
->fd_nfiles
||
3393 (fp
= fdp
->fd_ofiles
[fd
]) == NULL
||
3394 (fdp
->fd_ofileflags
[fd
] & UF_RESERVED
)) {
3398 if (fp
->f_type
!= DTYPE_PSXSHM
) {
3408 *resultpshm
= (struct pshmnode
*)fp
->f_data
;
3418 * Description: Get fileproc and POSIX semaphore pointer for a given fd from
3419 * the per process open file table of the specified process
3420 * and if successful, increment the f_iocount
3422 * Parameters: p Process in which fd lives
3423 * fd fd to get information for
3424 * resultfp Pointer to result fileproc
3425 * pointer area, or 0 if none
3426 * resultpsem Pointer to result POSIX
3427 * semaphore pointer area, or
3430 * Returns: EBADF The file descriptor is invalid
3431 * EBADF The file descriptor is not a POSIX
3436 * *resultfp (modified) Fileproc pointer
3437 * *resultpsem (modified) POSIX semaphore pointer
3439 * Notes: The second EBADF should probably be something else to make
3440 * the error condition distinct.
3442 * In order to support unnamed POSIX semaphores, the named
3443 * POSIX semaphores will have to move out of the per-process
3444 * open filetable, and into a global table that is shared with
3445 * unnamed POSIX semaphores, since unnamed POSIX semaphores
3446 * are typically used by declaring instances in shared memory,
3447 * and there's no other way to do this without changing the
3448 * underlying type, which would introduce binary compatibility
3452 fp_getfpsem(proc_t p
, int fd
, struct fileproc
**resultfp
,
3453 struct psemnode
**resultpsem
)
3455 struct filedesc
*fdp
= p
->p_fd
;
3456 struct fileproc
*fp
;
3458 proc_fdlock_spin(p
);
3459 if (fd
< 0 || fd
>= fdp
->fd_nfiles
||
3460 (fp
= fdp
->fd_ofiles
[fd
]) == NULL
||
3461 (fdp
->fd_ofileflags
[fd
] & UF_RESERVED
)) {
3465 if (fp
->f_type
!= DTYPE_PSXSEM
) {
3474 *resultpsem
= (struct psemnode
*)fp
->f_data
;
3484 * Description: Get fileproc and pipe pointer for a given fd from the
3485 * per process open file table of the specified process
3486 * and if successful, increment the f_iocount
3488 * Parameters: p Process in which fd lives
3489 * fd fd to get information for
3490 * resultfp Pointer to result fileproc
3491 * pointer area, or 0 if none
3492 * resultpipe Pointer to result pipe
3493 * pointer area, or 0 if none
3495 * Returns: EBADF The file descriptor is invalid
3496 * EBADF The file descriptor is not a socket
3500 * *resultfp (modified) Fileproc pointer
3501 * *resultpipe (modified) pipe pointer
3503 * Notes: The second EBADF should probably be something else to make
3504 * the error condition distinct.
3507 fp_getfpipe(proc_t p
, int fd
, struct fileproc
**resultfp
,
3508 struct pipe
**resultpipe
)
3510 struct filedesc
*fdp
= p
->p_fd
;
3511 struct fileproc
*fp
;
3513 proc_fdlock_spin(p
);
3514 if (fd
< 0 || fd
>= fdp
->fd_nfiles
||
3515 (fp
= fdp
->fd_ofiles
[fd
]) == NULL
||
3516 (fdp
->fd_ofileflags
[fd
] & UF_RESERVED
)) {
3520 if (fp
->f_type
!= DTYPE_PIPE
) {
3529 *resultpipe
= (struct pipe
*)fp
->f_data
;
3538 * Description: Get fileproc pointer for a given fd from the per process
3539 * open file table of the specified process and if successful,
3540 * increment the f_iocount
3542 * Parameters: p Process in which fd lives
3543 * fd fd to get information for
3544 * resultfp Pointer to result fileproc
3545 * pointer area, or 0 if none
3546 * locked !0 if the caller holds the
3547 * proc_fdlock, 0 otherwise
3549 * Returns: 0 Success
3550 * EBADF Bad file descriptor
3553 * *resultfp (modified) Fileproc pointer
3555 * Locks: If the argument 'locked' is non-zero, then the caller is
3556 * expected to have taken and held the proc_fdlock; if it is
3557 * zero, than this routine internally takes and drops this lock.
3560 fp_lookup(proc_t p
, int fd
, struct fileproc
**resultfp
, int locked
)
3562 struct filedesc
*fdp
= p
->p_fd
;
3563 struct fileproc
*fp
;
3566 proc_fdlock_spin(p
);
3567 if (fd
< 0 || fdp
== NULL
|| fd
>= fdp
->fd_nfiles
||
3568 (fp
= fdp
->fd_ofiles
[fd
]) == NULL
||
3569 (fdp
->fd_ofileflags
[fd
] & UF_RESERVED
)) {
3588 * Description: Swap the fileproc pointer for a given fd with a new
3589 * fileproc pointer in the per-process open file table of
3590 * the specified process. The fdlock must be held at entry.
3592 * Parameters: p Process containing the fd
3593 * fd The fd of interest
3594 * nfp Pointer to the newfp
3596 * Returns: 0 Success
3597 * EBADF Bad file descriptor
3599 * EKEEPLOOKING f_iocount changed while lock was dropped.
3602 fp_tryswap(proc_t p
, int fd
, struct fileproc
*nfp
)
3604 struct fileproc
*fp
;
3607 proc_fdlock_assert(p
, LCK_MTX_ASSERT_OWNED
);
3609 if (0 != (error
= fp_lookup(p
, fd
, &fp
, 1)))
3612 * At this point, our caller (change_guardedfd_np) has
3613 * one f_iocount reference, and we just took another
3614 * one to begin the replacement.
3616 if (fp
->f_iocount
< 2) {
3617 panic("f_iocount too small %d", fp
->f_iocount
);
3618 } else if (2 == fp
->f_iocount
) {
3620 /* Copy the contents of *fp, preserving the "type" of *nfp */
3622 nfp
->f_flags
= (nfp
->f_flags
& FP_TYPEMASK
) |
3623 (fp
->f_flags
& ~FP_TYPEMASK
);
3624 nfp
->f_iocount
= fp
->f_iocount
;
3625 nfp
->f_fglob
= fp
->f_fglob
;
3626 nfp
->f_waddr
= fp
->f_waddr
;
3628 p
->p_fd
->fd_ofiles
[fd
] = nfp
;
3629 (void) fp_drop(p
, fd
, nfp
, 1);
3632 * Wait for all other active references to evaporate.
3634 p
->p_fpdrainwait
= 1;
3635 error
= msleep(&p
->p_fpdrainwait
, &p
->p_fdmlock
,
3636 PRIBIO
| PCATCH
, "tryswap fpdrain", NULL
);
3639 * Return an "internal" errno to trigger a full
3640 * reevaluation of the change-guard attempt.
3642 error
= EKEEPLOOKING
;
3643 printf("%s: lookup collision fd %d\n", __func__
, fd
);
3645 (void) fp_drop(p
, fd
, fp
, 1);
3654 * Description: Set the FP_WRITTEN flag on the fileproc and drop the I/O
3655 * reference previously taken by calling fp_lookup et. al.
3657 * Parameters: p Process in which the fd lives
3658 * fd fd associated with the fileproc
3659 * fp fileproc on which to set the
3660 * flag and drop the reference
3662 * Returns: 0 Success
3663 * fp_drop:EBADF Bad file descriptor
3665 * Locks: This function internally takes and drops the proc_fdlock for
3666 * the supplied process
3668 * Notes: The fileproc must correspond to the fd in the supplied proc
3671 fp_drop_written(proc_t p
, int fd
, struct fileproc
*fp
)
3675 proc_fdlock_spin(p
);
3677 fp
->f_flags
|= FP_WRITTEN
;
3679 error
= fp_drop(p
, fd
, fp
, 1);
3690 * Description: Set the FP_WAITEVENT flag on the fileproc and drop the I/O
3691 * reference previously taken by calling fp_lookup et. al.
3693 * Parameters: p Process in which the fd lives
3694 * fd fd associated with the fileproc
3695 * fp fileproc on which to set the
3696 * flag and drop the reference
3698 * Returns: 0 Success
3699 * fp_drop:EBADF Bad file descriptor
3701 * Locks: This function internally takes and drops the proc_fdlock for
3702 * the supplied process
3704 * Notes: The fileproc must correspond to the fd in the supplied proc
3707 fp_drop_event(proc_t p
, int fd
, struct fileproc
*fp
)
3711 proc_fdlock_spin(p
);
3713 fp
->f_flags
|= FP_WAITEVENT
;
3715 error
= fp_drop(p
, fd
, fp
, 1);
3726 * Description: Drop the I/O reference previously taken by calling fp_lookup
3729 * Parameters: p Process in which the fd lives
3730 * fd fd associated with the fileproc
3731 * fp fileproc on which to set the
3732 * flag and drop the reference
3733 * locked flag to internally take and
3734 * drop proc_fdlock if it is not
3735 * already held by the caller
3737 * Returns: 0 Success
3738 * EBADF Bad file descriptor
3740 * Locks: This function internally takes and drops the proc_fdlock for
3741 * the supplied process if 'locked' is non-zero, and assumes that
3742 * the caller already holds this lock if 'locked' is non-zero.
3744 * Notes: The fileproc must correspond to the fd in the supplied proc
3747 fp_drop(proc_t p
, int fd
, struct fileproc
*fp
, int locked
)
3749 struct filedesc
*fdp
= p
->p_fd
;
3753 proc_fdlock_spin(p
);
3754 if ((fp
== FILEPROC_NULL
) && (fd
< 0 || fd
>= fdp
->fd_nfiles
||
3755 (fp
= fdp
->fd_ofiles
[fd
]) == NULL
||
3756 ((fdp
->fd_ofileflags
[fd
] & UF_RESERVED
) &&
3757 !(fdp
->fd_ofileflags
[fd
] & UF_CLOSING
)))) {
3764 if (fp
->f_iocount
== 0) {
3765 if (fp
->f_flags
& FP_SELCONFLICT
)
3766 fp
->f_flags
&= ~FP_SELCONFLICT
;
3768 if (p
->p_fpdrainwait
) {
3769 p
->p_fpdrainwait
= 0;
3776 wakeup(&p
->p_fpdrainwait
);
3785 * Description: Given an fd, look it up in the current process's per process
3786 * open file table, and return its internal vnode pointer.
3788 * Parameters: fd fd to obtain vnode from
3789 * vpp pointer to vnode return area
3791 * Returns: 0 Success
3792 * EINVAL The fd does not refer to a
3793 * vnode fileproc entry
3794 * fp_lookup:EBADF Bad file descriptor
3797 * *vpp (modified) Returned vnode pointer
3799 * Locks: This function internally takes and drops the proc_fdlock for
3800 * the current process
3802 * Notes: If successful, this function increments the f_iocount on the
3803 * fd's corresponding fileproc.
3805 * The fileproc referenced is not returned; because of this, care
3806 * must be taken to not drop the last reference (e.g. by closing
3807 * the file). This is inherently unsafe, since the reference may
3808 * not be recoverable from the vnode, if there is a subsequent
3809 * close that destroys the associate fileproc. The caller should
3810 * therefore retain their own reference on the fileproc so that
3811 * the f_iocount can be dropped subsequently. Failure to do this
3812 * can result in the returned pointer immediately becoming invalid
3813 * following the call.
3815 * Use of this function is discouraged.
3818 file_vnode(int fd
, struct vnode
**vpp
)
3820 proc_t p
= current_proc();
3821 struct fileproc
*fp
;
3824 proc_fdlock_spin(p
);
3825 if ( (error
= fp_lookup(p
, fd
, &fp
, 1)) ) {
3829 if (fp
->f_type
!= DTYPE_VNODE
) {
3830 fp_drop(p
, fd
, fp
,1);
3835 *vpp
= (struct vnode
*)fp
->f_data
;
3843 * file_vnode_withvid
3845 * Description: Given an fd, look it up in the current process's per process
3846 * open file table, and return its internal vnode pointer.
3848 * Parameters: fd fd to obtain vnode from
3849 * vpp pointer to vnode return area
3850 * vidp pointer to vid of the returned vnode
3852 * Returns: 0 Success
3853 * EINVAL The fd does not refer to a
3854 * vnode fileproc entry
3855 * fp_lookup:EBADF Bad file descriptor
3858 * *vpp (modified) Returned vnode pointer
3860 * Locks: This function internally takes and drops the proc_fdlock for
3861 * the current process
3863 * Notes: If successful, this function increments the f_iocount on the
3864 * fd's corresponding fileproc.
3866 * The fileproc referenced is not returned; because of this, care
3867 * must be taken to not drop the last reference (e.g. by closing
3868 * the file). This is inherently unsafe, since the reference may
3869 * not be recoverable from the vnode, if there is a subsequent
3870 * close that destroys the associate fileproc. The caller should
3871 * therefore retain their own reference on the fileproc so that
3872 * the f_iocount can be dropped subsequently. Failure to do this
3873 * can result in the returned pointer immediately becoming invalid
3874 * following the call.
3876 * Use of this function is discouraged.
3879 file_vnode_withvid(int fd
, struct vnode
**vpp
, uint32_t * vidp
)
3881 proc_t p
= current_proc();
3882 struct fileproc
*fp
;
3886 proc_fdlock_spin(p
);
3887 if ( (error
= fp_lookup(p
, fd
, &fp
, 1)) ) {
3891 if (fp
->f_type
!= DTYPE_VNODE
) {
3892 fp_drop(p
, fd
, fp
,1);
3896 vp
= (struct vnode
*)fp
->f_data
;
3900 if ((vidp
!= NULL
) && (vp
!= NULLVP
))
3901 *vidp
= (uint32_t)vp
->v_id
;
3912 * Description: Given an fd, look it up in the current process's per process
3913 * open file table, and return its internal socket pointer.
3915 * Parameters: fd fd to obtain vnode from
3916 * sp pointer to socket return area
3918 * Returns: 0 Success
3919 * ENOTSOCK Not a socket
3920 * fp_lookup:EBADF Bad file descriptor
3923 * *sp (modified) Returned socket pointer
3925 * Locks: This function internally takes and drops the proc_fdlock for
3926 * the current process
3928 * Notes: If successful, this function increments the f_iocount on the
3929 * fd's corresponding fileproc.
3931 * The fileproc referenced is not returned; because of this, care
3932 * must be taken to not drop the last reference (e.g. by closing
3933 * the file). This is inherently unsafe, since the reference may
3934 * not be recoverable from the socket, if there is a subsequent
3935 * close that destroys the associate fileproc. The caller should
3936 * therefore retain their own reference on the fileproc so that
3937 * the f_iocount can be dropped subsequently. Failure to do this
3938 * can result in the returned pointer immediately becoming invalid
3939 * following the call.
3941 * Use of this function is discouraged.
3944 file_socket(int fd
, struct socket
**sp
)
3946 proc_t p
= current_proc();
3947 struct fileproc
*fp
;
3950 proc_fdlock_spin(p
);
3951 if ( (error
= fp_lookup(p
, fd
, &fp
, 1)) ) {
3955 if (fp
->f_type
!= DTYPE_SOCKET
) {
3956 fp_drop(p
, fd
, fp
,1);
3960 *sp
= (struct socket
*)fp
->f_data
;
3970 * Description: Given an fd, look it up in the current process's per process
3971 * open file table, and return its fileproc's flags field.
3973 * Parameters: fd fd whose flags are to be
3975 * flags pointer to flags data area
3977 * Returns: 0 Success
3978 * ENOTSOCK Not a socket
3979 * fp_lookup:EBADF Bad file descriptor
3982 * *flags (modified) Returned flags field
3984 * Locks: This function internally takes and drops the proc_fdlock for
3985 * the current process
3987 * Notes: This function will internally increment and decrement the
3988 * f_iocount of the fileproc as part of its operation.
3991 file_flags(int fd
, int *flags
)
3994 proc_t p
= current_proc();
3995 struct fileproc
*fp
;
3998 proc_fdlock_spin(p
);
3999 if ( (error
= fp_lookup(p
, fd
, &fp
, 1)) ) {
4003 *flags
= (int)fp
->f_flag
;
4004 fp_drop(p
, fd
, fp
,1);
4014 * Description: Drop an iocount reference on an fd, and wake up any waiters
4015 * for draining (i.e. blocked in fileproc_drain() called during
4016 * the last attempt to close a file).
4018 * Parameters: fd fd on which an ioreference is
4021 * Returns: 0 Success
4022 * EBADF Bad file descriptor
4024 * Description: Given an fd, look it up in the current process's per process
4025 * open file table, and drop it's fileproc's f_iocount by one
4027 * Notes: This is intended as a corresponding operation to the functions
4028 * file_vnode() and file_socket() operations.
4030 * Technically, the close reference is supposed to be protected
4031 * by a fileproc_drain(), however, a drain will only block if
4032 * the fd refers to a character device, and that device has had
4033 * preparefileread() called on it. If it refers to something
4034 * other than a character device, then the drain will occur and
4035 * block each close attempt, rather than merely the last close.
4037 * Since it's possible for an fd that refers to a character
4038 * device to have an intermediate close followed by an open to
4039 * cause a different file to correspond to that descriptor,
4040 * unless there was a cautionary reference taken on the fileproc,
4041 * this is an inherently unsafe function. This happens in the
4042 * case where multiple fd's in a process refer to the same
4043 * character device (e.g. stdin/out/err pointing to a tty, etc.).
4045 * Use of this function is discouraged.
4050 struct fileproc
*fp
;
4051 proc_t p
= current_proc();
4054 proc_fdlock_spin(p
);
4055 if (fd
< 0 || fd
>= p
->p_fd
->fd_nfiles
||
4056 (fp
= p
->p_fd
->fd_ofiles
[fd
]) == NULL
||
4057 ((p
->p_fd
->fd_ofileflags
[fd
] & UF_RESERVED
) &&
4058 !(p
->p_fd
->fd_ofileflags
[fd
] & UF_CLOSING
))) {
4064 if (fp
->f_iocount
== 0) {
4065 if (fp
->f_flags
& FP_SELCONFLICT
)
4066 fp
->f_flags
&= ~FP_SELCONFLICT
;
4068 if (p
->p_fpdrainwait
) {
4069 p
->p_fpdrainwait
= 0;
4076 wakeup(&p
->p_fpdrainwait
);
4081 static int falloc_withalloc_locked(proc_t
, struct fileproc
**, int *,
4082 vfs_context_t
, struct fileproc
* (*)(void *), void *, int);
4087 * Description: Allocate an entry in the per process open file table and
4088 * return the corresponding fileproc and fd.
4090 * Parameters: p The process in whose open file
4091 * table the fd is to be allocated
4092 * resultfp Pointer to fileproc pointer
4094 * resultfd Pointer to fd return area
4097 * Returns: 0 Success
4098 * falloc:ENFILE Too many open files in system
4099 * falloc:EMFILE Too many open files in process
4100 * falloc:ENOMEM M_FILEPROC or M_FILEGLOB zone
4104 * *resultfd (modified) Returned fileproc pointer
4105 * *resultfd (modified) Returned fd
4107 * Locks: This function takes and drops the proc_fdlock; if this lock
4108 * is already held, use falloc_locked() instead.
4110 * Notes: This function takes separate process and context arguments
4111 * solely to support kern_exec.c; otherwise, it would take
4112 * neither, and expect falloc_locked() to use the
4113 * vfs_context_current() routine internally.
4116 falloc(proc_t p
, struct fileproc
**resultfp
, int *resultfd
, vfs_context_t ctx
)
4118 return (falloc_withalloc(p
, resultfp
, resultfd
, ctx
,
4119 fileproc_alloc_init
, NULL
));
4123 * Like falloc, but including the fileproc allocator and create-args
4126 falloc_withalloc(proc_t p
, struct fileproc
**resultfp
, int *resultfd
,
4127 vfs_context_t ctx
, fp_allocfn_t fp_zalloc
, void *arg
)
4132 error
= falloc_withalloc_locked(p
,
4133 resultfp
, resultfd
, ctx
, fp_zalloc
, arg
, 1);
4140 * "uninitialized" ops -- ensure fg->fg_ops->fo_type always exists
4142 static const struct fileops uninitops
;
4147 * Create a new open file structure and allocate
4148 * a file descriptor for the process that refers to it.
4150 * Returns: 0 Success
4152 * Description: Allocate an entry in the per process open file table and
4153 * return the corresponding fileproc and fd.
4155 * Parameters: p The process in whose open file
4156 * table the fd is to be allocated
4157 * resultfp Pointer to fileproc pointer
4159 * resultfd Pointer to fd return area
4161 * locked Flag to indicate whether the
4162 * caller holds proc_fdlock
4164 * Returns: 0 Success
4165 * ENFILE Too many open files in system
4166 * fdalloc:EMFILE Too many open files in process
4167 * ENOMEM M_FILEPROC or M_FILEGLOB zone
4172 * *resultfd (modified) Returned fileproc pointer
4173 * *resultfd (modified) Returned fd
4175 * Locks: If the parameter 'locked' is zero, this function takes and
4176 * drops the proc_fdlock; if non-zero, the caller must hold the
4179 * Notes: If you intend to use a non-zero 'locked' parameter, use the
4180 * utility function falloc() instead.
4182 * This function takes separate process and context arguments
4183 * solely to support kern_exec.c; otherwise, it would take
4184 * neither, and use the vfs_context_current() routine internally.
4187 falloc_locked(proc_t p
, struct fileproc
**resultfp
, int *resultfd
,
4188 vfs_context_t ctx
, int locked
)
4190 return (falloc_withalloc_locked(p
, resultfp
, resultfd
, ctx
,
4191 fileproc_alloc_init
, NULL
, locked
));
4195 falloc_withalloc_locked(proc_t p
, struct fileproc
**resultfp
, int *resultfd
,
4196 vfs_context_t ctx
, fp_allocfn_t fp_zalloc
, void *crarg
,
4199 struct fileproc
*fp
;
4200 struct fileglob
*fg
;
4205 if ( (error
= fdalloc(p
, 0, &nfd
)) ) {
4210 if (nfiles
>= maxfiles
) {
4217 error
= mac_file_check_create(proc_ucred(p
));
4226 * Allocate a new file descriptor.
4227 * If the process has file descriptor zero open, add to the list
4228 * of open files at that point, otherwise put it at the front of
4229 * the list of open files.
4233 fp
= (*fp_zalloc
)(crarg
);
4239 MALLOC_ZONE(fg
, struct fileglob
*, sizeof(struct fileglob
), M_FILEGLOB
, M_WAITOK
);
4246 bzero(fg
, sizeof(struct fileglob
));
4247 lck_mtx_init(&fg
->fg_lock
, file_lck_grp
, file_lck_attr
);
4251 fg
->fg_ops
= &uninitops
;
4254 mac_file_label_init(fg
);
4257 kauth_cred_ref(ctx
->vc_ucred
);
4261 fp
->f_cred
= ctx
->vc_ucred
;
4264 mac_file_label_associate(fp
->f_cred
, fg
);
4267 OSAddAtomic(1, &nfiles
);
4269 p
->p_fd
->fd_ofiles
[nfd
] = fp
;
4286 * Description: Free a file structure; drop the global open file count, and
4287 * drop the credential reference, if the fileglob has one, and
4288 * destroy the instance mutex before freeing
4290 * Parameters: fg Pointer to fileglob to be
4296 fg_free(struct fileglob
*fg
)
4298 OSAddAtomic(-1, &nfiles
);
4300 if (IS_VALID_CRED(fg
->fg_cred
)) {
4301 kauth_cred_unref(&fg
->fg_cred
);
4303 lck_mtx_destroy(&fg
->fg_lock
, file_lck_grp
);
4306 mac_file_label_destroy(fg
);
4308 FREE_ZONE(fg
, sizeof *fg
, M_FILEGLOB
);
4315 * Description: Perform close-on-exec processing for all files in a process
4316 * that are either marked as close-on-exec, or which were in the
4317 * process of being opened at the time of the execve
4319 * Also handles the case (via posix_spawn()) where -all-
4320 * files except those marked with "inherit" as treated as
4323 * Parameters: p Pointer to process calling
4328 * Locks: This function internally takes and drops proc_fdlock()
4330 * Notes: This function drops and retakes the kernel funnel; this is
4331 * inherently unsafe, since another thread may have the
4334 * XXX: We should likely reverse the lock and funnel drop/acquire
4335 * order to avoid the small race window; it's also possible that
4336 * if the program doing the exec has an outstanding listen socket
4337 * and a network connection is completed asynchronously that we
4338 * will end up with a "ghost" socket reference in the new process.
4340 * This needs reworking to make it safe to remove the funnel from
4341 * the execve and posix_spawn system calls.
4344 fdexec(proc_t p
, short flags
)
4346 struct filedesc
*fdp
= p
->p_fd
;
4348 boolean_t cloexec_default
= (flags
& POSIX_SPAWN_CLOEXEC_DEFAULT
) != 0;
4351 for (i
= fdp
->fd_lastfile
; i
>= 0; i
--) {
4353 struct fileproc
*fp
= fdp
->fd_ofiles
[i
];
4354 char *flagp
= &fdp
->fd_ofileflags
[i
];
4356 if (fp
&& cloexec_default
) {
4358 * Reverse the usual semantics of file descriptor
4359 * inheritance - all of them should be closed
4360 * except files marked explicitly as "inherit" and
4361 * not marked close-on-exec.
4363 if ((*flagp
& (UF_EXCLOSE
|UF_INHERIT
)) != UF_INHERIT
)
4364 *flagp
|= UF_EXCLOSE
;
4365 *flagp
&= ~UF_INHERIT
;
4369 ((*flagp
& (UF_RESERVED
|UF_EXCLOSE
)) == UF_EXCLOSE
)
4371 || (fp
&& mac_file_check_inherit(proc_ucred(p
), fp
->f_fglob
))
4374 if (i
< fdp
->fd_knlistsize
)
4375 knote_fdclose(p
, i
);
4376 procfdtbl_clearfd(p
, i
);
4377 if (i
== fdp
->fd_lastfile
&& i
> 0)
4379 if (i
< fdp
->fd_freefile
)
4380 fdp
->fd_freefile
= i
;
4383 * Wait for any third party viewers (e.g., lsof)
4384 * to release their references to this fileproc.
4386 while (fp
->f_iocount
> 0) {
4387 p
->p_fpdrainwait
= 1;
4388 msleep(&p
->p_fpdrainwait
, &p
->p_fdmlock
, PRIBIO
,
4392 closef_locked(fp
, fp
->f_fglob
, p
);
4404 * Description: Copy a filedesc structure. This is normally used as part of
4405 * forkproc() when forking a new process, to copy the per process
4406 * open file table over to the new process.
4408 * Parameters: p Process whose open file table
4409 * is to be copied (parent)
4410 * uth_cdir Per thread current working
4411 * cirectory, or NULL
4413 * Returns: NULL Copy failed
4414 * !NULL Pointer to new struct filedesc
4416 * Locks: This function internally takes and drops proc_fdlock()
4418 * Notes: Files are copied directly, ignoring the new resource limits
4419 * for the process that's being copied into. Since the descriptor
4420 * references are just additional references, this does not count
4421 * against the number of open files on the system.
4423 * The struct filedesc includes the current working directory,
4424 * and the current root directory, if the process is chroot'ed.
4426 * If the exec was called by a thread using a per thread current
4427 * working directory, we inherit the working directory from the
4428 * thread making the call, rather than from the process.
4430 * In the case of a failure to obtain a reference, for most cases,
4431 * the file entry will be silently dropped. There's an exception
4432 * for the case of a chroot dir, since a failure to to obtain a
4433 * reference there would constitute an "escape" from the chroot
4434 * environment, which must not be allowed. In that case, we will
4435 * deny the execve() operation, rather than allowing the escape.
4438 fdcopy(proc_t p
, vnode_t uth_cdir
)
4440 struct filedesc
*newfdp
, *fdp
= p
->p_fd
;
4442 struct fileproc
*ofp
, *fp
;
4445 MALLOC_ZONE(newfdp
, struct filedesc
*,
4446 sizeof(*newfdp
), M_FILEDESC
, M_WAITOK
);
4453 * the FD_CHROOT flag will be inherited via this copy
4455 (void) memcpy(newfdp
, fdp
, sizeof(*newfdp
));
4458 * If we are running with per-thread current working directories,
4459 * inherit the new current working directory from the current thread
4460 * instead, before we take our references.
4462 if (uth_cdir
!= NULLVP
)
4463 newfdp
->fd_cdir
= uth_cdir
;
4466 * For both fd_cdir and fd_rdir make sure we get
4467 * a valid reference... if we can't, than set
4468 * set the pointer(s) to NULL in the child... this
4469 * will keep us from using a non-referenced vp
4470 * and allows us to do the vnode_rele only on
4471 * a properly referenced vp
4473 if ( (v_dir
= newfdp
->fd_cdir
) ) {
4474 if (vnode_getwithref(v_dir
) == 0) {
4475 if ( (vnode_ref(v_dir
)) )
4476 newfdp
->fd_cdir
= NULL
;
4479 newfdp
->fd_cdir
= NULL
;
4481 if (newfdp
->fd_cdir
== NULL
&& fdp
->fd_cdir
) {
4483 * we couldn't get a new reference on
4484 * the current working directory being
4485 * inherited... we might as well drop
4486 * our reference from the parent also
4487 * since the vnode has gone DEAD making
4488 * it useless... by dropping it we'll
4489 * be that much closer to recycling it
4491 vnode_rele(fdp
->fd_cdir
);
4492 fdp
->fd_cdir
= NULL
;
4495 if ( (v_dir
= newfdp
->fd_rdir
) ) {
4496 if (vnode_getwithref(v_dir
) == 0) {
4497 if ( (vnode_ref(v_dir
)) )
4498 newfdp
->fd_rdir
= NULL
;
4501 newfdp
->fd_rdir
= NULL
;
4504 /* Coming from a chroot environment and unable to get a reference... */
4505 if (newfdp
->fd_rdir
== NULL
&& fdp
->fd_rdir
) {
4507 * We couldn't get a new reference on
4508 * the chroot directory being
4509 * inherited... this is fatal, since
4510 * otherwise it would constitute an
4511 * escape from a chroot environment by
4514 if (newfdp
->fd_cdir
)
4515 vnode_rele(newfdp
->fd_cdir
);
4516 FREE_ZONE(newfdp
, sizeof *newfdp
, M_FILEDESC
);
4521 * If the number of open files fits in the internal arrays
4522 * of the open file structure, use them, otherwise allocate
4523 * additional memory for the number of descriptors currently
4526 if (newfdp
->fd_lastfile
< NDFILE
)
4530 * Compute the smallest multiple of NDEXTENT needed
4531 * for the file descriptors currently in use,
4532 * allowing the table to shrink.
4534 i
= newfdp
->fd_nfiles
;
4535 while (i
> 2 * NDEXTENT
&& i
> newfdp
->fd_lastfile
* 2)
4540 MALLOC_ZONE(newfdp
->fd_ofiles
, struct fileproc
**,
4541 i
* OFILESIZE
, M_OFILETABL
, M_WAITOK
);
4542 if (newfdp
->fd_ofiles
== NULL
) {
4543 if (newfdp
->fd_cdir
)
4544 vnode_rele(newfdp
->fd_cdir
);
4545 if (newfdp
->fd_rdir
)
4546 vnode_rele(newfdp
->fd_rdir
);
4548 FREE_ZONE(newfdp
, sizeof(*newfdp
), M_FILEDESC
);
4551 (void) memset(newfdp
->fd_ofiles
, 0, i
* OFILESIZE
);
4554 newfdp
->fd_ofileflags
= (char *) &newfdp
->fd_ofiles
[i
];
4555 newfdp
->fd_nfiles
= i
;
4557 if (fdp
->fd_nfiles
> 0) {
4558 struct fileproc
**fpp
;
4561 (void) memcpy(newfdp
->fd_ofiles
, fdp
->fd_ofiles
,
4562 (newfdp
->fd_lastfile
+ 1) * sizeof(*fdp
->fd_ofiles
));
4563 (void) memcpy(newfdp
->fd_ofileflags
, fdp
->fd_ofileflags
,
4564 (newfdp
->fd_lastfile
+ 1) * sizeof(*fdp
->fd_ofileflags
));
4567 * kq descriptors cannot be copied.
4569 if (newfdp
->fd_knlistsize
!= -1) {
4570 fpp
= &newfdp
->fd_ofiles
[newfdp
->fd_lastfile
];
4571 flags
= &newfdp
->fd_ofileflags
[newfdp
->fd_lastfile
];
4572 for (i
= newfdp
->fd_lastfile
;
4573 i
>= 0; i
--, fpp
--, flags
--) {
4574 if (*flags
& UF_RESERVED
)
4575 continue; /* (removed below) */
4576 if (*fpp
!= NULL
&& (*fpp
)->f_type
== DTYPE_KQUEUE
) {
4579 if (i
< newfdp
->fd_freefile
)
4580 newfdp
->fd_freefile
= i
;
4582 if (*fpp
== NULL
&& i
== newfdp
->fd_lastfile
&& i
> 0)
4583 newfdp
->fd_lastfile
--;
4585 newfdp
->fd_knlist
= NULL
;
4586 newfdp
->fd_knlistsize
= -1;
4587 newfdp
->fd_knhash
= NULL
;
4588 newfdp
->fd_knhashmask
= 0;
4590 fpp
= newfdp
->fd_ofiles
;
4591 flags
= newfdp
->fd_ofileflags
;
4593 for (i
= newfdp
->fd_lastfile
+ 1; --i
>= 0; fpp
++, flags
++)
4594 if ((ofp
= *fpp
) != NULL
&&
4595 0 == (*flags
& (UF_FORKCLOSE
|UF_RESERVED
))) {
4597 if (FILEPROC_TYPE(ofp
) != FTYPE_SIMPLE
)
4598 panic("complex fileproc");
4600 fp
= fileproc_alloc_init(NULL
);
4603 * XXX no room to copy, unable to
4604 * XXX safely unwind state at present
4609 (ofp
->f_flags
& ~FP_TYPEMASK
);
4610 fp
->f_fglob
= ofp
->f_fglob
;
4615 if (i
< newfdp
->fd_freefile
)
4616 newfdp
->fd_freefile
= i
;
4630 * Description: Release a filedesc (per process open file table) structure;
4631 * this is done on process exit(), or from forkproc_free() if
4632 * the fork fails for some reason subsequent to a successful
4635 * Parameters: p Pointer to process going away
4639 * Locks: This function internally takes and drops proc_fdlock()
4644 struct filedesc
*fdp
;
4645 struct fileproc
*fp
;
4650 if (p
== kernproc
|| NULL
== (fdp
= p
->p_fd
)) {
4655 extern struct filedesc filedesc0
;
4657 if (&filedesc0
== fdp
)
4660 if (fdp
->fd_nfiles
> 0 && fdp
->fd_ofiles
) {
4661 for (i
= fdp
->fd_lastfile
; i
>= 0; i
--) {
4662 if ((fp
= fdp
->fd_ofiles
[i
]) != NULL
) {
4664 if (fdp
->fd_ofileflags
[i
] & UF_RESERVED
)
4665 panic("fdfree: found fp with UF_RESERVED");
4667 procfdtbl_reservefd(p
, i
);
4669 if (i
< fdp
->fd_knlistsize
)
4670 knote_fdclose(p
, i
);
4671 if (fp
->f_flags
& FP_WAITEVENT
)
4672 (void)waitevent_close(p
, fp
);
4673 (void) closef_locked(fp
, fp
->f_fglob
, p
);
4677 FREE_ZONE(fdp
->fd_ofiles
, fdp
->fd_nfiles
* OFILESIZE
, M_OFILETABL
);
4678 fdp
->fd_ofiles
= NULL
;
4685 vnode_rele(fdp
->fd_cdir
);
4687 vnode_rele(fdp
->fd_rdir
);
4689 proc_fdlock_spin(p
);
4694 FREE(fdp
->fd_knlist
, M_KQUEUE
);
4696 FREE(fdp
->fd_knhash
, M_KQUEUE
);
4698 FREE_ZONE(fdp
, sizeof(*fdp
), M_FILEDESC
);
4704 * Description: Internal form of closef; called with proc_fdlock held
4706 * Parameters: fp Pointer to fileproc for fd
4707 * fg Pointer to fileglob for fd
4708 * p Pointer to proc structure
4710 * Returns: 0 Success
4711 * closef_finish:??? Anything returnable by a per-fileops
4714 * Note: Decrements reference count on file structure; if this was the
4715 * last reference, then closef_finish() is called
4717 * p and fp are allowed to be NULL when closing a file that was
4718 * being passed in a message (but only if we are called when this
4719 * is NOT the last reference).
4722 closef_locked(struct fileproc
*fp
, struct fileglob
*fg
, proc_t p
)
4726 struct vfs_context context
;
4733 /* Set up context with cred stashed in fg */
4734 if (p
== current_proc())
4735 context
.vc_thread
= current_thread();
4737 context
.vc_thread
= NULL
;
4738 context
.vc_ucred
= fg
->fg_cred
;
4741 * POSIX record locking dictates that any close releases ALL
4742 * locks owned by this process. This is handled by setting
4743 * a flag in the unlock to free ONLY locks obeying POSIX
4744 * semantics, and not to free BSD-style file locks.
4745 * If the descriptor was in a message, POSIX-style locks
4746 * aren't passed with the descriptor.
4748 if (p
&& (p
->p_ladvflag
& P_LADVLOCK
) &&
4749 DTYPE_VNODE
== FILEGLOB_DTYPE(fg
)) {
4752 lf
.l_whence
= SEEK_SET
;
4755 lf
.l_type
= F_UNLCK
;
4756 vp
= (struct vnode
*)fg
->fg_data
;
4758 if ( (error
= vnode_getwithref(vp
)) == 0 ) {
4759 (void) VNOP_ADVLOCK(vp
, (caddr_t
)p
, F_UNLCK
, &lf
, F_POSIX
, &context
, NULL
);
4760 (void)vnode_put(vp
);
4764 lck_mtx_lock_spin(&fg
->fg_lock
);
4767 if (fg
->fg_count
> 0) {
4768 lck_mtx_unlock(&fg
->fg_lock
);
4772 if (fg
->fg_count
!= 0)
4773 panic("fg %p: being freed with bad fg_count (%d)", fg
, fg
->fg_count
);
4776 if (fp
&& (fp
->f_flags
& FP_WRITTEN
))
4777 fg
->fg_flag
|= FWASWRITTEN
;
4779 fg
->fg_lflags
|= FG_TERM
;
4780 lck_mtx_unlock(&fg
->fg_lock
);
4785 /* Since we ensure that fg->fg_ops is always initialized,
4786 * it is safe to invoke fo_close on the fg */
4787 error
= fo_close(fg
, &context
);
4801 * Description: Drain out pending I/O operations
4803 * Parameters: p Process closing this file
4804 * fp fileproc struct for the open
4805 * instance on the file
4809 * Locks: Assumes the caller holds the proc_fdlock
4811 * Notes: For character devices, this occurs on the last close of the
4812 * device; for all other file descriptors, this occurs on each
4813 * close to prevent fd's from being closed out from under
4814 * operations currently in progress and blocked
4816 * See Also: file_vnode(), file_socket(), file_drop(), and the cautions
4817 * regarding their use and interaction with this function.
4820 fileproc_drain(proc_t p
, struct fileproc
* fp
)
4822 struct vfs_context context
;
4824 context
.vc_thread
= proc_thread(p
); /* XXX */
4825 context
.vc_ucred
= fp
->f_fglob
->fg_cred
;
4827 fp
->f_iocount
-- ; /* (the one the close holds) */
4829 while (fp
->f_iocount
) {
4831 lck_mtx_convert_spin(&p
->p_fdmlock
);
4833 if (fp
->f_fglob
->fg_ops
->fo_drain
) {
4834 (*fp
->f_fglob
->fg_ops
->fo_drain
)(fp
, &context
);
4836 if ((fp
->f_flags
& FP_INSELECT
) == FP_INSELECT
) {
4837 if (wait_queue_wakeup_all((wait_queue_t
)fp
->f_waddr
, NULL
, THREAD_INTERRUPTED
) == KERN_INVALID_ARGUMENT
)
4838 panic("bad wait queue for wait_queue_wakeup_all %p", fp
->f_waddr
);
4840 if ((fp
->f_flags
& FP_SELCONFLICT
) == FP_SELCONFLICT
) {
4841 if (wait_queue_wakeup_all(&select_conflict_queue
, NULL
, THREAD_INTERRUPTED
) == KERN_INVALID_ARGUMENT
)
4842 panic("bad select_conflict_queue");
4844 p
->p_fpdrainwait
= 1;
4846 msleep(&p
->p_fpdrainwait
, &p
->p_fdmlock
, PRIBIO
, "fpdrain", NULL
);
4850 if ((fp
->f_flags
& FP_INSELECT
) != 0)
4851 panic("FP_INSELECT set on drained fp");
4853 if ((fp
->f_flags
& FP_SELCONFLICT
) == FP_SELCONFLICT
)
4854 fp
->f_flags
&= ~FP_SELCONFLICT
;
4861 * Description: Release the fd and free the fileproc associated with the fd
4862 * in the per process open file table of the specified process;
4863 * these values must correspond.
4865 * Parameters: p Process containing fd
4866 * fd fd to be released
4867 * fp fileproc to be freed
4869 * Returns: 0 Success
4871 * Notes: XXX function should be void - no one interprets the returns
4875 fp_free(proc_t p
, int fd
, struct fileproc
* fp
)
4877 proc_fdlock_spin(p
);
4881 fg_free(fp
->f_fglob
);
4890 * Description: Apply an advisory lock on a file descriptor.
4892 * Parameters: p Process making request
4893 * uap->fd fd on which the lock is to be
4895 * uap->how (Un)Lock bits, including type
4896 * retval Pointer to the call return area
4898 * Returns: 0 Success
4899 * fp_getfvp:EBADF Bad file descriptor
4900 * fp_getfvp:ENOTSUP fd does not refer to a vnode
4901 * vnode_getwithref:???
4905 * *retval (modified) Size of dtable
4907 * Notes: Just attempt to get a record lock of the requested type on
4908 * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
4911 flock(proc_t p
, struct flock_args
*uap
, __unused
int32_t *retval
)
4915 struct fileproc
*fp
;
4918 vfs_context_t ctx
= vfs_context_current();
4921 AUDIT_ARG(fd
, uap
->fd
);
4922 if ( (error
= fp_getfvp(p
, fd
, &fp
, &vp
)) ) {
4925 if ( (error
= vnode_getwithref(vp
)) ) {
4928 AUDIT_ARG(vnpath
, vp
, ARG_VNODE1
);
4930 lf
.l_whence
= SEEK_SET
;
4933 if (how
& LOCK_UN
) {
4934 lf
.l_type
= F_UNLCK
;
4935 fp
->f_flag
&= ~FHASLOCK
;
4936 error
= VNOP_ADVLOCK(vp
, (caddr_t
)fp
->f_fglob
, F_UNLCK
, &lf
, F_FLOCK
, ctx
, NULL
);
4940 lf
.l_type
= F_WRLCK
;
4941 else if (how
& LOCK_SH
)
4942 lf
.l_type
= F_RDLCK
;
4948 error
= mac_file_check_lock(proc_ucred(p
), fp
->f_fglob
, F_SETLK
, &lf
);
4952 fp
->f_flag
|= FHASLOCK
;
4953 if (how
& LOCK_NB
) {
4954 error
= VNOP_ADVLOCK(vp
, (caddr_t
)fp
->f_fglob
, F_SETLK
, &lf
, F_FLOCK
, ctx
, NULL
);
4957 error
= VNOP_ADVLOCK(vp
, (caddr_t
)fp
->f_fglob
, F_SETLK
, &lf
, F_FLOCK
|F_WAIT
, ctx
, NULL
);
4959 (void)vnode_put(vp
);
4961 fp_drop(p
, fd
, fp
, 0);
4969 * Description: Obtain a Mach send right for a given file descriptor.
4971 * Parameters: p Process calling fileport
4972 * uap->fd The fd to reference
4973 * uap->portnamep User address at which to place port name.
4975 * Returns: 0 Success.
4976 * EBADF Bad file descriptor.
4977 * EINVAL File descriptor had type that cannot be sent, misc. other errors.
4978 * EFAULT Address at which to store port name is not valid.
4979 * EAGAIN Resource shortage.
4982 * On success, name of send right is stored at user-specified address.
4985 fileport_makeport(proc_t p
, struct fileport_makeport_args
*uap
,
4986 __unused
int *retval
)
4990 user_addr_t user_portaddr
= uap
->portnamep
;
4991 struct fileproc
*fp
= FILEPROC_NULL
;
4992 struct fileglob
*fg
= NULL
;
4993 ipc_port_t fileport
;
4994 mach_port_name_t name
= MACH_PORT_NULL
;
4996 err
= fp_lookup(p
, fd
, &fp
, 0);
5001 if (!filetype_issendable(fp
->f_type
)) {
5006 if (FP_ISGUARDED(fp
, GUARD_FILEPORT
)) {
5008 err
= fp_guard_exception(p
, fd
, fp
, kGUARD_EXC_FILEPORT
);
5013 /* Dropped when port is deallocated */
5017 /* Allocate and initialize a port */
5018 fileport
= fileport_alloc(fg
);
5019 if (fileport
== IPC_PORT_NULL
) {
5025 /* Add an entry. Deallocates port on failure. */
5026 name
= ipc_port_copyout_send(fileport
, get_task_ipcspace(p
->task
));
5027 if (!MACH_PORT_VALID(name
)) {
5032 err
= copyout(&name
, user_portaddr
, sizeof(mach_port_name_t
));
5037 /* Tag the fileglob for debugging purposes */
5038 lck_mtx_lock_spin(&fg
->fg_lock
);
5039 fg
->fg_lflags
|= FG_PORTMADE
;
5040 lck_mtx_unlock(&fg
->fg_lock
);
5042 fp_drop(p
, fd
, fp
, 0);
5047 if (MACH_PORT_VALID(name
)) {
5048 /* Don't care if another thread races us to deallocate the entry */
5049 (void) mach_port_deallocate(get_task_ipcspace(p
->task
), name
);
5052 if (fp
!= FILEPROC_NULL
) {
5053 fp_drop(p
, fd
, fp
, 0);
5060 fileport_releasefg(struct fileglob
*fg
)
5062 (void)closef_locked(NULL
, fg
, PROC_NULL
);
5071 * Description: Obtain the file descriptor for a given Mach send right.
5073 * Parameters: p Process calling fileport
5074 * uap->port Name of send right to file port.
5076 * Returns: 0 Success
5077 * EINVAL Invalid Mach port name, or port is not for a file.
5079 * fdalloc:ENOMEM Unable to allocate fileproc or extend file table.
5082 * *retval (modified) The new descriptor
5085 fileport_makefd(proc_t p
, struct fileport_makefd_args
*uap
, int32_t *retval
)
5087 struct fileglob
*fg
;
5088 struct fileproc
*fp
= FILEPROC_NULL
;
5089 ipc_port_t port
= IPC_PORT_NULL
;
5090 mach_port_name_t send
= uap
->port
;
5095 res
= ipc_object_copyin(get_task_ipcspace(p
->task
),
5096 send
, MACH_MSG_TYPE_COPY_SEND
, &port
);
5098 if (res
!= KERN_SUCCESS
) {
5103 fg
= fileport_port_to_fileglob(port
);
5109 fp
= fileproc_alloc_init(NULL
);
5110 if (fp
== FILEPROC_NULL
) {
5119 err
= fdalloc(p
, 0, &fd
);
5124 *fdflags(p
, fd
) |= UF_EXCLOSE
;
5126 procfdtbl_releasefd(p
, fd
, fp
);
5132 if ((fp
!= NULL
) && (0 != err
)) {
5136 if (IPC_PORT_NULL
!= port
) {
5137 ipc_port_release_send(port
);
5147 * Description: Duplicate the specified descriptor to a free descriptor;
5148 * this is the second half of fdopen(), above.
5150 * Parameters: fdp filedesc pointer to fill in
5152 * dfd fd to dup from
5153 * mode mode to set on new fd
5154 * error command code
5156 * Returns: 0 Success
5157 * EBADF Source fd is bad
5158 * EACCES Requested mode not allowed
5159 * !0 'error', if not ENODEV or
5162 * Notes: XXX This is not thread safe; see fdopen() above
5165 dupfdopen(struct filedesc
*fdp
, int indx
, int dfd
, int flags
, int error
)
5167 struct fileproc
*wfp
;
5168 struct fileproc
*fp
;
5172 proc_t p
= current_proc();
5175 * If the to-be-dup'd fd number is greater than the allowed number
5176 * of file descriptors, or the fd to be dup'd has already been
5177 * closed, reject. Note, check for new == old is necessary as
5178 * falloc could allocate an already closed to-be-dup'd descriptor
5179 * as the new descriptor.
5183 fp
= fdp
->fd_ofiles
[indx
];
5184 if (dfd
< 0 || dfd
>= fdp
->fd_nfiles
||
5185 (wfp
= fdp
->fd_ofiles
[dfd
]) == NULL
|| wfp
== fp
||
5186 (fdp
->fd_ofileflags
[dfd
] & UF_RESERVED
)) {
5192 myerror
= mac_file_check_dup(proc_ucred(p
), wfp
->f_fglob
, dfd
);
5199 * There are two cases of interest here.
5201 * For ENODEV simply dup (dfd) to file descriptor
5202 * (indx) and return.
5204 * For ENXIO steal away the file structure from (dfd) and
5205 * store it in (indx). (dfd) is effectively closed by
5208 * Any other error code is just returned.
5212 if (FP_ISGUARDED(wfp
, GUARD_DUP
)) {
5213 int err
= fp_guard_exception(p
,
5214 dfd
, wfp
, kGUARD_EXC_DUP
);
5220 * Check that the mode the file is being opened for is a
5221 * subset of the mode of the existing descriptor.
5223 if (((flags
& (FREAD
|FWRITE
)) | wfp
->f_flag
) != wfp
->f_flag
) {
5227 if (indx
> fdp
->fd_lastfile
)
5228 fdp
->fd_lastfile
= indx
;
5232 fg_free(fp
->f_fglob
);
5233 fp
->f_fglob
= wfp
->f_fglob
;
5235 fdp
->fd_ofileflags
[indx
] = fdp
->fd_ofileflags
[dfd
] |
5236 (flags
& O_CLOEXEC
) ? UF_EXCLOSE
: 0;
5252 * Description: Add a reference to a fileglob by fileproc
5254 * Parameters: fp fileproc containing fileglob
5259 * Notes: XXX Should use OSAddAtomic?
5262 fg_ref(struct fileproc
* fp
)
5264 struct fileglob
*fg
;
5268 lck_mtx_lock_spin(&fg
->fg_lock
);
5271 if ((fp
->f_flags
& ~((unsigned int)FP_VALID_FLAGS
)) != 0)
5272 panic("fg_ref: invalid bits on fp %p", fp
);
5274 if (fg
->fg_count
== 0)
5275 panic("fg_ref: adding fgcount to zeroed fg: fp %p fg %p",
5279 lck_mtx_unlock(&fg
->fg_lock
);
5286 * Description: Remove a reference to a fileglob by fileproc
5288 * Parameters: fp fileproc containing fileglob
5293 * Notes: XXX Should use OSAddAtomic?
5296 fg_drop(struct fileproc
* fp
)
5298 struct fileglob
*fg
;
5301 lck_mtx_lock_spin(&fg
->fg_lock
);
5303 lck_mtx_unlock(&fg
->fg_lock
);
5310 * Description: Insert fileglob onto message queue
5312 * Parameters: fg Fileglob pointer to insert
5316 * Locks: Takes and drops fg_lock, potentially many times
5319 fg_insertuipc(struct fileglob
* fg
)
5323 lck_mtx_lock_spin(&fg
->fg_lock
);
5325 while (fg
->fg_lflags
& FG_RMMSGQ
) {
5326 lck_mtx_convert_spin(&fg
->fg_lock
);
5328 fg
->fg_lflags
|= FG_WRMMSGQ
;
5329 msleep(&fg
->fg_lflags
, &fg
->fg_lock
, 0, "fg_insertuipc", NULL
);
5334 if (fg
->fg_msgcount
== 1) {
5335 fg
->fg_lflags
|= FG_INSMSGQ
;
5338 lck_mtx_unlock(&fg
->fg_lock
);
5341 lck_mtx_lock_spin(uipc_lock
);
5343 LIST_INSERT_HEAD(&fmsghead
, fg
, f_msglist
);
5344 lck_mtx_unlock(uipc_lock
);
5345 lck_mtx_lock(&fg
->fg_lock
);
5346 fg
->fg_lflags
&= ~FG_INSMSGQ
;
5347 if (fg
->fg_lflags
& FG_WINSMSGQ
) {
5348 fg
->fg_lflags
&= ~FG_WINSMSGQ
;
5349 wakeup(&fg
->fg_lflags
);
5351 lck_mtx_unlock(&fg
->fg_lock
);
5360 * Description: Remove fileglob from message queue
5362 * Parameters: fg Fileglob pointer to remove
5366 * Locks: Takes and drops fg_lock, potentially many times
5369 fg_removeuipc(struct fileglob
* fg
)
5373 lck_mtx_lock_spin(&fg
->fg_lock
);
5374 while (fg
->fg_lflags
& FG_INSMSGQ
) {
5375 lck_mtx_convert_spin(&fg
->fg_lock
);
5377 fg
->fg_lflags
|= FG_WINSMSGQ
;
5378 msleep(&fg
->fg_lflags
, &fg
->fg_lock
, 0, "fg_removeuipc", NULL
);
5381 if (fg
->fg_msgcount
== 0) {
5382 fg
->fg_lflags
|= FG_RMMSGQ
;
5385 lck_mtx_unlock(&fg
->fg_lock
);
5388 lck_mtx_lock_spin(uipc_lock
);
5390 LIST_REMOVE(fg
, f_msglist
);
5391 lck_mtx_unlock(uipc_lock
);
5392 lck_mtx_lock(&fg
->fg_lock
);
5393 fg
->fg_lflags
&= ~FG_RMMSGQ
;
5394 if (fg
->fg_lflags
& FG_WRMMSGQ
) {
5395 fg
->fg_lflags
&= ~FG_WRMMSGQ
;
5396 wakeup(&fg
->fg_lflags
);
5398 lck_mtx_unlock(&fg
->fg_lock
);
5401 #endif /* SOCKETS */
5406 * Description: Generic fileops read indirected through the fileops pointer
5407 * in the fileproc structure
5409 * Parameters: fp fileproc structure pointer
5410 * uio user I/O structure pointer
5412 * ctx VFS context for operation
5414 * Returns: 0 Success
5415 * !0 Errno from read
5418 fo_read(struct fileproc
*fp
, struct uio
*uio
, int flags
, vfs_context_t ctx
)
5420 return ((*fp
->f_ops
->fo_read
)(fp
, uio
, flags
, ctx
));
5427 * Description: Generic fileops write indirected through the fileops pointer
5428 * in the fileproc structure
5430 * Parameters: fp fileproc structure pointer
5431 * uio user I/O structure pointer
5433 * ctx VFS context for operation
5435 * Returns: 0 Success
5436 * !0 Errno from write
5439 fo_write(struct fileproc
*fp
, struct uio
*uio
, int flags
, vfs_context_t ctx
)
5441 return((*fp
->f_ops
->fo_write
)(fp
, uio
, flags
, ctx
));
5448 * Description: Generic fileops ioctl indirected through the fileops pointer
5449 * in the fileproc structure
5451 * Parameters: fp fileproc structure pointer
5453 * data pointer to internalized copy
5454 * of user space ioctl command
5455 * parameter data in kernel space
5456 * ctx VFS context for operation
5458 * Returns: 0 Success
5459 * !0 Errno from ioctl
5461 * Locks: The caller is assumed to have held the proc_fdlock; this
5462 * function releases and reacquires this lock. If the caller
5463 * accesses data protected by this lock prior to calling this
5464 * function, it will need to revalidate/reacquire any cached
5465 * protected data obtained prior to the call.
5468 fo_ioctl(struct fileproc
*fp
, u_long com
, caddr_t data
, vfs_context_t ctx
)
5472 proc_fdunlock(vfs_context_proc(ctx
));
5473 error
= (*fp
->f_ops
->fo_ioctl
)(fp
, com
, data
, ctx
);
5474 proc_fdlock(vfs_context_proc(ctx
));
5482 * Description: Generic fileops select indirected through the fileops pointer
5483 * in the fileproc structure
5485 * Parameters: fp fileproc structure pointer
5486 * which select which
5487 * wql pointer to wait queue list
5488 * ctx VFS context for operation
5490 * Returns: 0 Success
5491 * !0 Errno from select
5494 fo_select(struct fileproc
*fp
, int which
, void *wql
, vfs_context_t ctx
)
5496 return((*fp
->f_ops
->fo_select
)(fp
, which
, wql
, ctx
));
5503 * Description: Generic fileops close indirected through the fileops pointer
5504 * in the fileproc structure
5506 * Parameters: fp fileproc structure pointer for
5508 * ctx VFS context for operation
5510 * Returns: 0 Success
5511 * !0 Errno from close
5514 fo_close(struct fileglob
*fg
, vfs_context_t ctx
)
5516 return((*fg
->fg_ops
->fo_close
)(fg
, ctx
));
5523 * Description: Generic fileops kqueue filter indirected through the fileops
5524 * pointer in the fileproc structure
5526 * Parameters: fp fileproc structure pointer
5527 * kn pointer to knote to filter on
5528 * ctx VFS context for operation
5530 * Returns: 0 Success
5531 * !0 Errno from kqueue filter
5534 fo_kqfilter(struct fileproc
*fp
, struct knote
*kn
, vfs_context_t ctx
)
5536 return ((*fp
->f_ops
->fo_kqfilter
)(fp
, kn
, ctx
));
5540 * The ability to send a file descriptor to another
5541 * process is opt-in by file type.
5544 filetype_issendable(file_type_t fdtype
)
5553 /* DTYPE_KQUEUE, DTYPE_FSEVENTS, DTYPE_PSXSEM */
5560 fileproc_alloc_init(__unused
void *arg
)
5562 struct fileproc
*fp
;
5564 MALLOC_ZONE(fp
, struct fileproc
*, sizeof (*fp
), M_FILEPROC
, M_WAITOK
);
5566 bzero(fp
, sizeof (*fp
));
5572 fileproc_free(struct fileproc
*fp
)
5574 switch (FILEPROC_TYPE(fp
)) {
5576 FREE_ZONE(fp
, sizeof (*fp
), M_FILEPROC
);
5579 guarded_fileproc_free(fp
);
5582 panic("%s: corrupt fp %p flags %x", __func__
, fp
, fp
->f_flags
);