]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/kern_descrip.c
xnu-4570.41.2.tar.gz
[apple/xnu.git] / bsd / kern / kern_descrip.c
CommitLineData
1c79356b 1/*
39037602 2 * Copyright (c) 2000-2016 Apple Inc. All rights reserved.
5d5c5d0d 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
39037602 5 *
2d21ac55
A
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.
39037602 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
39037602 17 *
2d21ac55
A
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
39037602 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/* Copyright (c) 1995, 1997 Apple Computer, Inc. All Rights Reserved */
29/*
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.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
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.
53 *
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
64 * SUCH DAMAGE.
65 *
66 * @(#)kern_descrip.c 8.8 (Berkeley) 2/14/95
1c79356b 67 */
2d21ac55
A
68/*
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,
72 * Version 2.0.
73 */
1c79356b
A
74
75#include <sys/param.h>
76#include <sys/systm.h>
77#include <sys/filedesc.h>
78#include <sys/kernel.h>
91447636
A
79#include <sys/vnode_internal.h>
80#include <sys/proc_internal.h>
81#include <sys/kauth.h>
82#include <sys/file_internal.h>
39236c6e 83#include <sys/guarded.h>
c7d2c2c6 84#include <sys/priv.h>
1c79356b
A
85#include <sys/socket.h>
86#include <sys/socketvar.h>
87#include <sys/stat.h>
88#include <sys/ioctl.h>
89#include <sys/fcntl.h>
90#include <sys/malloc.h>
91447636 91#include <sys/mman.h>
1c79356b
A
92#include <sys/syslog.h>
93#include <sys/unistd.h>
94#include <sys/resourcevar.h>
55e303ae 95#include <sys/aio_kern.h>
91447636 96#include <sys/ev.h>
fe8ab488 97#include <kern/locks.h>
b0d623f7 98#include <sys/uio_internal.h>
39236c6e 99#include <sys/codesign.h>
fe8ab488 100#include <sys/codedir_internal.h>
e5568f75 101
b0d623f7 102#include <security/audit/audit.h>
1c79356b 103
91447636
A
104#include <sys/mount_internal.h>
105#include <sys/kdebug.h>
106#include <sys/sysproto.h>
107#include <sys/pipe.h>
6d2010ae 108#include <sys/spawn.h>
39037602 109#include <sys/cprotect.h>
91447636
A
110#include <kern/kern_types.h>
111#include <kern/kalloc.h>
3e170ce0 112#include <kern/waitq.h>
b36670ce 113#include <libkern/OSAtomic.h>
91447636 114
593a1d5f 115#include <sys/ubc_internal.h>
2d21ac55 116
d1ecb069
A
117#include <kern/ipc_misc.h>
118#include <vm/vm_protos.h>
119
120#include <mach/mach_port.h>
fe8ab488 121#include <stdbool.h>
d1ecb069 122
5ba3f43e
A
123#if CONFIG_MACF
124#include <security/mac_framework.h>
125#endif
126
d1ecb069
A
127kern_return_t ipc_object_copyin(ipc_space_t, mach_port_name_t,
128 mach_msg_type_name_t, ipc_port_t *);
129void ipc_port_release_send(ipc_port_t);
130
91447636
A
131struct psemnode;
132struct pshmnode;
133
6d2010ae
A
134static int finishdup(proc_t p,
135 struct filedesc *fdp, int old, int new, int flags, int32_t *retval);
91447636 136
2d21ac55 137int falloc_locked(proc_t p, struct fileproc **resultfp, int *resultfd, vfs_context_t ctx, int locked);
91447636
A
138void fg_drop(struct fileproc * fp);
139void fg_free(struct fileglob *fg);
140void fg_ref(struct fileproc * fp);
d1ecb069 141void fileport_releasefg(struct fileglob *fg);
91447636 142
2d21ac55
A
143/* flags for close_internal_locked */
144#define FD_DUP2RESV 1
2d21ac55
A
145
146/* We don't want these exported */
2d21ac55
A
147
148__private_extern__
c18c124e 149int unlink1(vfs_context_t, vnode_t, user_addr_t, enum uio_seg, int);
2d21ac55
A
150
151static void _fdrelse(struct proc * p, int fd);
91447636 152
2d21ac55 153
39236c6e 154extern void file_lock_init(void);
91447636
A
155
156extern kauth_scope_t kauth_scope_fileop;
157
6d2010ae 158/* Conflict wait queue for when selects collide (opaque type) */
3e170ce0 159extern struct waitq select_conflict_queue;
6d2010ae 160
91447636 161#define f_flag f_fglob->fg_flag
39236c6e 162#define f_type f_fglob->fg_ops->fo_type
91447636
A
163#define f_msgcount f_fglob->fg_msgcount
164#define f_cred f_fglob->fg_cred
165#define f_ops f_fglob->fg_ops
166#define f_offset f_fglob->fg_offset
167#define f_data f_fglob->fg_data
39236c6e
A
168#define CHECK_ADD_OVERFLOW_INT64L(x, y) \
169 (((((x) > 0) && ((y) > 0) && ((x) > LLONG_MAX - (y))) || \
170 (((x) < 0) && ((y) < 0) && ((x) < LLONG_MIN - (y)))) \
171 ? 1 : 0)
1c79356b
A
172/*
173 * Descriptor management.
174 */
91447636
A
175struct fmsglist fmsghead; /* head of list of open files */
176struct fmsglist fmsg_ithead; /* head of list of open files */
1c79356b
A
177int nfiles; /* actual number of open files */
178
91447636
A
179
180lck_grp_attr_t * file_lck_grp_attr;
181lck_grp_t * file_lck_grp;
182lck_attr_t * file_lck_attr;
183
184lck_mtx_t * uipc_lock;
91447636
A
185
186
39236c6e
A
187/*
188 * check_file_seek_range
189 *
190 * Description: Checks if seek offsets are in the range of 0 to LLONG_MAX.
191 *
192 * Parameters: fl Flock structure.
193 * cur_file_offset Current offset in the file.
194 *
195 * Returns: 0 on Success.
196 * EOVERFLOW on overflow.
197 * EINVAL on offset less than zero.
198 */
199
200static int
201check_file_seek_range(struct flock *fl, off_t cur_file_offset)
202{
203 if (fl->l_whence == SEEK_CUR) {
204 /* Check if the start marker is beyond LLONG_MAX. */
205 if (CHECK_ADD_OVERFLOW_INT64L(fl->l_start, cur_file_offset)) {
206 /* Check if start marker is negative */
207 if (fl->l_start < 0) {
208 return EINVAL;
209 }
210 return EOVERFLOW;
211 }
212 /* Check if the start marker is negative. */
213 if (fl->l_start + cur_file_offset < 0) {
214 return EINVAL;
215 }
216 /* Check if end marker is beyond LLONG_MAX. */
39037602 217 if ((fl->l_len > 0) && (CHECK_ADD_OVERFLOW_INT64L(fl->l_start +
39236c6e
A
218 cur_file_offset, fl->l_len - 1))) {
219 return EOVERFLOW;
220 }
221 /* Check if the end marker is negative. */
222 if ((fl->l_len <= 0) && (fl->l_start + cur_file_offset +
223 fl->l_len < 0)) {
224 return EINVAL;
225 }
226 } else if (fl->l_whence == SEEK_SET) {
227 /* Check if the start marker is negative. */
228 if (fl->l_start < 0) {
229 return EINVAL;
230 }
231 /* Check if the end marker is beyond LLONG_MAX. */
39037602 232 if ((fl->l_len > 0) &&
39236c6e
A
233 CHECK_ADD_OVERFLOW_INT64L(fl->l_start, fl->l_len - 1)) {
234 return EOVERFLOW;
235 }
236 /* Check if the end marker is negative. */
237 if ((fl->l_len < 0) && fl->l_start + fl->l_len < 0) {
238 return EINVAL;
239 }
240 }
241 return 0;
242}
243
244
2d21ac55
A
245/*
246 * file_lock_init
247 *
248 * Description: Initialize the file lock group and the uipc and flist locks
249 *
250 * Parameters: (void)
251 *
252 * Returns: void
253 *
254 * Notes: Called at system startup from bsd_init().
255 */
91447636
A
256void
257file_lock_init(void)
258{
91447636
A
259 /* allocate file lock group attribute and group */
260 file_lck_grp_attr= lck_grp_attr_alloc_init();
91447636
A
261
262 file_lck_grp = lck_grp_alloc_init("file", file_lck_grp_attr);
263
264 /* Allocate file lock attribute */
265 file_lck_attr = lck_attr_alloc_init();
91447636
A
266
267 uipc_lock = lck_mtx_alloc_init(file_lck_grp, file_lck_attr);
2d21ac55 268}
91447636 269
91447636 270
2d21ac55
A
271/*
272 * proc_fdlock, proc_fdlock_spin
273 *
274 * Description: Lock to control access to the per process struct fileproc
275 * and struct filedesc
276 *
277 * Parameters: p Process to take the lock on
278 *
279 * Returns: void
280 *
281 * Notes: The lock is initialized in forkproc() and destroyed in
282 * reap_child_process().
283 */
284void
285proc_fdlock(proc_t p)
286{
287 lck_mtx_lock(&p->p_fdmlock);
91447636
A
288}
289
2d21ac55
A
290void
291proc_fdlock_spin(proc_t p)
292{
293 lck_mtx_lock_spin(&p->p_fdmlock);
294}
91447636
A
295
296void
2d21ac55 297proc_fdlock_assert(proc_t p, int assertflags)
91447636 298{
2d21ac55 299 lck_mtx_assert(&p->p_fdmlock, assertflags);
91447636
A
300}
301
2d21ac55
A
302
303/*
304 * proc_fdunlock
305 *
306 * Description: Unlock the lock previously locked by a call to proc_fdlock()
307 *
308 * Parameters: p Process to drop the lock on
309 *
310 * Returns: void
311 */
91447636 312void
2d21ac55 313proc_fdunlock(proc_t p)
91447636
A
314{
315 lck_mtx_unlock(&p->p_fdmlock);
316}
9bccf70c 317
2d21ac55 318
1c79356b
A
319/*
320 * System calls on descriptors.
321 */
91447636 322
2d21ac55
A
323
324/*
325 * getdtablesize
326 *
327 * Description: Returns the per process maximum size of the descriptor table
328 *
329 * Parameters: p Process being queried
330 * retval Pointer to the call return area
331 *
332 * Returns: 0 Success
333 *
334 * Implicit returns:
335 * *retval (modified) Size of dtable
336 */
1c79356b 337int
b0d623f7 338getdtablesize(proc_t p, __unused struct getdtablesize_args *uap, int32_t *retval)
1c79356b 339{
2d21ac55 340 proc_fdlock_spin(p);
1c79356b 341 *retval = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
91447636
A
342 proc_fdunlock(p);
343
1c79356b
A
344 return (0);
345}
346
1c79356b 347
6601e61a
A
348void
349procfdtbl_reservefd(struct proc * p, int fd)
350{
351 p->p_fd->fd_ofiles[fd] = NULL;
352 p->p_fd->fd_ofileflags[fd] |= UF_RESERVED;
353}
354
355void
356procfdtbl_markclosefd(struct proc * p, int fd)
357{
358 p->p_fd->fd_ofileflags[fd] |= (UF_RESERVED | UF_CLOSING);
359}
360
361void
362procfdtbl_releasefd(struct proc * p, int fd, struct fileproc * fp)
363{
364 if (fp != NULL)
365 p->p_fd->fd_ofiles[fd] = fp;
366 p->p_fd->fd_ofileflags[fd] &= ~UF_RESERVED;
367 if ((p->p_fd->fd_ofileflags[fd] & UF_RESVWAIT) == UF_RESVWAIT) {
368 p->p_fd->fd_ofileflags[fd] &= ~UF_RESVWAIT;
369 wakeup(&p->p_fd);
370 }
371}
372
39037602 373void
6601e61a
A
374procfdtbl_waitfd(struct proc * p, int fd)
375{
376 p->p_fd->fd_ofileflags[fd] |= UF_RESVWAIT;
377 msleep(&p->p_fd, &p->p_fdmlock, PRIBIO, "ftbl_waitfd", NULL);
378}
379
380
381void
382procfdtbl_clearfd(struct proc * p, int fd)
383{
384 int waiting;
385
386 waiting = (p->p_fd->fd_ofileflags[fd] & UF_RESVWAIT);
39037602 387 p->p_fd->fd_ofiles[fd] = NULL;
6601e61a
A
388 p->p_fd->fd_ofileflags[fd] = 0;
389 if ( waiting == UF_RESVWAIT) {
390 wakeup(&p->p_fd);
391 }
392}
393
2d21ac55
A
394/*
395 * _fdrelse
396 *
397 * Description: Inline utility function to free an fd in a filedesc
398 *
399 * Parameters: fdp Pointer to filedesc fd lies in
400 * fd fd to free
401 * reserv fd should be reserved
402 *
403 * Returns: void
404 *
405 * Locks: Assumes proc_fdlock for process pointing to fdp is held by
406 * the caller
407 */
408static void
409_fdrelse(struct proc * p, int fd)
1c79356b 410{
2d21ac55
A
411 struct filedesc *fdp = p->p_fd;
412 int nfd = 0;
6601e61a 413
1c79356b
A
414 if (fd < fdp->fd_freefile)
415 fdp->fd_freefile = fd;
416#if DIAGNOSTIC
417 if (fd > fdp->fd_lastfile)
2d21ac55 418 panic("fdrelse: fd_lastfile inconsistent");
1c79356b 419#endif
6601e61a 420 procfdtbl_clearfd(p, fd);
91447636 421
6601e61a
A
422 while ((nfd = fdp->fd_lastfile) > 0 &&
423 fdp->fd_ofiles[nfd] == NULL &&
424 !(fdp->fd_ofileflags[nfd] & UF_RESERVED))
5ba3f43e 425 /* JMM - What about files with lingering EV_VANISHED knotes? */
1c79356b
A
426 fdp->fd_lastfile--;
427}
428
2d21ac55 429
b0d623f7
A
430int
431fd_rdwr(
432 int fd,
433 enum uio_rw rw,
434 uint64_t base,
435 int64_t len,
436 enum uio_seg segflg,
437 off_t offset,
438 int io_flg,
439 int64_t *aresid)
440{
441 struct fileproc *fp;
442 proc_t p;
443 int error = 0;
444 int flags = 0;
445 int spacetype;
446 uio_t auio = NULL;
447 char uio_buf[ UIO_SIZEOF(1) ];
448 struct vfs_context context = *(vfs_context_current());
fe8ab488 449 bool wrote_some = false;
b0d623f7
A
450
451 p = current_proc();
452
453 error = fp_lookup(p, fd, &fp, 0);
454 if (error)
455 return(error);
456
457 if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_PIPE && fp->f_type != DTYPE_SOCKET) {
458 error = EINVAL;
459 goto out;
460 }
461 if (rw == UIO_WRITE && !(fp->f_flag & FWRITE)) {
462 error = EBADF;
463 goto out;
464 }
39037602 465
b0d623f7
A
466 if (rw == UIO_READ && !(fp->f_flag & FREAD)) {
467 error = EBADF;
468 goto out;
469 }
39037602 470
b0d623f7
A
471 context.vc_ucred = fp->f_fglob->fg_cred;
472
473 if (UIO_SEG_IS_USER_SPACE(segflg))
474 spacetype = proc_is64bit(p) ? UIO_USERSPACE64 : UIO_USERSPACE32;
475 else
476 spacetype = UIO_SYSSPACE;
477
478 auio = uio_createwithbuffer(1, offset, spacetype, rw, &uio_buf[0], sizeof(uio_buf));
479
480 uio_addiov(auio, base, len);
481
482 if ( !(io_flg & IO_APPEND))
483 flags = FOF_OFFSET;
484
fe8ab488
A
485 if (rw == UIO_WRITE) {
486 user_ssize_t orig_resid = uio_resid(auio);
b0d623f7 487 error = fo_write(fp, auio, flags, &context);
fe8ab488
A
488 wrote_some = uio_resid(auio) < orig_resid;
489 } else
b0d623f7
A
490 error = fo_read(fp, auio, flags, &context);
491
492 if (aresid)
493 *aresid = uio_resid(auio);
494 else {
495 if (uio_resid(auio) && error == 0)
496 error = EIO;
497 }
498out:
fe8ab488 499 if (wrote_some)
b0d623f7
A
500 fp_drop_written(p, fd, fp);
501 else
502 fp_drop(p, fd, fp, 0);
503
504 return error;
505}
506
507
508
1c79356b 509/*
2d21ac55
A
510 * dup
511 *
512 * Description: Duplicate a file descriptor.
513 *
514 * Parameters: p Process performing the dup
515 * uap->fd The fd to dup
516 * retval Pointer to the call return area
517 *
518 * Returns: 0 Success
519 * !0 Errno
520 *
521 * Implicit returns:
522 * *retval (modified) The new descriptor
1c79356b 523 */
1c79356b 524int
b0d623f7 525dup(proc_t p, struct dup_args *uap, int32_t *retval)
1c79356b 526{
2d21ac55
A
527 struct filedesc *fdp = p->p_fd;
528 int old = uap->fd;
1c79356b 529 int new, error;
91447636 530 struct fileproc *fp;
1c79356b 531
91447636
A
532 proc_fdlock(p);
533 if ( (error = fp_lookup(p, old, &fp, 1)) ) {
534 proc_fdunlock(p);
535 return(error);
536 }
39236c6e
A
537 if (FP_ISGUARDED(fp, GUARD_DUP)) {
538 error = fp_guard_exception(p, old, fp, kGUARD_EXC_DUP);
539 (void) fp_drop(p, old, fp, 1);
540 proc_fdunlock(p);
541 return (error);
542 }
91447636
A
543 if ( (error = fdalloc(p, 0, &new)) ) {
544 fp_drop(p, old, fp, 1);
545 proc_fdunlock(p);
1c79356b 546 return (error);
91447636 547 }
6d2010ae 548 error = finishdup(p, fdp, old, new, 0, retval);
91447636
A
549 fp_drop(p, old, fp, 1);
550 proc_fdunlock(p);
551
3e170ce0
A
552 if (ENTR_SHOULDTRACE && fp->f_type == DTYPE_SOCKET) {
553 KERNEL_ENERGYTRACE(kEnTrActKernSocket, DBG_FUNC_START,
554 new, 0, (int64_t)VM_KERNEL_ADDRPERM(fp->f_data));
555 }
556
91447636 557 return (error);
1c79356b
A
558}
559
560/*
2d21ac55
A
561 * dup2
562 *
563 * Description: Duplicate a file descriptor to a particular value.
564 *
565 * Parameters: p Process performing the dup
6d2010ae 566 * uap->from The fd to dup
2d21ac55
A
567 * uap->to The fd to dup it to
568 * retval Pointer to the call return area
569 *
570 * Returns: 0 Success
571 * !0 Errno
572 *
573 * Implicit returns:
574 * *retval (modified) The new descriptor
1c79356b 575 */
1c79356b 576int
b0d623f7 577dup2(proc_t p, struct dup2_args *uap, int32_t *retval)
1c79356b 578{
2d21ac55
A
579 struct filedesc *fdp = p->p_fd;
580 int old = uap->from, new = uap->to;
1c79356b 581 int i, error;
6601e61a 582 struct fileproc *fp, *nfp;
1c79356b 583
91447636
A
584 proc_fdlock(p);
585
6601e61a 586startover:
91447636
A
587 if ( (error = fp_lookup(p, old, &fp, 1)) ) {
588 proc_fdunlock(p);
589 return(error);
590 }
39236c6e
A
591 if (FP_ISGUARDED(fp, GUARD_DUP)) {
592 error = fp_guard_exception(p, old, fp, kGUARD_EXC_DUP);
593 (void) fp_drop(p, old, fp, 1);
594 proc_fdunlock(p);
595 return (error);
596 }
91447636 597 if (new < 0 ||
2d21ac55 598 (rlim_t)new >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
91447636
A
599 new >= maxfiles) {
600 fp_drop(p, old, fp, 1);
601 proc_fdunlock(p);
1c79356b 602 return (EBADF);
91447636 603 }
1c79356b 604 if (old == new) {
91447636 605 fp_drop(p, old, fp, 1);
1c79356b 606 *retval = new;
91447636 607 proc_fdunlock(p);
1c79356b
A
608 return (0);
609 }
91447636
A
610 if (new < 0 || new >= fdp->fd_nfiles) {
611 if ( (error = fdalloc(p, new, &i)) ) {
612 fp_drop(p, old, fp, 1);
613 proc_fdunlock(p);
1c79356b 614 return (error);
91447636 615 }
1c79356b 616 if (new != i) {
2d21ac55 617 fdrelse(p, i);
1c79356b
A
618 goto closeit;
619 }
fa4905b1 620 } else {
1c79356b 621closeit:
6601e61a
A
622 while ((fdp->fd_ofileflags[new] & UF_RESERVED) == UF_RESERVED) {
623 fp_drop(p, old, fp, 1);
624 procfdtbl_waitfd(p, new);
2d21ac55
A
625#if DIAGNOSTIC
626 proc_fdlock_assert(p, LCK_MTX_ASSERT_OWNED);
627#endif
6601e61a 628 goto startover;
91447636
A
629 }
630
6d2010ae
A
631 if ((fdp->fd_ofiles[new] != NULL) &&
632 ((error = fp_lookup(p, new, &nfp, 1)) == 0)) {
6601e61a 633 fp_drop(p, old, fp, 1);
39236c6e
A
634 if (FP_ISGUARDED(nfp, GUARD_CLOSE)) {
635 error = fp_guard_exception(p,
636 new, nfp, kGUARD_EXC_CLOSE);
637 (void) fp_drop(p, new, nfp, 1);
638 proc_fdunlock(p);
639 return (error);
640 }
2d21ac55
A
641 (void)close_internal_locked(p, new, nfp, FD_DUP2RESV);
642#if DIAGNOSTIC
643 proc_fdlock_assert(p, LCK_MTX_ASSERT_OWNED);
644#endif
6601e61a
A
645 procfdtbl_clearfd(p, new);
646 goto startover;
647 } else {
2d21ac55
A
648#if DIAGNOSTIC
649 if (fdp->fd_ofiles[new] != NULL)
6d2010ae 650 panic("dup2: no ref on fileproc %d", new);
2d21ac55 651#endif
6601e61a 652 procfdtbl_reservefd(p, new);
1c79356b 653 }
2d21ac55
A
654
655#if DIAGNOSTIC
656 proc_fdlock_assert(p, LCK_MTX_ASSERT_OWNED);
657#endif
658
1c79356b 659 }
2d21ac55
A
660#if DIAGNOSTIC
661 if (fdp->fd_ofiles[new] != 0)
6d2010ae 662 panic("dup2: overwriting fd_ofiles with new %d", new);
2d21ac55 663 if ((fdp->fd_ofileflags[new] & UF_RESERVED) == 0)
6d2010ae 664 panic("dup2: unreserved fileflags with new %d", new);
2d21ac55 665#endif
6d2010ae 666 error = finishdup(p, fdp, old, new, 0, retval);
91447636
A
667 fp_drop(p, old, fp, 1);
668 proc_fdunlock(p);
669
670 return(error);
1c79356b
A
671}
672
2d21ac55
A
673
674/*
675 * fcntl
676 *
677 * Description: The file control system call.
678 *
679 * Parameters: p Process performing the fcntl
680 * uap->fd The fd to operate against
681 * uap->cmd The command to perform
682 * uap->arg Pointer to the command argument
683 * retval Pointer to the call return area
684 *
685 * Returns: 0 Success
686 * !0 Errno (see fcntl_nocancel)
687 *
688 * Implicit returns:
689 * *retval (modified) fcntl return value (if any)
690 *
691 * Notes: This system call differs from fcntl_nocancel() in that it
692 * tests for cancellation prior to performing a potentially
693 * blocking operation.
694 */
695int
b0d623f7 696fcntl(proc_t p, struct fcntl_args *uap, int32_t *retval)
2d21ac55
A
697{
698 __pthread_testcancel(1);
699 return(fcntl_nocancel(p, (struct fcntl_nocancel_args *)uap, retval));
700}
701
702
1c79356b 703/*
2d21ac55
A
704 * fcntl_nocancel
705 *
706 * Description: A non-cancel-testing file control system call.
707 *
708 * Parameters: p Process performing the fcntl
709 * uap->fd The fd to operate against
710 * uap->cmd The command to perform
711 * uap->arg Pointer to the command argument
712 * retval Pointer to the call return area
713 *
714 * Returns: 0 Success
715 * EINVAL
716 * fp_lookup:EBADF Bad file descriptor
717 * [F_DUPFD]
718 * fdalloc:EMFILE
719 * fdalloc:ENOMEM
720 * finishdup:EBADF
721 * finishdup:ENOMEM
722 * [F_SETOWN]
723 * ESRCH
724 * [F_SETLK]
725 * EBADF
726 * EOVERFLOW
727 * copyin:EFAULT
728 * vnode_getwithref:???
729 * VNOP_ADVLOCK:???
39236c6e 730 * msleep:ETIMEDOUT
2d21ac55
A
731 * [F_GETLK]
732 * EBADF
733 * EOVERFLOW
734 * copyin:EFAULT
735 * copyout:EFAULT
736 * vnode_getwithref:???
737 * VNOP_ADVLOCK:???
738 * [F_PREALLOCATE]
739 * EBADF
740 * EINVAL
741 * copyin:EFAULT
742 * copyout:EFAULT
743 * vnode_getwithref:???
744 * VNOP_ALLOCATE:???
745 * [F_SETSIZE,F_RDADVISE]
746 * EBADF
747 * copyin:EFAULT
748 * vnode_getwithref:???
749 * [F_RDAHEAD,F_NOCACHE]
750 * EBADF
751 * vnode_getwithref:???
752 * [???]
753 *
754 * Implicit returns:
755 * *retval (modified) fcntl return value (if any)
1c79356b 756 */
1c79356b 757int
b0d623f7 758fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, int32_t *retval)
1c79356b
A
759{
760 int fd = uap->fd;
91447636
A
761 struct filedesc *fdp = p->p_fd;
762 struct fileproc *fp;
763 char *pop;
2d21ac55 764 struct vnode *vp = NULLVP; /* for AUDIT_ARG() at end */
3e170ce0 765 int i, tmp, error, error2, flg = 0;
1c79356b 766 struct flock fl;
39236c6e
A
767 struct flocktimeout fltimeout;
768 struct timespec *timeout = NULL;
91447636
A
769 struct vfs_context context;
770 off_t offset;
1c79356b 771 int newmin;
91447636 772 daddr64_t lbn, bn;
91447636
A
773 unsigned int fflag;
774 user_addr_t argp;
e2fac8b1 775 boolean_t is64bit;
1c79356b 776
55e303ae
A
777 AUDIT_ARG(fd, uap->fd);
778 AUDIT_ARG(cmd, uap->cmd);
91447636
A
779
780 proc_fdlock(p);
781 if ( (error = fp_lookup(p, fd, &fp, 1)) ) {
782 proc_fdunlock(p);
783 return(error);
784 }
2d21ac55 785 context.vc_thread = current_thread();
91447636 786 context.vc_ucred = fp->f_cred;
e2fac8b1
A
787
788 is64bit = proc_is64bit(p);
789 if (is64bit) {
91447636
A
790 argp = uap->arg;
791 }
792 else {
2d21ac55
A
793 /*
794 * Since the arg parameter is defined as a long but may be
795 * either a long or a pointer we must take care to handle
796 * sign extension issues. Our sys call munger will sign
797 * extend a long when we are called from a 32-bit process.
798 * Since we can never have an address greater than 32-bits
799 * from a 32-bit process we lop off the top 32-bits to avoid
800 * getting the wrong address
91447636 801 */
b0d623f7 802 argp = CAST_USER_ADDR_T((uint32_t)uap->arg);
91447636
A
803 }
804
1c79356b 805 pop = &fdp->fd_ofileflags[fd];
55e303ae 806
2d21ac55
A
807#if CONFIG_MACF
808 error = mac_file_check_fcntl(proc_ucred(p), fp->f_fglob, uap->cmd,
809 uap->arg);
810 if (error)
811 goto out;
812#endif
813
1c79356b
A
814 switch (uap->cmd) {
815
816 case F_DUPFD:
6d2010ae 817 case F_DUPFD_CLOEXEC:
39236c6e
A
818 if (FP_ISGUARDED(fp, GUARD_DUP)) {
819 error = fp_guard_exception(p, fd, fp, kGUARD_EXC_DUP);
820 goto out;
821 }
b0d623f7
A
822 newmin = CAST_DOWN_EXPLICIT(int, uap->arg); /* arg is an int, so we won't lose bits */
823 AUDIT_ARG(value32, newmin);
1c79356b 824 if ((u_int)newmin >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
91447636
A
825 newmin >= maxfiles) {
826 error = EINVAL;
827 goto out;
828 }
829 if ( (error = fdalloc(p, newmin, &i)) )
830 goto out;
6d2010ae
A
831 error = finishdup(p, fdp, fd, i,
832 uap->cmd == F_DUPFD_CLOEXEC ? UF_EXCLOSE : 0, retval);
91447636 833 goto out;
1c79356b
A
834
835 case F_GETFD:
39236c6e 836 *retval = (*pop & UF_EXCLOSE)? FD_CLOEXEC : 0;
91447636
A
837 error = 0;
838 goto out;
1c79356b
A
839
840 case F_SETFD:
b0d623f7 841 AUDIT_ARG(value32, uap->arg);
39236c6e
A
842 if (uap->arg & FD_CLOEXEC)
843 *pop |= UF_EXCLOSE;
844 else {
845 if (FILEPROC_TYPE(fp) == FTYPE_GUARDED) {
846 error = fp_guard_exception(p,
847 fd, fp, kGUARD_EXC_NOCLOEXEC);
848 goto out;
849 }
850 *pop &= ~UF_EXCLOSE;
851 }
91447636
A
852 error = 0;
853 goto out;
1c79356b
A
854
855 case F_GETFL:
856 *retval = OFLAGS(fp->f_flag);
91447636
A
857 error = 0;
858 goto out;
1c79356b
A
859
860 case F_SETFL:
861 fp->f_flag &= ~FCNTLFLAGS;
b0d623f7
A
862 tmp = CAST_DOWN_EXPLICIT(int, uap->arg); /* arg is an int, so we won't lose bits */
863 AUDIT_ARG(value32, tmp);
91447636 864 fp->f_flag |= FFLAGS(tmp) & FCNTLFLAGS;
1c79356b 865 tmp = fp->f_flag & FNONBLOCK;
2d21ac55 866 error = fo_ioctl(fp, FIONBIO, (caddr_t)&tmp, &context);
1c79356b 867 if (error)
91447636 868 goto out;
1c79356b 869 tmp = fp->f_flag & FASYNC;
2d21ac55 870 error = fo_ioctl(fp, FIOASYNC, (caddr_t)&tmp, &context);
1c79356b 871 if (!error)
91447636 872 goto out;
1c79356b
A
873 fp->f_flag &= ~FNONBLOCK;
874 tmp = 0;
2d21ac55 875 (void)fo_ioctl(fp, FIONBIO, (caddr_t)&tmp, &context);
91447636 876 goto out;
1c79356b
A
877
878 case F_GETOWN:
879 if (fp->f_type == DTYPE_SOCKET) {
880 *retval = ((struct socket *)fp->f_data)->so_pgid;
91447636
A
881 error = 0;
882 goto out;
1c79356b 883 }
2d21ac55 884 error = fo_ioctl(fp, (int)TIOCGPGRP, (caddr_t)retval, &context);
1c79356b 885 *retval = -*retval;
91447636 886 goto out;
1c79356b
A
887
888 case F_SETOWN:
b0d623f7
A
889 tmp = CAST_DOWN_EXPLICIT(pid_t, uap->arg); /* arg is an int, so we won't lose bits */
890 AUDIT_ARG(value32, tmp);
1c79356b 891 if (fp->f_type == DTYPE_SOCKET) {
91447636
A
892 ((struct socket *)fp->f_data)->so_pgid = tmp;
893 error =0;
894 goto out;
1c79356b 895 }
91447636 896 if (fp->f_type == DTYPE_PIPE) {
0b4c1975 897 error = fo_ioctl(fp, TIOCSPGRP, (caddr_t)&tmp, &context);
91447636
A
898 goto out;
899 }
900
901 if (tmp <= 0) {
902 tmp = -tmp;
1c79356b 903 } else {
2d21ac55 904 proc_t p1 = proc_find(tmp);
91447636
A
905 if (p1 == 0) {
906 error = ESRCH;
907 goto out;
908 }
2d21ac55
A
909 tmp = (int)p1->p_pgrpid;
910 proc_rele(p1);
1c79356b 911 }
2d21ac55 912 error = fo_ioctl(fp, (int)TIOCSPGRP, (caddr_t)&tmp, &context);
91447636 913 goto out;
1c79356b 914
6d2010ae
A
915 case F_SETNOSIGPIPE:
916 tmp = CAST_DOWN_EXPLICIT(int, uap->arg);
917 if (fp->f_type == DTYPE_SOCKET) {
39236c6e 918#if SOCKETS
6d2010ae
A
919 error = sock_setsockopt((struct socket *)fp->f_data,
920 SOL_SOCKET, SO_NOSIGPIPE, &tmp, sizeof (tmp));
39236c6e
A
921#else
922 error = EINVAL;
923#endif
6d2010ae
A
924 } else {
925 struct fileglob *fg = fp->f_fglob;
926
927 lck_mtx_lock_spin(&fg->fg_lock);
928 if (tmp)
929 fg->fg_lflags |= FG_NOSIGPIPE;
930 else
931 fg->fg_lflags &= FG_NOSIGPIPE;
932 lck_mtx_unlock(&fg->fg_lock);
933 error = 0;
934 }
935 goto out;
936
937 case F_GETNOSIGPIPE:
938 if (fp->f_type == DTYPE_SOCKET) {
39236c6e 939#if SOCKETS
6d2010ae
A
940 int retsize = sizeof (*retval);
941 error = sock_getsockopt((struct socket *)fp->f_data,
942 SOL_SOCKET, SO_NOSIGPIPE, retval, &retsize);
39236c6e
A
943#else
944 error = EINVAL;
945#endif
6d2010ae
A
946 } else {
947 *retval = (fp->f_fglob->fg_lflags & FG_NOSIGPIPE) ?
948 1 : 0;
949 error = 0;
950 }
951 goto out;
952
3e170ce0
A
953 case F_SETCONFINED:
954 /*
955 * If this is the only reference to this fglob in the process
956 * and it's already marked as close-on-fork then mark it as
957 * (immutably) "confined" i.e. any fd that points to it will
958 * forever be close-on-fork, and attempts to use an IPC
959 * mechanism to move the descriptor elsewhere will fail.
960 */
961 if (CAST_DOWN_EXPLICIT(int, uap->arg)) {
962 struct fileglob *fg = fp->f_fglob;
963
964 lck_mtx_lock_spin(&fg->fg_lock);
965 if (fg->fg_lflags & FG_CONFINED)
966 error = 0;
967 else if (1 != fg->fg_count)
968 error = EAGAIN; /* go close the dup .. */
969 else if (UF_FORKCLOSE == (*pop & UF_FORKCLOSE)) {
970 fg->fg_lflags |= FG_CONFINED;
971 error = 0;
972 } else
973 error = EBADF; /* open without O_CLOFORK? */
974 lck_mtx_unlock(&fg->fg_lock);
975 } else {
976 /*
977 * Other subsystems may have built on the immutability
978 * of FG_CONFINED; clearing it may be tricky.
979 */
980 error = EPERM; /* immutable */
981 }
982 goto out;
983
984 case F_GETCONFINED:
985 *retval = (fp->f_fglob->fg_lflags & FG_CONFINED) ? 1 : 0;
986 error = 0;
987 goto out;
988
39236c6e 989 case F_SETLKWTIMEOUT:
1c79356b 990 case F_SETLKW:
3e170ce0
A
991 case F_OFD_SETLKWTIMEOUT:
992 case F_OFD_SETLKW:
1c79356b
A
993 flg |= F_WAIT;
994 /* Fall into F_SETLK */
995
996 case F_SETLK:
3e170ce0 997 case F_OFD_SETLK:
91447636
A
998 if (fp->f_type != DTYPE_VNODE) {
999 error = EBADF;
1000 goto out;
1001 }
1c79356b 1002 vp = (struct vnode *)fp->f_data;
ccc36f2f 1003
91447636
A
1004 fflag = fp->f_flag;
1005 offset = fp->f_offset;
1006 proc_fdunlock(p);
1007
1c79356b 1008 /* Copy in the lock structure */
3e170ce0
A
1009 if (F_SETLKWTIMEOUT == uap->cmd ||
1010 F_OFD_SETLKWTIMEOUT == uap->cmd) {
39236c6e
A
1011 error = copyin(argp, (caddr_t) &fltimeout, sizeof(fltimeout));
1012 if (error) {
1013 goto outdrop;
1014 }
1015 fl = fltimeout.fl;
1016 timeout = &fltimeout.timeout;
1017 } else {
1018 error = copyin(argp, (caddr_t)&fl, sizeof(fl));
1019 if (error) {
1020 goto outdrop;
1021 }
91447636 1022 }
2d21ac55 1023
39236c6e
A
1024 /* Check starting byte and ending byte for EOVERFLOW in SEEK_CUR */
1025 /* and ending byte for EOVERFLOW in SEEK_SET */
1026 error = check_file_seek_range(&fl, offset);
1027 if (error) {
1028 goto outdrop;
2d21ac55
A
1029 }
1030
91447636
A
1031 if ( (error = vnode_getwithref(vp)) ) {
1032 goto outdrop;
1033 }
1c79356b 1034 if (fl.l_whence == SEEK_CUR)
91447636
A
1035 fl.l_start += offset;
1036
2d21ac55
A
1037#if CONFIG_MACF
1038 error = mac_file_check_lock(proc_ucred(p), fp->f_fglob,
1039 F_SETLK, &fl);
1040 if (error) {
1041 (void)vnode_put(vp);
1042 goto outdrop;
1043 }
1044#endif
3e170ce0
A
1045 switch (uap->cmd) {
1046 case F_OFD_SETLK:
1047 case F_OFD_SETLKW:
1048 case F_OFD_SETLKWTIMEOUT:
1049 flg |= F_OFD_LOCK;
1050 switch (fl.l_type) {
1051 case F_RDLCK:
1052 if ((fflag & FREAD) == 0) {
1053 error = EBADF;
1054 break;
1055 }
1056 error = VNOP_ADVLOCK(vp, (caddr_t)fp->f_fglob,
1057 F_SETLK, &fl, flg, &context, timeout);
1058 break;
1059 case F_WRLCK:
1060 if ((fflag & FWRITE) == 0) {
1061 error = EBADF;
1062 break;
1063 }
1064 error = VNOP_ADVLOCK(vp, (caddr_t)fp->f_fglob,
1065 F_SETLK, &fl, flg, &context, timeout);
1066 break;
1067 case F_UNLCK:
1068 error = VNOP_ADVLOCK(vp, (caddr_t)fp->f_fglob,
1069 F_UNLCK, &fl, F_OFD_LOCK, &context,
1070 timeout);
1071 break;
1072 default:
1073 error = EINVAL;
1074 break;
91447636 1075 }
3e170ce0
A
1076 if (0 == error &&
1077 (F_RDLCK == fl.l_type || F_WRLCK == fl.l_type)) {
1078 struct fileglob *fg = fp->f_fglob;
1c79356b 1079
3e170ce0
A
1080 /*
1081 * arrange F_UNLCK on last close (once
1082 * set, FG_HAS_OFDLOCK is immutable)
1083 */
1084 if ((fg->fg_lflags & FG_HAS_OFDLOCK) == 0) {
1085 lck_mtx_lock_spin(&fg->fg_lock);
1086 fg->fg_lflags |= FG_HAS_OFDLOCK;
1087 lck_mtx_unlock(&fg->fg_lock);
1088 }
91447636 1089 }
3e170ce0 1090 break;
1c79356b 1091 default:
3e170ce0
A
1092 flg |= F_POSIX;
1093 switch (fl.l_type) {
1094 case F_RDLCK:
1095 if ((fflag & FREAD) == 0) {
1096 error = EBADF;
1097 break;
1098 }
1099 // XXX UInt32 unsafe for LP64 kernel
1100 OSBitOrAtomic(P_LADVLOCK, &p->p_ladvflag);
1101 error = VNOP_ADVLOCK(vp, (caddr_t)p,
1102 F_SETLK, &fl, flg, &context, timeout);
1103 break;
1104 case F_WRLCK:
1105 if ((fflag & FWRITE) == 0) {
1106 error = EBADF;
1107 break;
1108 }
1109 // XXX UInt32 unsafe for LP64 kernel
1110 OSBitOrAtomic(P_LADVLOCK, &p->p_ladvflag);
1111 error = VNOP_ADVLOCK(vp, (caddr_t)p,
1112 F_SETLK, &fl, flg, &context, timeout);
1113 break;
1114 case F_UNLCK:
1115 error = VNOP_ADVLOCK(vp, (caddr_t)p,
1116 F_UNLCK, &fl, F_POSIX, &context, timeout);
1117 break;
1118 default:
1119 error = EINVAL;
1120 break;
1121 }
1122 break;
1c79356b 1123 }
3e170ce0
A
1124 (void) vnode_put(vp);
1125 goto outdrop;
1c79356b
A
1126
1127 case F_GETLK:
3e170ce0 1128 case F_OFD_GETLK:
5ba3f43e
A
1129#if CONFIG_EMBEDDED
1130 case F_GETLKPID:
1131 case F_OFD_GETLKPID:
1132#endif
91447636
A
1133 if (fp->f_type != DTYPE_VNODE) {
1134 error = EBADF;
1135 goto out;
1136 }
1c79356b 1137 vp = (struct vnode *)fp->f_data;
ccc36f2f 1138
91447636
A
1139 offset = fp->f_offset;
1140 proc_fdunlock(p);
1141
1c79356b 1142 /* Copy in the lock structure */
2d21ac55 1143 error = copyin(argp, (caddr_t)&fl, sizeof(fl));
1c79356b 1144 if (error)
91447636
A
1145 goto outdrop;
1146
2d21ac55
A
1147 /* Check starting byte and ending byte for EOVERFLOW in SEEK_CUR */
1148 /* and ending byte for EOVERFLOW in SEEK_SET */
39236c6e
A
1149 error = check_file_seek_range(&fl, offset);
1150 if (error) {
2d21ac55
A
1151 goto outdrop;
1152 }
1153
1154 if ((fl.l_whence == SEEK_SET) && (fl.l_start < 0)) {
1155 error = EINVAL;
1156 goto outdrop;
1157 }
1158
1159 switch (fl.l_type) {
1160 case F_RDLCK:
1161 case F_UNLCK:
1162 case F_WRLCK:
1163 break;
1164 default:
1165 error = EINVAL;
1166 goto outdrop;
1167 }
1168
1169 switch (fl.l_whence) {
1170 case SEEK_CUR:
1171 case SEEK_SET:
1172 case SEEK_END:
1173 break;
1174 default:
1175 error = EINVAL;
1176 goto outdrop;
1177 }
1178
91447636
A
1179 if ( (error = vnode_getwithref(vp)) == 0 ) {
1180 if (fl.l_whence == SEEK_CUR)
1181 fl.l_start += offset;
1182
2d21ac55
A
1183#if CONFIG_MACF
1184 error = mac_file_check_lock(proc_ucred(p), fp->f_fglob,
6d2010ae 1185 uap->cmd, &fl);
2d21ac55
A
1186 if (error == 0)
1187#endif
3e170ce0
A
1188 switch (uap->cmd) {
1189 case F_OFD_GETLK:
1190 error = VNOP_ADVLOCK(vp, (caddr_t)fp->f_fglob,
1191 F_GETLK, &fl, F_OFD_LOCK, &context, NULL);
1192 break;
1193 case F_OFD_GETLKPID:
1194 error = VNOP_ADVLOCK(vp, (caddr_t)fp->f_fglob,
1195 F_GETLKPID, &fl, F_OFD_LOCK, &context, NULL);
1196 break;
1197 default:
1198 error = VNOP_ADVLOCK(vp, (caddr_t)p,
1199 uap->cmd, &fl, F_POSIX, &context, NULL);
1200 break;
1201 }
91447636
A
1202
1203 (void)vnode_put(vp);
1204
1205 if (error == 0)
2d21ac55 1206 error = copyout((caddr_t)&fl, argp, sizeof(fl));
91447636
A
1207 }
1208 goto outdrop;
1209
1210 case F_PREALLOCATE: {
1211 fstore_t alloc_struct; /* structure for allocate command */
1212 u_int32_t alloc_flags = 0;
1213
1214 if (fp->f_type != DTYPE_VNODE) {
1215 error = EBADF;
1216 goto out;
1217 }
1c79356b 1218
ccc36f2f 1219 vp = (struct vnode *)fp->f_data;
91447636 1220 proc_fdunlock(p);
9bccf70c
A
1221
1222 /* make sure that we have write permission */
ccc36f2f
A
1223 if ((fp->f_flag & FWRITE) == 0) {
1224 error = EBADF;
91447636 1225 goto outdrop;
ccc36f2f 1226 }
1c79356b 1227
2d21ac55 1228 error = copyin(argp, (caddr_t)&alloc_struct, sizeof(alloc_struct));
1c79356b 1229 if (error)
91447636 1230 goto outdrop;
1c79356b 1231
9bccf70c 1232 /* now set the space allocated to 0 */
1c79356b 1233 alloc_struct.fst_bytesalloc = 0;
39037602 1234
9bccf70c
A
1235 /*
1236 * Do some simple parameter checking
1237 */
1c79356b
A
1238
1239 /* set up the flags */
1240
1241 alloc_flags |= PREALLOCATE;
39037602 1242
9bccf70c 1243 if (alloc_struct.fst_flags & F_ALLOCATECONTIG)
1c79356b 1244 alloc_flags |= ALLOCATECONTIG;
1c79356b 1245
9bccf70c
A
1246 if (alloc_struct.fst_flags & F_ALLOCATEALL)
1247 alloc_flags |= ALLOCATEALL;
1c79356b 1248
9bccf70c
A
1249 /*
1250 * Do any position mode specific stuff. The only
1251 * position mode supported now is PEOFPOSMODE
1252 */
1c79356b
A
1253
1254 switch (alloc_struct.fst_posmode) {
39037602 1255
1c79356b 1256 case F_PEOFPOSMODE:
91447636 1257 if (alloc_struct.fst_offset != 0) {
ccc36f2f 1258 error = EINVAL;
91447636
A
1259 goto outdrop;
1260 }
1261
1262 alloc_flags |= ALLOCATEFROMPEOF;
1c79356b
A
1263 break;
1264
0b4e3aa0 1265 case F_VOLPOSMODE:
91447636 1266 if (alloc_struct.fst_offset <= 0) {
ccc36f2f 1267 error = EINVAL;
91447636
A
1268 goto outdrop;
1269 }
1270
1271 alloc_flags |= ALLOCATEFROMVOL;
0b4e3aa0
A
1272 break;
1273
91447636 1274 default: {
ccc36f2f 1275 error = EINVAL;
91447636
A
1276 goto outdrop;
1277 }
1c79356b 1278 }
91447636
A
1279 if ( (error = vnode_getwithref(vp)) == 0 ) {
1280 /*
1281 * call allocate to get the space
1282 */
1283 error = VNOP_ALLOCATE(vp,alloc_struct.fst_length,alloc_flags,
1284 &alloc_struct.fst_bytesalloc, alloc_struct.fst_offset,
1285 &context);
1286 (void)vnode_put(vp);
1c79356b 1287
2d21ac55 1288 error2 = copyout((caddr_t)&alloc_struct, argp, sizeof(alloc_struct));
1c79356b 1289
91447636 1290 if (error == 0)
ccc36f2f 1291 error = error2;
1c79356b 1292 }
91447636 1293 goto outdrop;
813fb2f6
A
1294 }
1295 case F_PUNCHHOLE: {
1296 fpunchhole_t args;
1297
1298 if (fp->f_type != DTYPE_VNODE) {
1299 error = EBADF;
1300 goto out;
1301 }
1302
1303 vp = (struct vnode *)fp->f_data;
1304 proc_fdunlock(p);
1305
1306 /* need write permissions */
1307 if ((fp->f_flag & FWRITE) == 0) {
1308 error = EPERM;
1309 goto outdrop;
1310 }
1311
1312 if ((error = copyin(argp, (caddr_t)&args, sizeof(args)))) {
1313 goto outdrop;
1314 }
39037602 1315
813fb2f6
A
1316 if ((error = vnode_getwithref(vp))) {
1317 goto outdrop;
1318 }
1319
1320#if CONFIG_MACF
1321 if ((error = mac_vnode_check_write(&context, fp->f_fglob->fg_cred, vp))) {
1322 (void)vnode_put(vp);
1323 goto outdrop;
91447636 1324 }
813fb2f6
A
1325#endif
1326
1327 error = VNOP_IOCTL(vp, F_PUNCHHOLE, (caddr_t)&args, 0, &context);
1328 (void)vnode_put(vp);
1329
1330 goto outdrop;
1331 }
1332 case F_TRIM_ACTIVE_FILE: {
1333 ftrimactivefile_t args;
1334
1335 if (priv_check_cred(kauth_cred_get(), PRIV_TRIM_ACTIVE_FILE, 0)) {
1336 error = EACCES;
1337 goto out;
1338 }
1339
1340 if (fp->f_type != DTYPE_VNODE) {
1341 error = EBADF;
1342 goto out;
1343 }
1344
1345 vp = (struct vnode *)fp->f_data;
1346 proc_fdunlock(p);
1347
1348 /* need write permissions */
1349 if ((fp->f_flag & FWRITE) == 0) {
1350 error = EPERM;
1351 goto outdrop;
1352 }
1353
1354 if ((error = copyin(argp, (caddr_t)&args, sizeof(args)))) {
1355 goto outdrop;
1356 }
1357
1358 if ((error = vnode_getwithref(vp))) {
1359 goto outdrop;
1360 }
1361
1362 error = VNOP_IOCTL(vp, F_TRIM_ACTIVE_FILE, (caddr_t)&args, 0, &context);
1363 (void)vnode_put(vp);
1364
1365 goto outdrop;
1366 }
9bccf70c 1367 case F_SETSIZE:
91447636
A
1368 if (fp->f_type != DTYPE_VNODE) {
1369 error = EBADF;
1370 goto out;
1371 }
2d21ac55 1372 vp = (struct vnode *)fp->f_data;
91447636 1373 proc_fdunlock(p);
ccc36f2f 1374
91447636 1375 error = copyin(argp, (caddr_t)&offset, sizeof (off_t));
1c79356b 1376 if (error)
91447636 1377 goto outdrop;
b0d623f7 1378 AUDIT_ARG(value64, offset);
1c79356b 1379
2d21ac55
A
1380 error = vnode_getwithref(vp);
1381 if (error)
1382 goto outdrop;
1383
1384#if CONFIG_MACF
1385 error = mac_vnode_check_truncate(&context,
1386 fp->f_fglob->fg_cred, vp);
1387 if (error) {
1388 (void)vnode_put(vp);
1389 goto outdrop;
1390 }
1391#endif
9bccf70c
A
1392 /*
1393 * Make sure that we are root. Growing a file
39037602 1394 * without zero filling the data is a security hole
9bccf70c
A
1395 * root would have access anyway so we'll allow it
1396 */
39236c6e 1397 if (!kauth_cred_issuser(kauth_cred_get())) {
ccc36f2f 1398 error = EACCES;
2d21ac55
A
1399 } else {
1400 /*
91447636
A
1401 * set the file size
1402 */
2d21ac55
A
1403 error = vnode_setsize(vp, offset, IO_NOZEROFILL,
1404 &context);
39037602
A
1405
1406#if CONFIG_MACF
1407 if (error == 0)
1408 mac_vnode_notify_truncate(&context, fp->f_fglob->fg_cred, vp);
1409#endif
91447636 1410 }
2d21ac55
A
1411
1412 (void)vnode_put(vp);
91447636 1413 goto outdrop;
9bccf70c
A
1414
1415 case F_RDAHEAD:
91447636
A
1416 if (fp->f_type != DTYPE_VNODE) {
1417 error = EBADF;
1418 goto out;
1419 }
2d21ac55
A
1420 if (uap->arg)
1421 fp->f_fglob->fg_flag &= ~FNORDAHEAD;
1422 else
1423 fp->f_fglob->fg_flag |= FNORDAHEAD;
91447636 1424
2d21ac55 1425 goto out;
1c79356b 1426
9bccf70c 1427 case F_NOCACHE:
91447636
A
1428 if (fp->f_type != DTYPE_VNODE) {
1429 error = EBADF;
1430 goto out;
1431 }
2d21ac55
A
1432 if (uap->arg)
1433 fp->f_fglob->fg_flag |= FNOCACHE;
1434 else
1435 fp->f_fglob->fg_flag &= ~FNOCACHE;
1436
1437 goto out;
1438
6d2010ae
A
1439 case F_NODIRECT:
1440 if (fp->f_type != DTYPE_VNODE) {
1441 error = EBADF;
1442 goto out;
1443 }
1444 if (uap->arg)
1445 fp->f_fglob->fg_flag |= FNODIRECT;
1446 else
1447 fp->f_fglob->fg_flag &= ~FNODIRECT;
1448
1449 goto out;
1450
316670eb
A
1451 case F_SINGLE_WRITER:
1452 if (fp->f_type != DTYPE_VNODE) {
1453 error = EBADF;
1454 goto out;
1455 }
1456 if (uap->arg)
1457 fp->f_fglob->fg_flag |= FSINGLE_WRITER;
1458 else
1459 fp->f_fglob->fg_flag &= ~FSINGLE_WRITER;
1460
1461 goto out;
1462
2d21ac55
A
1463 case F_GLOBAL_NOCACHE:
1464 if (fp->f_type != DTYPE_VNODE) {
1465 error = EBADF;
1466 goto out;
1467 }
9bccf70c 1468 vp = (struct vnode *)fp->f_data;
91447636 1469 proc_fdunlock(p);
9bccf70c 1470
91447636 1471 if ( (error = vnode_getwithref(vp)) == 0 ) {
2d21ac55
A
1472
1473 *retval = vnode_isnocache(vp);
1474
1475 if (uap->arg)
91447636
A
1476 vnode_setnocache(vp);
1477 else
1478 vnode_clearnocache(vp);
1c79356b 1479
91447636
A
1480 (void)vnode_put(vp);
1481 }
1482 goto outdrop;
1c79356b 1483
2d21ac55
A
1484 case F_CHECK_OPENEVT:
1485 if (fp->f_type != DTYPE_VNODE) {
1486 error = EBADF;
3a60a9f5
A
1487 goto out;
1488 }
1489 vp = (struct vnode *)fp->f_data;
1490 proc_fdunlock(p);
1491
1492 if ( (error = vnode_getwithref(vp)) == 0 ) {
1493
2d21ac55 1494 *retval = vnode_is_openevt(vp);
3a60a9f5 1495
2d21ac55
A
1496 if (uap->arg)
1497 vnode_set_openevt(vp);
3a60a9f5 1498 else
2d21ac55 1499 vnode_clear_openevt(vp);
3a60a9f5
A
1500
1501 (void)vnode_put(vp);
1502 }
1503 goto outdrop;
1504
91447636
A
1505 case F_RDADVISE: {
1506 struct radvisory ra_struct;
9bccf70c 1507
91447636
A
1508 if (fp->f_type != DTYPE_VNODE) {
1509 error = EBADF;
1510 goto out;
1511 }
55e303ae 1512 vp = (struct vnode *)fp->f_data;
91447636 1513 proc_fdunlock(p);
55e303ae 1514
2d21ac55 1515 if ( (error = copyin(argp, (caddr_t)&ra_struct, sizeof(ra_struct))) )
91447636
A
1516 goto outdrop;
1517 if ( (error = vnode_getwithref(vp)) == 0 ) {
1518 error = VNOP_IOCTL(vp, F_RDADVISE, (caddr_t)&ra_struct, 0, &context);
1519
1520 (void)vnode_put(vp);
1521 }
1522 goto outdrop;
1523 }
55e303ae 1524
6d2010ae
A
1525 case F_FLUSH_DATA:
1526
1527 if (fp->f_type != DTYPE_VNODE) {
1528 error = EBADF;
1529 goto out;
1530 }
1531 vp = (struct vnode *)fp->f_data;
1532 proc_fdunlock(p);
1533
1534 if ( (error = vnode_getwithref(vp)) == 0 ) {
813fb2f6 1535 error = VNOP_FSYNC(vp, MNT_NOWAIT, &context);
6d2010ae
A
1536
1537 (void)vnode_put(vp);
1538 }
1539 goto outdrop;
1540
6d2010ae
A
1541 case F_LOG2PHYS:
1542 case F_LOG2PHYS_EXT: {
91447636 1543 struct log2phys l2p_struct; /* structure for allocate command */
6d2010ae 1544 int devBlockSize;
9bccf70c 1545
6d2010ae
A
1546 off_t file_offset = 0;
1547 size_t a_size = 0;
1548 size_t run = 0;
1549
1550 if (uap->cmd == F_LOG2PHYS_EXT) {
1551 error = copyin(argp, (caddr_t)&l2p_struct, sizeof(l2p_struct));
1552 if (error)
1553 goto out;
1554 file_offset = l2p_struct.l2p_devoffset;
1555 } else {
1556 file_offset = fp->f_offset;
1557 }
91447636
A
1558 if (fp->f_type != DTYPE_VNODE) {
1559 error = EBADF;
1560 goto out;
1561 }
1c79356b 1562 vp = (struct vnode *)fp->f_data;
91447636
A
1563 proc_fdunlock(p);
1564 if ( (error = vnode_getwithref(vp)) ) {
1565 goto outdrop;
1566 }
6d2010ae 1567 error = VNOP_OFFTOBLK(vp, file_offset, &lbn);
91447636
A
1568 if (error) {
1569 (void)vnode_put(vp);
1570 goto outdrop;
1571 }
1572 error = VNOP_BLKTOOFF(vp, lbn, &offset);
1573 if (error) {
1574 (void)vnode_put(vp);
1575 goto outdrop;
1576 }
1577 devBlockSize = vfs_devblocksize(vnode_mount(vp));
6d2010ae 1578 if (uap->cmd == F_LOG2PHYS_EXT) {
3e170ce0
A
1579 if (l2p_struct.l2p_contigbytes < 0) {
1580 vnode_put(vp);
1581 error = EINVAL;
39236c6e 1582 goto outdrop;
39236c6e 1583 }
3e170ce0
A
1584
1585 a_size = MIN((uint64_t)l2p_struct.l2p_contigbytes, SIZE_MAX);
6d2010ae
A
1586 } else {
1587 a_size = devBlockSize;
1588 }
39037602 1589
6d2010ae 1590 error = VNOP_BLOCKMAP(vp, offset, a_size, &bn, &run, NULL, 0, &context);
91447636
A
1591
1592 (void)vnode_put(vp);
ccc36f2f 1593
1c79356b
A
1594 if (!error) {
1595 l2p_struct.l2p_flags = 0; /* for now */
6d2010ae
A
1596 if (uap->cmd == F_LOG2PHYS_EXT) {
1597 l2p_struct.l2p_contigbytes = run - (file_offset - offset);
1598 } else {
1599 l2p_struct.l2p_contigbytes = 0; /* for now */
1600 }
39236c6e
A
1601
1602 /*
1603 * The block number being -1 suggests that the file offset is not backed
1604 * by any real blocks on-disk. As a result, just let it be passed back up wholesale.
1605 */
1606 if (bn == -1) {
1607 /* Don't multiply it by the block size */
1608 l2p_struct.l2p_devoffset = bn;
1609 }
1610 else {
1611 l2p_struct.l2p_devoffset = bn * devBlockSize;
1612 l2p_struct.l2p_devoffset += file_offset - offset;
1613 }
2d21ac55 1614 error = copyout((caddr_t)&l2p_struct, argp, sizeof(l2p_struct));
91447636
A
1615 }
1616 goto outdrop;
1c79356b 1617 }
55e303ae 1618 case F_GETPATH: {
91447636
A
1619 char *pathbufp;
1620 int pathlen;
55e303ae 1621
91447636
A
1622 if (fp->f_type != DTYPE_VNODE) {
1623 error = EBADF;
1624 goto out;
1625 }
55e303ae 1626 vp = (struct vnode *)fp->f_data;
91447636 1627 proc_fdunlock(p);
55e303ae 1628
91447636
A
1629 pathlen = MAXPATHLEN;
1630 MALLOC(pathbufp, char *, pathlen, M_TEMP, M_WAITOK);
1631 if (pathbufp == NULL) {
1632 error = ENOMEM;
1633 goto outdrop;
1634 }
1635 if ( (error = vnode_getwithref(vp)) == 0 ) {
1636 error = vn_getpath(vp, pathbufp, &pathlen);
1637 (void)vnode_put(vp);
4a249263 1638
91447636
A
1639 if (error == 0)
1640 error = copyout((caddr_t)pathbufp, argp, pathlen);
1641 }
1642 FREE(pathbufp, M_TEMP);
1643 goto outdrop;
55e303ae
A
1644 }
1645
91447636
A
1646 case F_PATHPKG_CHECK: {
1647 char *pathbufp;
1648 size_t pathlen;
1649
1650 if (fp->f_type != DTYPE_VNODE) {
1651 error = EBADF;
1652 goto out;
1653 }
55e303ae 1654 vp = (struct vnode *)fp->f_data;
91447636 1655 proc_fdunlock(p);
55e303ae 1656
91447636
A
1657 pathlen = MAXPATHLEN;
1658 pathbufp = kalloc(MAXPATHLEN);
1659
1660 if ( (error = copyinstr(argp, pathbufp, MAXPATHLEN, &pathlen)) == 0 ) {
1661 if ( (error = vnode_getwithref(vp)) == 0 ) {
b0d623f7 1662 AUDIT_ARG(text, pathbufp);
91447636
A
1663 error = vn_path_package_check(vp, pathbufp, pathlen, retval);
1664
1665 (void)vnode_put(vp);
1666 }
1667 }
1668 kfree(pathbufp, MAXPATHLEN);
1669 goto outdrop;
1670 }
1671
1672 case F_CHKCLEAN: // used by regression tests to see if all dirty pages got cleaned by fsync()
3e170ce0
A
1673 case F_FULLFSYNC: // fsync + flush the journal + DKIOCSYNCHRONIZE
1674 case F_BARRIERFSYNC: // fsync + barrier
91447636
A
1675 case F_FREEZE_FS: // freeze all other fs operations for the fs of this fd
1676 case F_THAW_FS: { // thaw all frozen fs operations for the fs of this fd
1677 if (fp->f_type != DTYPE_VNODE) {
1678 error = EBADF;
1679 goto out;
1680 }
1681 vp = (struct vnode *)fp->f_data;
1682 proc_fdunlock(p);
ccc36f2f 1683
91447636
A
1684 if ( (error = vnode_getwithref(vp)) == 0 ) {
1685 error = VNOP_IOCTL(vp, uap->cmd, (caddr_t)NULL, 0, &context);
1686
1687 (void)vnode_put(vp);
1688 }
ccc36f2f 1689 break;
55e303ae 1690 }
2d21ac55
A
1691
1692 /*
1693 * SPI (private) for opening a file starting from a dir fd
1694 */
1695 case F_OPENFROM: {
1696 struct user_fopenfrom fopen;
1697 struct vnode_attr va;
1698 struct nameidata nd;
1699 int cmode;
1700
1701 /* Check if this isn't a valid file descriptor */
1702 if ((fp->f_type != DTYPE_VNODE) ||
1703 (fp->f_flag & FREAD) == 0) {
1704 error = EBADF;
91447636
A
1705 goto out;
1706 }
2d21ac55
A
1707 vp = (struct vnode *)fp->f_data;
1708 proc_fdunlock(p);
91447636 1709
2d21ac55
A
1710 if (vnode_getwithref(vp)) {
1711 error = ENOENT;
1712 goto outdrop;
1713 }
39037602 1714
2d21ac55
A
1715 /* Only valid for directories */
1716 if (vp->v_type != VDIR) {
1717 vnode_put(vp);
1718 error = ENOTDIR;
1719 goto outdrop;
1720 }
91447636 1721
2d21ac55
A
1722 /* Get flags, mode and pathname arguments. */
1723 if (IS_64BIT_PROCESS(p)) {
1724 error = copyin(argp, &fopen, sizeof(fopen));
1725 } else {
b0d623f7 1726 struct user32_fopenfrom fopen32;
2d21ac55
A
1727
1728 error = copyin(argp, &fopen32, sizeof(fopen32));
1729 fopen.o_flags = fopen32.o_flags;
1730 fopen.o_mode = fopen32.o_mode;
1731 fopen.o_pathname = CAST_USER_ADDR_T(fopen32.o_pathname);
1732 }
1733 if (error) {
1734 vnode_put(vp);
1735 goto outdrop;
1736 }
b0d623f7
A
1737 AUDIT_ARG(fflags, fopen.o_flags);
1738 AUDIT_ARG(mode, fopen.o_mode);
2d21ac55
A
1739 VATTR_INIT(&va);
1740 /* Mask off all but regular access permissions */
1741 cmode = ((fopen.o_mode &~ fdp->fd_cmask) & ALLPERMS) & ~S_ISTXT;
1742 VATTR_SET(&va, va_mode, cmode & ACCESSPERMS);
1743
1744 /* Start the lookup relative to the file descriptor's vnode. */
6d2010ae 1745 NDINIT(&nd, LOOKUP, OP_OPEN, USEDVP | FOLLOW | AUDITVNPATH1, UIO_USERSPACE,
2d21ac55
A
1746 fopen.o_pathname, &context);
1747 nd.ni_dvp = vp;
1748
39236c6e
A
1749 error = open1(&context, &nd, fopen.o_flags, &va,
1750 fileproc_alloc_init, NULL, retval);
2d21ac55
A
1751
1752 vnode_put(vp);
1753 break;
1754 }
1755 /*
1756 * SPI (private) for unlinking a file starting from a dir fd
1757 */
1758 case F_UNLINKFROM: {
2d21ac55
A
1759 user_addr_t pathname;
1760
1761 /* Check if this isn't a valid file descriptor */
1762 if ((fp->f_type != DTYPE_VNODE) ||
1763 (fp->f_flag & FREAD) == 0) {
91447636
A
1764 error = EBADF;
1765 goto out;
1766 }
1767 vp = (struct vnode *)fp->f_data;
1768 proc_fdunlock(p);
1769
2d21ac55
A
1770 if (vnode_getwithref(vp)) {
1771 error = ENOENT;
1772 goto outdrop;
1773 }
39037602 1774
2d21ac55
A
1775 /* Only valid for directories */
1776 if (vp->v_type != VDIR) {
1777 vnode_put(vp);
1778 error = ENOTDIR;
1779 goto outdrop;
1780 }
91447636 1781
2d21ac55
A
1782 /* Get flags, mode and pathname arguments. */
1783 if (IS_64BIT_PROCESS(p)) {
1784 pathname = (user_addr_t)argp;
1785 } else {
1786 pathname = CAST_USER_ADDR_T(argp);
91447636 1787 }
ccc36f2f 1788
2d21ac55 1789 /* Start the lookup relative to the file descriptor's vnode. */
c18c124e 1790 error = unlink1(&context, vp, pathname, UIO_USERSPACE, 0);
39037602 1791
2d21ac55
A
1792 vnode_put(vp);
1793 break;
1c79356b 1794
1c79356b 1795 }
2d21ac55 1796
b0d623f7
A
1797 case F_ADDSIGS:
1798 case F_ADDFILESIGS:
c18c124e 1799 case F_ADDFILESIGS_FOR_DYLD_SIM:
3e170ce0 1800 case F_ADDFILESIGS_RETURN:
b0d623f7 1801 {
3e170ce0 1802 struct cs_blob *blob = NULL;
2d21ac55
A
1803 struct user_fsignatures fs;
1804 kern_return_t kr;
b0d623f7 1805 vm_offset_t kernel_blob_addr;
2d21ac55 1806 vm_size_t kernel_blob_size;
c18c124e 1807 int blob_add_flags = 0;
2d21ac55
A
1808
1809 if (fp->f_type != DTYPE_VNODE) {
1810 error = EBADF;
1811 goto out;
1812 }
1813 vp = (struct vnode *)fp->f_data;
1814 proc_fdunlock(p);
c18c124e
A
1815
1816 if (uap->cmd == F_ADDFILESIGS_FOR_DYLD_SIM) {
1817 blob_add_flags |= MAC_VNODE_CHECK_DYLD_SIM;
1818 if ((p->p_csflags & CS_KILL) == 0) {
1819 proc_lock(p);
1820 p->p_csflags |= CS_KILL;
1821 proc_unlock(p);
1822 }
1823 }
1824
2d21ac55
A
1825 error = vnode_getwithref(vp);
1826 if (error)
1827 goto outdrop;
1828
1829 if (IS_64BIT_PROCESS(p)) {
1830 error = copyin(argp, &fs, sizeof (fs));
1831 } else {
b0d623f7 1832 struct user32_fsignatures fs32;
2d21ac55
A
1833
1834 error = copyin(argp, &fs32, sizeof (fs32));
1835 fs.fs_file_start = fs32.fs_file_start;
1836 fs.fs_blob_start = CAST_USER_ADDR_T(fs32.fs_blob_start);
1837 fs.fs_blob_size = fs32.fs_blob_size;
1838 }
1839
1840 if (error) {
1841 vnode_put(vp);
1842 goto outdrop;
1843 }
1844
3e170ce0
A
1845 /*
1846 * First check if we have something loaded a this offset
1847 */
1848 blob = ubc_cs_blob_get(vp, CPU_TYPE_ANY, fs.fs_file_start);
1849 if (blob != NULL)
593a1d5f 1850 {
c18c124e
A
1851 /* If this is for dyld_sim revalidate the blob */
1852 if (uap->cmd == F_ADDFILESIGS_FOR_DYLD_SIM) {
39037602
A
1853 error = ubc_cs_blob_revalidate(vp, blob, NULL, blob_add_flags);
1854 if (error) {
1855 vnode_put(vp);
1856 goto outdrop;
1857 }
c18c124e 1858 }
2d21ac55 1859
3e170ce0
A
1860 } else {
1861 /*
1862 * An arbitrary limit, to prevent someone from mapping in a 20GB blob. This should cover
1863 * our use cases for the immediate future, but note that at the time of this commit, some
1864 * platforms are nearing 2MB blob sizes (with a prior soft limit of 2.5MB).
1865 *
1866 * We should consider how we can manage this more effectively; the above means that some
1867 * platforms are using megabytes of memory for signing data; it merely hasn't crossed the
1868 * threshold considered ridiculous at the time of this change.
1869 */
1870#define CS_MAX_BLOB_SIZE (40ULL * 1024ULL * 1024ULL)
1871 if (fs.fs_blob_size > CS_MAX_BLOB_SIZE) {
1872 error = E2BIG;
1873 vnode_put(vp);
1874 goto outdrop;
1875 }
2d21ac55 1876
3e170ce0
A
1877 kernel_blob_size = CAST_DOWN(vm_size_t, fs.fs_blob_size);
1878 kr = ubc_cs_blob_allocate(&kernel_blob_addr, &kernel_blob_size);
1879 if (kr != KERN_SUCCESS) {
1880 error = ENOMEM;
1881 vnode_put(vp);
1882 goto outdrop;
c18c124e 1883 }
2d21ac55 1884
3e170ce0
A
1885 if(uap->cmd == F_ADDSIGS) {
1886 error = copyin(fs.fs_blob_start,
1887 (void *) kernel_blob_addr,
593a1d5f 1888 kernel_blob_size);
3e170ce0
A
1889 } else /* F_ADDFILESIGS || F_ADDFILESIGS_RETURN || F_ADDFILESIGS_FOR_DYLD_SIM */ {
1890 int resid;
1891
1892 error = vn_rdwr(UIO_READ,
1893 vp,
1894 (caddr_t) kernel_blob_addr,
1895 kernel_blob_size,
1896 fs.fs_file_start + fs.fs_blob_start,
1897 UIO_SYSSPACE,
1898 0,
1899 kauth_cred_get(),
1900 &resid,
1901 p);
1902 if ((error == 0) && resid) {
1903 /* kernel_blob_size rounded to a page size, but signature may be at end of file */
1904 memset((void *)(kernel_blob_addr + (kernel_blob_size - resid)), 0x0, resid);
1905 }
1906 }
39037602 1907
3e170ce0
A
1908 if (error) {
1909 ubc_cs_blob_deallocate(kernel_blob_addr,
39037602 1910 kernel_blob_size);
3e170ce0
A
1911 vnode_put(vp);
1912 goto outdrop;
1913 }
1914
1915 blob = NULL;
1916 error = ubc_cs_blob_add(vp,
1917 CPU_TYPE_ANY, /* not for a specific architecture */
1918 fs.fs_file_start,
39037602 1919 &kernel_blob_addr,
3e170ce0 1920 kernel_blob_size,
39037602 1921 NULL,
3e170ce0
A
1922 blob_add_flags,
1923 &blob);
39037602
A
1924
1925 /* ubc_blob_add() has consumed "kernel_blob_addr" if it is zeroed */
3e170ce0 1926 if (error) {
39037602
A
1927 if (kernel_blob_addr) {
1928 ubc_cs_blob_deallocate(kernel_blob_addr,
1929 kernel_blob_size);
1930 }
1931 vnode_put(vp);
1932 goto outdrop;
3e170ce0 1933 } else {
6d2010ae 1934#if CHECK_CS_VALIDATION_BITMAP
3e170ce0 1935 ubc_cs_validation_bitmap_allocate( vp );
6d2010ae 1936#endif
3e170ce0
A
1937 }
1938 }
1939
1940 if (uap->cmd == F_ADDFILESIGS_RETURN || uap->cmd == F_ADDFILESIGS_FOR_DYLD_SIM) {
1941 /*
1942 * The first element of the structure is a
1943 * off_t that happen to have the same size for
1944 * all archs. Lets overwrite that.
1945 */
1946 off_t end_offset = 0;
1947 if (blob)
1948 end_offset = blob->csb_end_offset;
1949 error = copyout(&end_offset, argp, sizeof (end_offset));
2d21ac55
A
1950 }
1951
1952 (void) vnode_put(vp);
1953 break;
1954 }
39037602 1955 case F_GETCODEDIR:
39236c6e 1956 case F_FINDSIGS: {
39236c6e 1957 error = ENOTSUP;
3e170ce0 1958 goto out;
6d2010ae 1959 }
39037602
A
1960 case F_CHECK_LV: {
1961 struct fileglob *fg;
1962 fchecklv_t lv;
1963
1964 if (fp->f_type != DTYPE_VNODE) {
1965 error = EBADF;
1966 goto out;
1967 }
1968 fg = fp->f_fglob;
1969 proc_fdunlock(p);
1970
1971 if (IS_64BIT_PROCESS(p)) {
1972 error = copyin(argp, &lv, sizeof (lv));
1973 } else {
1974 struct user32_fchecklv lv32;
1975
1976 error = copyin(argp, &lv32, sizeof (lv32));
1977 lv.lv_file_start = lv32.lv_file_start;
5ba3f43e 1978 lv.lv_error_message = (void *)(uintptr_t)lv32.lv_error_message;
39037602
A
1979 lv.lv_error_message_size = lv32.lv_error_message;
1980 }
1981 if (error)
1982 goto outdrop;
1983
1984#if CONFIG_MACF
1985 error = mac_file_check_library_validation(p, fg, lv.lv_file_start,
5ba3f43e 1986 (user_long_t)lv.lv_error_message, lv.lv_error_message_size);
39037602
A
1987#endif
1988
1989 break;
1990 }
316670eb 1991#if CONFIG_PROTECT
6d2010ae 1992 case F_GETPROTECTIONCLASS: {
6d2010ae
A
1993 if (fp->f_type != DTYPE_VNODE) {
1994 error = EBADF;
1995 goto out;
1996 }
1997 vp = (struct vnode *)fp->f_data;
1998
1999 proc_fdunlock(p);
2000
2001 if (vnode_getwithref(vp)) {
2002 error = ENOENT;
2003 goto outdrop;
2004 }
39037602
A
2005
2006 struct vnode_attr va;
2007
2008 VATTR_INIT(&va);
2009 VATTR_WANTED(&va, va_dataprotect_class);
2010 error = VNOP_GETATTR(vp, &va, &context);
2011 if (!error) {
2012 if (VATTR_IS_SUPPORTED(&va, va_dataprotect_class))
2013 *retval = va.va_dataprotect_class;
2014 else
2015 error = ENOTSUP;
6d2010ae 2016 }
2d21ac55
A
2017
2018 vnode_put(vp);
6d2010ae
A
2019 break;
2020 }
39037602 2021
6d2010ae
A
2022 case F_SETPROTECTIONCLASS: {
2023 /* tmp must be a valid PROTECTION_CLASS_* */
2024 tmp = CAST_DOWN_EXPLICIT(uint32_t, uap->arg);
39037602 2025
6d2010ae
A
2026 if (fp->f_type != DTYPE_VNODE) {
2027 error = EBADF;
2028 goto out;
2029 }
2030 vp = (struct vnode *)fp->f_data;
2031
2032 proc_fdunlock(p);
39037602 2033
6d2010ae
A
2034 if (vnode_getwithref(vp)) {
2035 error = ENOENT;
2036 goto outdrop;
39037602
A
2037 }
2038
6d2010ae
A
2039 /* Only go forward if you have write access */
2040 vfs_context_t ctx = vfs_context_current();
2041 if(vnode_authorize(vp, NULLVP, (KAUTH_VNODE_ACCESS | KAUTH_VNODE_WRITE_DATA), ctx) != 0) {
2042 vnode_put(vp);
2043 error = EBADF;
2044 goto outdrop;
2045 }
39037602
A
2046
2047 struct vnode_attr va;
2048
2049 VATTR_INIT(&va);
2050 VATTR_SET(&va, va_dataprotect_class, tmp);
2051
2052 error = VNOP_SETATTR(vp, &va, ctx);
2053
6d2010ae
A
2054 vnode_put(vp);
2055 break;
39037602 2056 }
316670eb
A
2057
2058 case F_TRANSCODEKEY: {
316670eb
A
2059 if (fp->f_type != DTYPE_VNODE) {
2060 error = EBADF;
2061 goto out;
2062 }
39037602 2063
316670eb
A
2064 vp = (struct vnode *)fp->f_data;
2065 proc_fdunlock(p);
2066
2067 if (vnode_getwithref(vp)) {
2068 error = ENOENT;
2069 goto outdrop;
fe8ab488
A
2070 }
2071
39037602
A
2072 cp_key_t k = {
2073 .len = CP_MAX_WRAPPEDKEYSIZE,
2074 };
2075
2076 MALLOC(k.key, char *, k.len, M_TEMP, M_WAITOK);
2077
2078 error = VNOP_IOCTL(vp, F_TRANSCODEKEY, (caddr_t)&k, 1, &context);
2079
316670eb 2080 vnode_put(vp);
fe8ab488
A
2081
2082 if (error == 0) {
39037602
A
2083 error = copyout(k.key, argp, k.len);
2084 *retval = k.len;
fe8ab488
A
2085 }
2086
39037602 2087 FREE(k.key, M_TEMP);
fe8ab488 2088
316670eb 2089 break;
39037602 2090 }
316670eb
A
2091
2092 case F_GETPROTECTIONLEVEL: {
316670eb 2093 if (fp->f_type != DTYPE_VNODE) {
39037602 2094 error = EBADF;
316670eb
A
2095 goto out;
2096 }
2097
2098 vp = (struct vnode*) fp->f_data;
2099 proc_fdunlock (p);
2100
2101 if (vnode_getwithref(vp)) {
2102 error = ENOENT;
2103 goto outdrop;
2104 }
2105
39037602 2106 error = VNOP_IOCTL(vp, F_GETPROTECTIONLEVEL, (caddr_t)retval, 0, &context);
316670eb
A
2107
2108 vnode_put (vp);
2109 break;
2110 }
39236c6e
A
2111
2112 case F_GETDEFAULTPROTLEVEL: {
39236c6e 2113 if (fp->f_type != DTYPE_VNODE) {
39037602 2114 error = EBADF;
39236c6e
A
2115 goto out;
2116 }
2117
2118 vp = (struct vnode*) fp->f_data;
2119 proc_fdunlock (p);
2120
2121 if (vnode_getwithref(vp)) {
2122 error = ENOENT;
2123 goto outdrop;
2124 }
2125
2126 /*
39037602 2127 * if cp_get_major_vers fails, error will be set to proper errno
39236c6e
A
2128 * and cp_version will still be 0.
2129 */
2130
39037602 2131 error = VNOP_IOCTL(vp, F_GETDEFAULTPROTLEVEL, (caddr_t)retval, 0, &context);
39236c6e
A
2132
2133 vnode_put (vp);
2134 break;
2135 }
2136
6d2010ae 2137#endif /* CONFIG_PROTECT */
316670eb 2138
6d2010ae
A
2139 case F_MOVEDATAEXTENTS: {
2140 struct fileproc *fp2 = NULL;
2141 struct vnode *src_vp = NULLVP;
2142 struct vnode *dst_vp = NULLVP;
2143 /* We need to grab the 2nd FD out of the argments before moving on. */
2144 int fd2 = CAST_DOWN_EXPLICIT(int32_t, uap->arg);
c7d2c2c6
A
2145
2146 error = priv_check_cred(kauth_cred_get(), PRIV_VFS_MOVE_DATA_EXTENTS, 0);
2147 if (error)
2148 goto out;
2149
6d2010ae
A
2150 if (fp->f_type != DTYPE_VNODE) {
2151 error = EBADF;
2152 goto out;
2153 }
6d2010ae
A
2154
2155 /* For now, special case HFS+ only, since this is SPI. */
316670eb 2156 src_vp = (struct vnode *)fp->f_data;
6d2010ae
A
2157 if (src_vp->v_tag != VT_HFS) {
2158 error = EINVAL;
2159 goto out;
2160 }
2161
316670eb 2162 /*
39037602 2163 * Get the references before we start acquiring iocounts on the vnodes,
316670eb
A
2164 * while we still hold the proc fd lock
2165 */
6d2010ae
A
2166 if ( (error = fp_lookup(p, fd2, &fp2, 1)) ) {
2167 error = EBADF;
2168 goto out;
2169 }
2170 if (fp2->f_type != DTYPE_VNODE) {
2171 fp_drop(p, fd2, fp2, 1);
2172 error = EBADF;
2173 goto out;
2174 }
2175 dst_vp = (struct vnode *)fp2->f_data;
6d2010ae
A
2176 if (dst_vp->v_tag != VT_HFS) {
2177 fp_drop(p, fd2, fp2, 1);
2178 error = EINVAL;
2179 goto out;
2180 }
2181
2182#if CONFIG_MACF
2183 /* Re-do MAC checks against the new FD, pass in a fake argument */
2184 error = mac_file_check_fcntl(proc_ucred(p), fp2->f_fglob, uap->cmd, 0);
2185 if (error) {
2186 fp_drop(p, fd2, fp2, 1);
2187 goto out;
2188 }
2189#endif
2190 /* Audit the 2nd FD */
2191 AUDIT_ARG(fd, fd2);
2192
2193 proc_fdunlock(p);
2194
6d2010ae
A
2195 if (vnode_getwithref(src_vp)) {
2196 fp_drop(p, fd2, fp2, 0);
2197 error = ENOENT;
2198 goto outdrop;
39037602 2199 }
6d2010ae
A
2200 if (vnode_getwithref(dst_vp)) {
2201 vnode_put (src_vp);
2202 fp_drop(p, fd2, fp2, 0);
2203 error = ENOENT;
2204 goto outdrop;
39037602
A
2205 }
2206
2207 /*
6d2010ae
A
2208 * Basic asserts; validate they are not the same and that
2209 * both live on the same filesystem.
2210 */
6d2010ae
A
2211 if (dst_vp == src_vp) {
2212 vnode_put (src_vp);
2213 vnode_put (dst_vp);
2214 fp_drop (p, fd2, fp2, 0);
2215 error = EINVAL;
2216 goto outdrop;
39037602 2217 }
316670eb 2218
6d2010ae
A
2219 if (dst_vp->v_mount != src_vp->v_mount) {
2220 vnode_put (src_vp);
2221 vnode_put (dst_vp);
2222 fp_drop (p, fd2, fp2, 0);
2223 error = EXDEV;
2224 goto outdrop;
2225 }
2226
316670eb
A
2227 /* Now we have a legit pair of FDs. Go to work */
2228
6d2010ae 2229 /* Now check for write access to the target files */
39037602 2230 if(vnode_authorize(src_vp, NULLVP,
316670eb 2231 (KAUTH_VNODE_ACCESS | KAUTH_VNODE_WRITE_DATA), &context) != 0) {
6d2010ae
A
2232 vnode_put(src_vp);
2233 vnode_put(dst_vp);
2234 fp_drop(p, fd2, fp2, 0);
2235 error = EBADF;
2236 goto outdrop;
2237 }
39037602
A
2238
2239 if(vnode_authorize(dst_vp, NULLVP,
316670eb 2240 (KAUTH_VNODE_ACCESS | KAUTH_VNODE_WRITE_DATA), &context) != 0) {
6d2010ae
A
2241 vnode_put(src_vp);
2242 vnode_put(dst_vp);
2243 fp_drop(p, fd2, fp2, 0);
2244 error = EBADF;
2245 goto outdrop;
2246 }
39037602 2247
6d2010ae 2248 /* Verify that both vps point to files and not directories */
316670eb 2249 if ( !vnode_isreg(src_vp) || !vnode_isreg(dst_vp)) {
6d2010ae 2250 error = EINVAL;
316670eb
A
2251 vnode_put (src_vp);
2252 vnode_put (dst_vp);
2253 fp_drop (p, fd2, fp2, 0);
6d2010ae
A
2254 goto outdrop;
2255 }
2256
39037602 2257 /*
6d2010ae
A
2258 * The exchangedata syscall handler passes in 0 for the flags to VNOP_EXCHANGE.
2259 * We'll pass in our special bit indicating that the new behavior is expected
2260 */
39037602 2261
6d2010ae 2262 error = VNOP_EXCHANGE(src_vp, dst_vp, FSOPT_EXCHANGE_DATA_ONLY, &context);
39037602 2263
6d2010ae
A
2264 vnode_put (src_vp);
2265 vnode_put (dst_vp);
2266 fp_drop(p, fd2, fp2, 0);
2d21ac55
A
2267 break;
2268 }
39037602
A
2269
2270 /*
39236c6e
A
2271 * SPI for making a file compressed.
2272 */
2273 case F_MAKECOMPRESSED: {
2274 uint32_t gcounter = CAST_DOWN_EXPLICIT(uint32_t, uap->arg);
2275
2276 if (fp->f_type != DTYPE_VNODE) {
39037602 2277 error = EBADF;
39236c6e
A
2278 goto out;
2279 }
2280
2281 vp = (struct vnode*) fp->f_data;
2282 proc_fdunlock (p);
2283
2284 /* get the vnode */
2285 if (vnode_getwithref(vp)) {
2286 error = ENOENT;
2287 goto outdrop;
2288 }
2289
2290 /* Is it a file? */
2291 if ((vnode_isreg(vp) == 0) && (vnode_islnk(vp) == 0)) {
2292 vnode_put(vp);
2293 error = EBADF;
2294 goto outdrop;
2295 }
2296
2297 /* invoke ioctl to pass off to FS */
39037602 2298 /* Only go forward if you have write access */
39236c6e
A
2299 vfs_context_t ctx = vfs_context_current();
2300 if(vnode_authorize(vp, NULLVP, (KAUTH_VNODE_ACCESS | KAUTH_VNODE_WRITE_DATA), ctx) != 0) {
2301 vnode_put(vp);
2302 error = EBADF;
2303 goto outdrop;
2304 }
2305
2306 error = VNOP_IOCTL(vp, uap->cmd, (caddr_t)&gcounter, 0, &context);
2307
2308 vnode_put (vp);
39037602 2309 break;
39236c6e 2310 }
39037602 2311
39236c6e
A
2312 /*
2313 * SPI (private) for indicating to a filesystem that subsequent writes to
2314 * the open FD will written to the Fastflow.
2315 */
2316 case F_SET_GREEDY_MODE:
2317 /* intentionally drop through to the same handler as F_SETSTATIC.
2318 * both fcntls should pass the argument and their selector into VNOP_IOCTL.
2319 */
2320
316670eb
A
2321 /*
2322 * SPI (private) for indicating to a filesystem that subsequent writes to
2323 * the open FD will represent static content.
2324 */
2325 case F_SETSTATICCONTENT: {
2326 caddr_t ioctl_arg = NULL;
2d21ac55 2327
316670eb
A
2328 if (uap->arg) {
2329 ioctl_arg = (caddr_t) 1;
2330 }
2331
2332 if (fp->f_type != DTYPE_VNODE) {
2333 error = EBADF;
2334 goto out;
2335 }
2336 vp = (struct vnode *)fp->f_data;
2337 proc_fdunlock(p);
2338
2339 error = vnode_getwithref(vp);
2340 if (error) {
2341 error = ENOENT;
2342 goto outdrop;
2343 }
2344
2345 /* Only go forward if you have write access */
2346 vfs_context_t ctx = vfs_context_current();
2347 if(vnode_authorize(vp, NULLVP, (KAUTH_VNODE_ACCESS | KAUTH_VNODE_WRITE_DATA), ctx) != 0) {
2348 vnode_put(vp);
2349 error = EBADF;
2350 goto outdrop;
2351 }
2352
2353 error = VNOP_IOCTL(vp, uap->cmd, ioctl_arg, 0, &context);
2354 (void)vnode_put(vp);
39037602 2355
fe8ab488
A
2356 break;
2357 }
2358
2359 /*
2360 * SPI (private) for indicating to the lower level storage driver that the
2361 * subsequent writes should be of a particular IO type (burst, greedy, static),
2362 * or other flavors that may be necessary.
2363 */
2364 case F_SETIOTYPE: {
39037602 2365 caddr_t param_ptr;
fe8ab488
A
2366 uint32_t param;
2367
2368 if (uap->arg) {
2369 /* extract 32 bits of flags from userland */
2370 param_ptr = (caddr_t) uap->arg;
2371 param = (uint32_t) param_ptr;
2372 }
2373 else {
2374 /* If no argument is specified, error out */
2375 error = EINVAL;
2376 goto out;
2377 }
39037602
A
2378
2379 /*
2380 * Validate the different types of flags that can be specified:
fe8ab488
A
2381 * all of them are mutually exclusive for now.
2382 */
2383 switch (param) {
2384 case F_IOTYPE_ISOCHRONOUS:
2385 break;
2386
2387 default:
2388 error = EINVAL;
2389 goto out;
2390 }
2391
2392
2393 if (fp->f_type != DTYPE_VNODE) {
2394 error = EBADF;
2395 goto out;
2396 }
2397 vp = (struct vnode *)fp->f_data;
2398 proc_fdunlock(p);
2399
2400 error = vnode_getwithref(vp);
2401 if (error) {
2402 error = ENOENT;
2403 goto outdrop;
2404 }
2405
2406 /* Only go forward if you have write access */
2407 vfs_context_t ctx = vfs_context_current();
2408 if(vnode_authorize(vp, NULLVP, (KAUTH_VNODE_ACCESS | KAUTH_VNODE_WRITE_DATA), ctx) != 0) {
2409 vnode_put(vp);
2410 error = EBADF;
2411 goto outdrop;
2412 }
2413
2414 error = VNOP_IOCTL(vp, uap->cmd, param_ptr, 0, &context);
2415 (void)vnode_put(vp);
2416
2417 break;
2418 }
2419
fe8ab488 2420 /*
6d2010ae
A
2421 * Set the vnode pointed to by 'fd'
2422 * and tag it as the (potentially future) backing store
2423 * for another filesystem
2424 */
2425 case F_SETBACKINGSTORE: {
2426 if (fp->f_type != DTYPE_VNODE) {
2427 error = EBADF;
2428 goto out;
2429 }
39037602 2430
316670eb
A
2431 vp = (struct vnode *)fp->f_data;
2432
6d2010ae
A
2433 if (vp->v_tag != VT_HFS) {
2434 error = EINVAL;
2435 goto out;
6d2010ae
A
2436 }
2437 proc_fdunlock(p);
2438
2439 if (vnode_getwithref(vp)) {
2440 error = ENOENT;
2441 goto outdrop;
2442 }
39037602 2443
6d2010ae
A
2444 /* only proceed if you have write access */
2445 vfs_context_t ctx = vfs_context_current();
2446 if(vnode_authorize(vp, NULLVP, (KAUTH_VNODE_ACCESS | KAUTH_VNODE_WRITE_DATA), ctx) != 0) {
2447 vnode_put(vp);
2448 error = EBADF;
2449 goto outdrop;
2450 }
2451
39037602 2452
6d2010ae
A
2453 /* If arg != 0, set, otherwise unset */
2454 if (uap->arg) {
316670eb 2455 error = VNOP_IOCTL (vp, uap->cmd, (caddr_t)1, 0, &context);
6d2010ae
A
2456 }
2457 else {
316670eb 2458 error = VNOP_IOCTL (vp, uap->cmd, (caddr_t)NULL, 0, &context);
6d2010ae 2459 }
39037602 2460
6d2010ae
A
2461 vnode_put(vp);
2462 break;
d1ecb069
A
2463 }
2464
39037602 2465 /*
6d2010ae
A
2466 * like F_GETPATH, but special semantics for
2467 * the mobile time machine handler.
2468 */
2469 case F_GETPATH_MTMINFO: {
2470 char *pathbufp;
2471 int pathlen;
2472
2473 if (fp->f_type != DTYPE_VNODE) {
2474 error = EBADF;
2475 goto out;
2476 }
2477 vp = (struct vnode *)fp->f_data;
2478 proc_fdunlock(p);
2479
2480 pathlen = MAXPATHLEN;
2481 MALLOC(pathbufp, char *, pathlen, M_TEMP, M_WAITOK);
2482 if (pathbufp == NULL) {
2483 error = ENOMEM;
2484 goto outdrop;
2485 }
2486 if ( (error = vnode_getwithref(vp)) == 0 ) {
2487 int backingstore = 0;
39037602 2488
6d2010ae
A
2489 /* Check for error from vn_getpath before moving on */
2490 if ((error = vn_getpath(vp, pathbufp, &pathlen)) == 0) {
2491 if (vp->v_tag == VT_HFS) {
316670eb 2492 error = VNOP_IOCTL (vp, uap->cmd, (caddr_t) &backingstore, 0, &context);
6d2010ae
A
2493 }
2494 (void)vnode_put(vp);
2495
2496 if (error == 0) {
2497 error = copyout((caddr_t)pathbufp, argp, pathlen);
2498 }
2499 if (error == 0) {
39037602 2500 /*
6d2010ae
A
2501 * If the copyout was successful, now check to ensure
2502 * that this vnode is not a BACKINGSTORE vnode. mtmd
2503 * wants the path regardless.
2504 */
2505 if (backingstore) {
2506 error = EBUSY;
2507 }
2508 }
2509 } else
2510 (void)vnode_put(vp);
2511 }
2512 FREE(pathbufp, M_TEMP);
2513 goto outdrop;
d1ecb069
A
2514 }
2515
3e170ce0
A
2516#if DEBUG || DEVELOPMENT
2517 case F_RECYCLE:
2518 if (fp->f_type != DTYPE_VNODE) {
2519 error = EBADF;
2520 goto out;
2521 }
2522 vp = (struct vnode *)fp->f_data;
2523 proc_fdunlock(p);
2524
2525 vnode_recycle(vp);
2526 break;
2527#endif
2528
2d21ac55 2529 default:
e2fac8b1
A
2530 /*
2531 * This is an fcntl() that we d not recognize at this level;
2532 * if this is a vnode, we send it down into the VNOP_IOCTL
2533 * for this vnode; this can include special devices, and will
2534 * effectively overload fcntl() to send ioctl()'s.
2535 */
2536 if((uap->cmd & IOC_VOID) && (uap->cmd & IOC_INOUT)){
39236c6e 2537 error = EINVAL;
2d21ac55
A
2538 goto out;
2539 }
39037602 2540
39236c6e
A
2541 /* Catch any now-invalid fcntl() selectors */
2542 switch (uap->cmd) {
2543 case F_MARKDEPENDENCY:
2544 error = EINVAL;
2545 goto out;
2546 default:
2547 break;
2548 }
2549
2d21ac55
A
2550 if (fp->f_type != DTYPE_VNODE) {
2551 error = EBADF;
2552 goto out;
2553 }
2554 vp = (struct vnode *)fp->f_data;
2555 proc_fdunlock(p);
2556
2557 if ( (error = vnode_getwithref(vp)) == 0 ) {
e2fac8b1 2558#define STK_PARAMS 128
00867663 2559 char stkbuf[STK_PARAMS] = {0};
e2fac8b1
A
2560 unsigned int size;
2561 caddr_t data, memp;
e2fac8b1
A
2562 /*
2563 * For this to work properly, we have to copy in the
2564 * ioctl() cmd argument if there is one; we must also
2565 * check that a command parameter, if present, does
2566 * not exceed the maximum command length dictated by
2567 * the number of bits we have available in the command
2568 * to represent a structure length. Finally, we have
2569 * to copy the results back out, if it is that type of
2570 * ioctl().
2571 */
2572 size = IOCPARM_LEN(uap->cmd);
2573 if (size > IOCPARM_MAX) {
2574 (void)vnode_put(vp);
2575 error = EINVAL;
2576 break;
2577 }
2578
e2fac8b1
A
2579 memp = NULL;
2580 if (size > sizeof (stkbuf)) {
2581 if ((memp = (caddr_t)kalloc(size)) == 0) {
2582 (void)vnode_put(vp);
2583 error = ENOMEM;
b0d623f7 2584 goto outdrop;
e2fac8b1
A
2585 }
2586 data = memp;
2587 } else {
2588 data = &stkbuf[0];
2589 }
39037602 2590
b0d623f7 2591 if (uap->cmd & IOC_IN) {
e2fac8b1
A
2592 if (size) {
2593 /* structure */
2594 error = copyin(argp, data, size);
2595 if (error) {
2596 (void)vnode_put(vp);
2597 if (memp)
2598 kfree(memp, size);
2599 goto outdrop;
2600 }
39236c6e
A
2601
2602 /* Bzero the section beyond that which was needed */
2603 if (size <= sizeof(stkbuf)) {
2604 bzero ( (((uint8_t*)data) + size), (sizeof(stkbuf) - size));
2605 }
e2fac8b1
A
2606 } else {
2607 /* int */
2608 if (is64bit) {
2609 *(user_addr_t *)data = argp;
2610 } else {
2611 *(uint32_t *)data = (uint32_t)argp;
2612 }
2613 };
b0d623f7 2614 } else if ((uap->cmd & IOC_OUT) && size) {
e2fac8b1
A
2615 /*
2616 * Zero the buffer so the user always
2617 * gets back something deterministic.
2618 */
2619 bzero(data, size);
b0d623f7 2620 } else if (uap->cmd & IOC_VOID) {
e2fac8b1
A
2621 if (is64bit) {
2622 *(user_addr_t *)data = argp;
2623 } else {
2624 *(uint32_t *)data = (uint32_t)argp;
2625 }
2626 }
2627
e2fac8b1 2628 error = VNOP_IOCTL(vp, uap->cmd, CAST_DOWN(caddr_t, data), 0, &context);
2d21ac55
A
2629
2630 (void)vnode_put(vp);
e2fac8b1
A
2631
2632 /* Copy any output data to user */
39037602 2633 if (error == 0 && (uap->cmd & IOC_OUT) && size)
e2fac8b1
A
2634 error = copyout(data, argp, size);
2635 if (memp)
2636 kfree(memp, size);
2d21ac55
A
2637 }
2638 break;
2d21ac55
A
2639 }
2640
2641outdrop:
2642 AUDIT_ARG(vnpath_withref, vp, ARG_VNODE1);
2643 fp_drop(p, fd, fp, 0);
2644 return(error);
2645out:
2646 fp_drop(p, fd, fp, 1);
2647 proc_fdunlock(p);
2648 return(error);
2649}
2650
2651
2652/*
2653 * finishdup
2654 *
2655 * Description: Common code for dup, dup2, and fcntl(F_DUPFD).
2656 *
2657 * Parameters: p Process performing the dup
2658 * old The fd to dup
2659 * new The fd to dup it to
6d2010ae 2660 * fd_flags Flags to augment the new fd
2d21ac55
A
2661 * retval Pointer to the call return area
2662 *
2663 * Returns: 0 Success
2664 * EBADF
2665 * ENOMEM
2666 *
2667 * Implicit returns:
2668 * *retval (modified) The new descriptor
2669 *
2670 * Locks: Assumes proc_fdlock for process pointing to fdp is held by
2671 * the caller
2672 *
2673 * Notes: This function may drop and reacquire this lock; it is unsafe
2674 * for a caller to assume that other state protected by the lock
6d2010ae 2675 * has not been subsequently changed out from under it.
2d21ac55
A
2676 */
2677int
6d2010ae
A
2678finishdup(proc_t p,
2679 struct filedesc *fdp, int old, int new, int fd_flags, int32_t *retval)
2d21ac55
A
2680{
2681 struct fileproc *nfp;
2682 struct fileproc *ofp;
2683#if CONFIG_MACF
2684 int error;
2685#endif
2686
2687#if DIAGNOSTIC
2688 proc_fdlock_assert(p, LCK_MTX_ASSERT_OWNED);
2689#endif
2d21ac55 2690 if ((ofp = fdp->fd_ofiles[old]) == NULL ||
6d2010ae 2691 (fdp->fd_ofileflags[old] & UF_RESERVED)) {
2d21ac55
A
2692 fdrelse(p, new);
2693 return (EBADF);
2694 }
2695 fg_ref(ofp);
2696
2697#if CONFIG_MACF
2698 error = mac_file_check_dup(proc_ucred(p), ofp->f_fglob, new);
2699 if (error) {
2700 fg_drop(ofp);
2701 fdrelse(p, new);
2702 return (error);
2703 }
2704#endif
2705
2706 proc_fdunlock(p);
91447636 2707
39236c6e 2708 nfp = fileproc_alloc_init(NULL);
91447636
A
2709
2710 proc_fdlock(p);
2d21ac55
A
2711
2712 if (nfp == NULL) {
2713 fg_drop(ofp);
2714 fdrelse(p, new);
2715 return (ENOMEM);
2716 }
2717
91447636 2718 nfp->f_fglob = ofp->f_fglob;
91447636 2719
2d21ac55
A
2720#if DIAGNOSTIC
2721 if (fdp->fd_ofiles[new] != 0)
6d2010ae 2722 panic("finishdup: overwriting fd_ofiles with new %d", new);
2d21ac55 2723 if ((fdp->fd_ofileflags[new] & UF_RESERVED) == 0)
6d2010ae 2724 panic("finishdup: unreserved fileflags with new %d", new);
2d21ac55
A
2725#endif
2726
1c79356b
A
2727 if (new > fdp->fd_lastfile)
2728 fdp->fd_lastfile = new;
6d2010ae 2729 *fdflags(p, new) |= fd_flags;
6601e61a 2730 procfdtbl_releasefd(p, new, nfp);
1c79356b
A
2731 *retval = new;
2732 return (0);
2733}
2734
91447636 2735
2d21ac55
A
2736/*
2737 * close
2738 *
2739 * Description: The implementation of the close(2) system call
2740 *
2741 * Parameters: p Process in whose per process file table
2742 * the close is to occur
2743 * uap->fd fd to be closed
2744 * retval <unused>
2745 *
2746 * Returns: 0 Success
2747 * fp_lookup:EBADF Bad file descriptor
39236c6e 2748 * fp_guard_exception:??? Guarded file descriptor
2d21ac55
A
2749 * close_internal:EBADF
2750 * close_internal:??? Anything returnable by a per-fileops
2751 * close function
2752 */
2753int
b0d623f7 2754close(proc_t p, struct close_args *uap, int32_t *retval)
2d21ac55
A
2755{
2756 __pthread_testcancel(1);
2757 return(close_nocancel(p, (struct close_nocancel_args *)uap, retval));
2758}
2759
2760
1c79356b 2761int
b0d623f7 2762close_nocancel(proc_t p, struct close_nocancel_args *uap, __unused int32_t *retval)
1c79356b 2763{
91447636 2764 struct fileproc *fp;
1c79356b 2765 int fd = uap->fd;
39236c6e 2766 int error;
1c79356b 2767
e5568f75 2768 AUDIT_SYSCLOSE(p, fd);
91447636
A
2769
2770 proc_fdlock(p);
2771
2772 if ( (error = fp_lookup(p,fd,&fp, 1)) ) {
2773 proc_fdunlock(p);
2774 return(error);
2775 }
2776
39236c6e
A
2777 if (FP_ISGUARDED(fp, GUARD_CLOSE)) {
2778 error = fp_guard_exception(p, fd, fp, kGUARD_EXC_CLOSE);
2779 (void) fp_drop(p, fd, fp, 1);
2780 proc_fdunlock(p);
2781 return (error);
2782 }
2783
2d21ac55 2784 error = close_internal_locked(p, fd, fp, 0);
91447636
A
2785
2786 proc_fdunlock(p);
2787
39236c6e 2788 return (error);
91447636
A
2789}
2790
2791
2792/*
2d21ac55
A
2793 * close_internal_locked
2794 *
91447636 2795 * Close a file descriptor.
2d21ac55
A
2796 *
2797 * Parameters: p Process in whose per process file table
2798 * the close is to occur
2799 * fd fd to be closed
2800 * fp fileproc associated with the fd
2801 *
2802 * Returns: 0 Success
2803 * EBADF fd already in close wait state
2804 * closef_locked:??? Anything returnable by a per-fileops
2805 * close function
2806 *
2807 * Locks: Assumes proc_fdlock for process is held by the caller and returns
2808 * with lock held
2809 *
2810 * Notes: This function may drop and reacquire this lock; it is unsafe
2811 * for a caller to assume that other state protected by the lock
39236c6e 2812 * has not been subsequently changed out from under it.
91447636 2813 */
39236c6e 2814int
2d21ac55 2815close_internal_locked(proc_t p, int fd, struct fileproc *fp, int flags)
91447636
A
2816{
2817 struct filedesc *fdp = p->p_fd;
2818 int error =0;
2d21ac55 2819 int resvfd = flags & FD_DUP2RESV;
91447636 2820
2d21ac55
A
2821
2822#if DIAGNOSTIC
2823 proc_fdlock_assert(p, LCK_MTX_ASSERT_OWNED);
2824#endif
55e303ae
A
2825
2826 /* Keep people from using the filedesc while we are closing it */
6601e61a 2827 procfdtbl_markclosefd(p, fd);
2d21ac55
A
2828
2829
6601e61a 2830 if ((fp->f_flags & FP_CLOSING) == FP_CLOSING) {
6d2010ae 2831 panic("close_internal_locked: being called on already closing fd");
6601e61a 2832 }
91447636
A
2833
2834
2d21ac55
A
2835#if DIAGNOSTIC
2836 if ((fdp->fd_ofileflags[fd] & UF_RESERVED) == 0)
6d2010ae 2837 panic("close_internal: unreserved fileflags with fd %d", fd);
2d21ac55 2838#endif
91447636
A
2839
2840 fp->f_flags |= FP_CLOSING;
91447636
A
2841
2842 if ( (fp->f_flags & FP_AIOISSUED) || kauth_authorize_fileop_has_listeners() ) {
2843
2844 proc_fdunlock(p);
2845
2846 if ( (fp->f_type == DTYPE_VNODE) && kauth_authorize_fileop_has_listeners() ) {
2847 /*
39037602 2848 * call out to allow 3rd party notification of close.
91447636
A
2849 * Ignore result of kauth_authorize_fileop call.
2850 */
2851 if (vnode_getwithref((vnode_t)fp->f_data) == 0) {
2852 u_int fileop_flags = 0;
2853 if ((fp->f_flags & FP_WRITTEN) != 0)
2854 fileop_flags |= KAUTH_FILEOP_CLOSE_MODIFIED;
39037602 2855 kauth_authorize_fileop(fp->f_fglob->fg_cred, KAUTH_FILEOP_CLOSE,
91447636
A
2856 (uintptr_t)fp->f_data, (uintptr_t)fileop_flags);
2857 vnode_put((vnode_t)fp->f_data);
2858 }
2859 }
2860 if (fp->f_flags & FP_AIOISSUED)
2861 /*
2862 * cancel all async IO requests that can be cancelled.
2863 */
2864 _aio_close( p, fd );
2865
2866 proc_fdlock(p);
2867 }
2868
2869 if (fd < fdp->fd_knlistsize)
39037602 2870 knote_fdclose(p, fd, FALSE);
55e303ae 2871
39037602 2872 if (fp->f_flags & FP_WAITEVENT)
91447636
A
2873 (void)waitevent_close(p, fp);
2874
39236c6e 2875 fileproc_drain(p, fp);
2d21ac55 2876
db609669 2877 if (resvfd == 0) {
6601e61a 2878 _fdrelse(p, fd);
db609669
A
2879 } else {
2880 procfdtbl_reservefd(p, fd);
2881 }
2d21ac55 2882
3e170ce0
A
2883 if (ENTR_SHOULDTRACE && fp->f_type == DTYPE_SOCKET)
2884 KERNEL_ENERGYTRACE(kEnTrActKernSocket, DBG_FUNC_END,
2885 fd, 0, (int64_t)VM_KERNEL_ADDRPERM(fp->f_data));
2886
91447636
A
2887 error = closef_locked(fp, fp->f_fglob, p);
2888 if ((fp->f_flags & FP_WAITCLOSE) == FP_WAITCLOSE)
2889 wakeup(&fp->f_flags);
2890 fp->f_flags &= ~(FP_WAITCLOSE | FP_CLOSING);
2891
2d21ac55
A
2892 proc_fdunlock(p);
2893
39037602 2894 fileproc_free(fp);
2d21ac55
A
2895
2896 proc_fdlock(p);
2897
2898#if DIAGNOSTIC
2899 if (resvfd != 0) {
2900 if ((fdp->fd_ofileflags[fd] & UF_RESERVED) == 0)
6d2010ae 2901 panic("close with reserved fd returns with freed fd:%d: proc: %p", fd, p);
2d21ac55
A
2902 }
2903#endif
91447636 2904
91447636 2905 return(error);
1c79356b
A
2906}
2907
2d21ac55 2908
1c79356b 2909/*
2d21ac55
A
2910 * fstat1
2911 *
2912 * Description: Return status information about a file descriptor.
2913 *
2914 * Parameters: p The process doing the fstat
2915 * fd The fd to stat
2916 * ub The user stat buffer
2917 * xsecurity The user extended security
2918 * buffer, or 0 if none
2919 * xsecurity_size The size of xsecurity, or 0
2920 * if no xsecurity
2921 * isstat64 Flag to indicate 64 bit version
2922 * for inode size, etc.
2923 *
2924 * Returns: 0 Success
2925 * EBADF
2926 * EFAULT
2927 * fp_lookup:EBADF Bad file descriptor
2928 * vnode_getwithref:???
2929 * copyout:EFAULT
2930 * vnode_getwithref:???
2931 * vn_stat:???
2932 * soo_stat:???
2933 * pipe_stat:???
2934 * pshm_stat:???
2935 * kqueue_stat:???
2936 *
2937 * Notes: Internal implementation for all other fstat() related
2938 * functions
91447636 2939 *
2d21ac55
A
2940 * XXX switch on node type is bogus; need a stat in struct
2941 * XXX fileops instead.
1c79356b 2942 */
91447636 2943static int
2d21ac55 2944fstat1(proc_t p, int fd, user_addr_t ub, user_addr_t xsecurity, user_addr_t xsecurity_size, int isstat64)
1c79356b 2945{
91447636 2946 struct fileproc *fp;
b0d623f7
A
2947 union {
2948 struct stat sb;
2949 struct stat64 sb64;
2950 } source;
2951 union {
2952 struct user64_stat user64_sb;
2953 struct user32_stat user32_sb;
2954 struct user64_stat64 user64_sb64;
2955 struct user32_stat64 user32_sb64;
2956 } dest;
91447636 2957 int error, my_size;
8f6c56a5 2958 file_type_t type;
91447636
A
2959 caddr_t data;
2960 kauth_filesec_t fsec;
2d21ac55
A
2961 user_size_t xsecurity_bufsize;
2962 vfs_context_t ctx = vfs_context_current();
2963 void * sbptr;
1c79356b 2964
91447636
A
2965
2966 AUDIT_ARG(fd, fd);
2967
2d21ac55 2968 if ((error = fp_lookup(p, fd, &fp, 0)) != 0) {
91447636 2969 return(error);
2d21ac55 2970 }
91447636
A
2971 type = fp->f_type;
2972 data = fp->f_data;
2973 fsec = KAUTH_FILESEC_NONE;
2974
b0d623f7 2975 sbptr = (void *)&source;
2d21ac55 2976
91447636 2977 switch (type) {
1c79356b
A
2978
2979 case DTYPE_VNODE:
91447636
A
2980 if ((error = vnode_getwithref((vnode_t)data)) == 0) {
2981 /*
2d21ac55
A
2982 * If the caller has the file open, and is not
2983 * requesting extended security information, we are
2984 * going to let them get the basic stat information.
91447636
A
2985 */
2986 if (xsecurity == USER_ADDR_NULL) {
743345f9
A
2987 error = vn_stat_noauth((vnode_t)data, sbptr, NULL, isstat64, ctx,
2988 fp->f_fglob->fg_cred);
91447636 2989 } else {
2d21ac55 2990 error = vn_stat((vnode_t)data, sbptr, &fsec, isstat64, ctx);
91447636
A
2991 }
2992
2993 AUDIT_ARG(vnpath, (struct vnode *)data, ARG_VNODE1);
2994 (void)vnode_put((vnode_t)data);
55e303ae 2995 }
1c79356b
A
2996 break;
2997
2d21ac55 2998#if SOCKETS
1c79356b 2999 case DTYPE_SOCKET:
2d21ac55 3000 error = soo_stat((struct socket *)data, sbptr, isstat64);
91447636 3001 break;
2d21ac55 3002#endif /* SOCKETS */
91447636
A
3003
3004 case DTYPE_PIPE:
2d21ac55 3005 error = pipe_stat((void *)data, sbptr, isstat64);
1c79356b
A
3006 break;
3007
3008 case DTYPE_PSXSHM:
2d21ac55 3009 error = pshm_stat((void *)data, sbptr, isstat64);
1c79356b 3010 break;
55e303ae
A
3011
3012 case DTYPE_KQUEUE:
fe8ab488 3013 error = kqueue_stat((void *)data, sbptr, isstat64, p);
91447636 3014 break;
55e303ae 3015
1c79356b 3016 default:
91447636
A
3017 error = EBADF;
3018 goto out;
3019 }
91447636
A
3020 if (error == 0) {
3021 caddr_t sbp;
2d21ac55
A
3022
3023 if (isstat64 != 0) {
b0d623f7
A
3024 source.sb64.st_lspare = 0;
3025 source.sb64.st_qspare[0] = 0LL;
3026 source.sb64.st_qspare[1] = 0LL;
3027
2d21ac55 3028 if (IS_64BIT_PROCESS(current_proc())) {
39037602 3029 munge_user64_stat64(&source.sb64, &dest.user64_sb64);
b0d623f7
A
3030 my_size = sizeof(dest.user64_sb64);
3031 sbp = (caddr_t)&dest.user64_sb64;
2d21ac55 3032 } else {
39037602 3033 munge_user32_stat64(&source.sb64, &dest.user32_sb64);
b0d623f7
A
3034 my_size = sizeof(dest.user32_sb64);
3035 sbp = (caddr_t)&dest.user32_sb64;
2d21ac55
A
3036 }
3037 } else {
b0d623f7
A
3038 source.sb.st_lspare = 0;
3039 source.sb.st_qspare[0] = 0LL;
3040 source.sb.st_qspare[1] = 0LL;
2d21ac55 3041 if (IS_64BIT_PROCESS(current_proc())) {
39037602 3042 munge_user64_stat(&source.sb, &dest.user64_sb);
b0d623f7
A
3043 my_size = sizeof(dest.user64_sb);
3044 sbp = (caddr_t)&dest.user64_sb;
2d21ac55 3045 } else {
39037602 3046 munge_user32_stat(&source.sb, &dest.user32_sb);
b0d623f7
A
3047 my_size = sizeof(dest.user32_sb);
3048 sbp = (caddr_t)&dest.user32_sb;
2d21ac55 3049 }
91447636 3050 }
2d21ac55 3051
91447636 3052 error = copyout(sbp, ub, my_size);
1c79356b 3053 }
1c79356b 3054
91447636
A
3055 /* caller wants extended security information? */
3056 if (xsecurity != USER_ADDR_NULL) {
1c79356b 3057
91447636
A
3058 /* did we get any? */
3059 if (fsec == KAUTH_FILESEC_NONE) {
3060 if (susize(xsecurity_size, 0) != 0) {
3061 error = EFAULT;
3062 goto out;
3063 }
3064 } else {
3065 /* find the user buffer size */
3066 xsecurity_bufsize = fusize(xsecurity_size);
1c79356b 3067
91447636
A
3068 /* copy out the actual data size */
3069 if (susize(xsecurity_size, KAUTH_FILESEC_COPYSIZE(fsec)) != 0) {
3070 error = EFAULT;
3071 goto out;
3072 }
1c79356b 3073
91447636
A
3074 /* if the caller supplied enough room, copy out to it */
3075 if (xsecurity_bufsize >= KAUTH_FILESEC_COPYSIZE(fsec))
3076 error = copyout(fsec, xsecurity, KAUTH_FILESEC_COPYSIZE(fsec));
3077 }
1c79356b 3078 }
91447636
A
3079out:
3080 fp_drop(p, fd, fp, 0);
3081 if (fsec != NULL)
3082 kauth_filesec_free(fsec);
1c79356b
A
3083 return (error);
3084}
91447636 3085
2d21ac55
A
3086
3087/*
3088 * fstat_extended
3089 *
3090 * Description: Extended version of fstat supporting returning extended
3091 * security information
3092 *
3093 * Parameters: p The process doing the fstat
3094 * uap->fd The fd to stat
3095 * uap->ub The user stat buffer
3096 * uap->xsecurity The user extended security
3097 * buffer, or 0 if none
3098 * uap->xsecurity_size The size of xsecurity, or 0
3099 *
3100 * Returns: 0 Success
3101 * !0 Errno (see fstat1)
3102 */
91447636 3103int
b0d623f7 3104fstat_extended(proc_t p, struct fstat_extended_args *uap, __unused int32_t *retval)
91447636 3105{
2d21ac55 3106 return(fstat1(p, uap->fd, uap->ub, uap->xsecurity, uap->xsecurity_size, 0));
91447636 3107}
39037602 3108
2d21ac55
A
3109
3110/*
3111 * fstat
3112 *
3113 * Description: Get file status for the file associated with fd
3114 *
3115 * Parameters: p The process doing the fstat
3116 * uap->fd The fd to stat
3117 * uap->ub The user stat buffer
3118 *
3119 * Returns: 0 Success
3120 * !0 Errno (see fstat1)
3121 */
3122int
39037602 3123fstat(proc_t p, struct fstat_args *uap, __unused int32_t *retval)
2d21ac55
A
3124{
3125 return(fstat1(p, uap->fd, uap->ub, 0, 0, 0));
3126}
3127
3128
3129/*
3130 * fstat64_extended
3131 *
3132 * Description: Extended version of fstat64 supporting returning extended
3133 * security information
3134 *
3135 * Parameters: p The process doing the fstat
3136 * uap->fd The fd to stat
3137 * uap->ub The user stat buffer
3138 * uap->xsecurity The user extended security
3139 * buffer, or 0 if none
3140 * uap->xsecurity_size The size of xsecurity, or 0
3141 *
3142 * Returns: 0 Success
3143 * !0 Errno (see fstat1)
3144 */
3145int
b0d623f7 3146fstat64_extended(proc_t p, struct fstat64_extended_args *uap, __unused int32_t *retval)
2d21ac55
A
3147{
3148 return(fstat1(p, uap->fd, uap->ub, uap->xsecurity, uap->xsecurity_size, 1));
3149}
39037602 3150
2d21ac55
A
3151
3152/*
3153 * fstat64
3154 *
3155 * Description: Get 64 bit version of the file status for the file associated
3156 * with fd
3157 *
3158 * Parameters: p The process doing the fstat
3159 * uap->fd The fd to stat
3160 * uap->ub The user stat buffer
3161 *
3162 * Returns: 0 Success
3163 * !0 Errno (see fstat1)
3164 */
91447636 3165int
39037602 3166fstat64(proc_t p, struct fstat64_args *uap, __unused int32_t *retval)
91447636 3167{
2d21ac55 3168 return(fstat1(p, uap->fd, uap->ub, 0, 0, 1));
91447636 3169}
1c79356b 3170
2d21ac55 3171
1c79356b 3172/*
2d21ac55
A
3173 * fpathconf
3174 *
3175 * Description: Return pathconf information about a file descriptor.
3176 *
3177 * Parameters: p Process making the request
3178 * uap->fd fd to get information about
3179 * uap->name Name of information desired
3180 * retval Pointer to the call return area
3181 *
3182 * Returns: 0 Success
3183 * EINVAL
3184 * fp_lookup:EBADF Bad file descriptor
3185 * vnode_getwithref:???
3186 * vn_pathconf:???
3187 *
3188 * Implicit returns:
3189 * *retval (modified) Returned information (numeric)
1c79356b 3190 */
91447636 3191int
b0d623f7 3192fpathconf(proc_t p, struct fpathconf_args *uap, int32_t *retval)
1c79356b
A
3193{
3194 int fd = uap->fd;
91447636 3195 struct fileproc *fp;
1c79356b 3196 struct vnode *vp;
91447636 3197 int error = 0;
8f6c56a5 3198 file_type_t type;
91447636
A
3199 caddr_t data;
3200
1c79356b 3201
55e303ae 3202 AUDIT_ARG(fd, uap->fd);
91447636
A
3203 if ( (error = fp_lookup(p, fd, &fp, 0)) )
3204 return(error);
3205 type = fp->f_type;
3206 data = fp->f_data;
3207
3208 switch (type) {
1c79356b
A
3209
3210 case DTYPE_SOCKET:
b0d623f7
A
3211 if (uap->name != _PC_PIPE_BUF) {
3212 error = EINVAL;
91447636
A
3213 goto out;
3214 }
1c79356b 3215 *retval = PIPE_BUF;
91447636
A
3216 error = 0;
3217 goto out;
3218
3219 case DTYPE_PIPE:
b0d623f7
A
3220 if (uap->name != _PC_PIPE_BUF) {
3221 error = EINVAL;
3222 goto out;
3223 }
3224 *retval = PIPE_BUF;
91447636
A
3225 error = 0;
3226 goto out;
1c79356b
A
3227
3228 case DTYPE_VNODE:
91447636
A
3229 vp = (struct vnode *)data;
3230
3231 if ( (error = vnode_getwithref(vp)) == 0) {
3232 AUDIT_ARG(vnpath, vp, ARG_VNODE1);
3233
2d21ac55 3234 error = vn_pathconf(vp, uap->name, retval, vfs_context_current());
91447636
A
3235
3236 (void)vnode_put(vp);
3237 }
3238 goto out;
55e303ae 3239
39236c6e 3240 default:
91447636
A
3241 error = EINVAL;
3242 goto out;
1c79356b 3243
1c79356b
A
3244 }
3245 /*NOTREACHED*/
91447636
A
3246out:
3247 fp_drop(p, fd, fp, 0);
3248 return(error);
1c79356b
A
3249}
3250
3251/*
2d21ac55
A
3252 * Statistics counter for the number of times a process calling fdalloc()
3253 * has resulted in an expansion of the per process open file table.
3254 *
3255 * XXX This would likely be of more use if it were per process
1c79356b
A
3256 */
3257int fdexpand;
3258
2d21ac55
A
3259
3260/*
3261 * fdalloc
3262 *
3263 * Description: Allocate a file descriptor for the process.
3264 *
3265 * Parameters: p Process to allocate the fd in
3266 * want The fd we would prefer to get
3267 * result Pointer to fd we got
3268 *
3269 * Returns: 0 Success
3270 * EMFILE
3271 * ENOMEM
3272 *
3273 * Implicit returns:
3274 * *result (modified) The fd which was allocated
3275 */
1c79356b 3276int
2d21ac55 3277fdalloc(proc_t p, int want, int *result)
1c79356b 3278{
2d21ac55
A
3279 struct filedesc *fdp = p->p_fd;
3280 int i;
91447636
A
3281 int lim, last, numfiles, oldnfiles;
3282 struct fileproc **newofiles, **ofiles;
6601e61a 3283 char *newofileflags;
1c79356b
A
3284
3285 /*
3286 * Search for a free descriptor starting at the higher
3287 * of want or fd_freefile. If that fails, consider
3288 * expanding the ofile array.
3289 */
2d21ac55
A
3290#if DIAGNOSTIC
3291 proc_fdlock_assert(p, LCK_MTX_ASSERT_OWNED);
3292#endif
3293
1c79356b
A
3294 lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
3295 for (;;) {
3296 last = min(fdp->fd_nfiles, lim);
3297 if ((i = want) < fdp->fd_freefile)
3298 i = fdp->fd_freefile;
1c79356b 3299 for (; i < last; i++) {
6601e61a
A
3300 if (fdp->fd_ofiles[i] == NULL && !(fdp->fd_ofileflags[i] & UF_RESERVED)) {
3301 procfdtbl_reservefd(p, i);
1c79356b
A
3302 if (i > fdp->fd_lastfile)
3303 fdp->fd_lastfile = i;
3304 if (want <= fdp->fd_freefile)
3305 fdp->fd_freefile = i;
3306 *result = i;
3307 return (0);
3308 }
1c79356b
A
3309 }
3310
3311 /*
3312 * No space in current array. Expand?
3313 */
3314 if (fdp->fd_nfiles >= lim)
3315 return (EMFILE);
3316 if (fdp->fd_nfiles < NDEXTENT)
91447636 3317 numfiles = NDEXTENT;
1c79356b 3318 else
91447636 3319 numfiles = 2 * fdp->fd_nfiles;
1c79356b 3320 /* Enforce lim */
91447636
A
3321 if (numfiles > lim)
3322 numfiles = lim;
3323 proc_fdunlock(p);
3324 MALLOC_ZONE(newofiles, struct fileproc **,
3325 numfiles * OFILESIZE, M_OFILETABL, M_WAITOK);
3326 proc_fdlock(p);
3327 if (newofiles == NULL) {
3328 return (ENOMEM);
3329 }
3330 if (fdp->fd_nfiles >= numfiles) {
3331 FREE_ZONE(newofiles, numfiles * OFILESIZE, M_OFILETABL);
1c79356b
A
3332 continue;
3333 }
91447636 3334 newofileflags = (char *) &newofiles[numfiles];
1c79356b
A
3335 /*
3336 * Copy the existing ofile and ofileflags arrays
3337 * and zero the new portion of each array.
3338 */
3339 oldnfiles = fdp->fd_nfiles;
3340 (void) memcpy(newofiles, fdp->fd_ofiles,
2d21ac55 3341 oldnfiles * sizeof(*fdp->fd_ofiles));
1c79356b 3342 (void) memset(&newofiles[oldnfiles], 0,
2d21ac55 3343 (numfiles - oldnfiles) * sizeof(*fdp->fd_ofiles));
1c79356b
A
3344
3345 (void) memcpy(newofileflags, fdp->fd_ofileflags,
2d21ac55 3346 oldnfiles * sizeof(*fdp->fd_ofileflags));
1c79356b 3347 (void) memset(&newofileflags[oldnfiles], 0,
91447636 3348 (numfiles - oldnfiles) *
2d21ac55 3349 sizeof(*fdp->fd_ofileflags));
1c79356b
A
3350 ofiles = fdp->fd_ofiles;
3351 fdp->fd_ofiles = newofiles;
3352 fdp->fd_ofileflags = newofileflags;
91447636 3353 fdp->fd_nfiles = numfiles;
1c79356b
A
3354 FREE_ZONE(ofiles, oldnfiles * OFILESIZE, M_OFILETABL);
3355 fdexpand++;
3356 }
3357}
3358
2d21ac55 3359
91447636 3360/*
2d21ac55
A
3361 * fdavail
3362 *
3363 * Description: Check to see whether n user file descriptors are available
3364 * to the process p.
3365 *
3366 * Parameters: p Process to check in
3367 * n The number of fd's desired
3368 *
3369 * Returns: 0 No
3370 * 1 Yes
3371 *
3372 * Locks: Assumes proc_fdlock for process is held by the caller
3373 *
3374 * Notes: The answer only remains valid so long as the proc_fdlock is
3375 * held by the caller.
91447636
A
3376 */
3377int
2d21ac55 3378fdavail(proc_t p, int n)
91447636
A
3379{
3380 struct filedesc *fdp = p->p_fd;
3381 struct fileproc **fpp;
3382 char *flags;
3383 int i, lim;
3384
3385 lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
3386 if ((i = lim - fdp->fd_nfiles) > 0 && (n -= i) <= 0)
3387 return (1);
3388 fpp = &fdp->fd_ofiles[fdp->fd_freefile];
3389 flags = &fdp->fd_ofileflags[fdp->fd_freefile];
3390 for (i = fdp->fd_nfiles - fdp->fd_freefile; --i >= 0; fpp++, flags++)
3391 if (*fpp == NULL && !(*flags & UF_RESERVED) && --n <= 0)
3392 return (1);
3393 return (0);
3394}
3395
91447636 3396
2d21ac55
A
3397/*
3398 * fdrelse
3399 *
3400 * Description: Legacy KPI wrapper function for _fdrelse
3401 *
3402 * Parameters: p Process in which fd lives
3403 * fd fd to free
3404 *
3405 * Returns: void
3406 *
3407 * Locks: Assumes proc_fdlock for process is held by the caller
3408 */
91447636 3409void
2d21ac55 3410fdrelse(proc_t p, int fd)
91447636 3411{
2d21ac55 3412 _fdrelse(p, fd);
91447636
A
3413}
3414
3415
2d21ac55
A
3416/*
3417 * fdgetf_noref
3418 *
3419 * Description: Get the fileproc pointer for the given fd from the per process
3420 * open file table without taking an explicit reference on it.
3421 *
3422 * Parameters: p Process containing fd
3423 * fd fd to obtain fileproc for
3424 * resultfp Pointer to pointer return area
3425 *
3426 * Returns: 0 Success
3427 * EBADF
3428 *
3429 * Implicit returns:
3430 * *resultfp (modified) Pointer to fileproc pointer
3431 *
3432 * Locks: Assumes proc_fdlock for process is held by the caller
3433 *
3434 * Notes: Because there is no reference explicitly taken, the returned
3435 * fileproc pointer is only valid so long as the proc_fdlock
3436 * remains held by the caller.
3437 */
91447636 3438int
2d21ac55 3439fdgetf_noref(proc_t p, int fd, struct fileproc **resultfp)
91447636
A
3440{
3441 struct filedesc *fdp = p->p_fd;
3442 struct fileproc *fp;
3443
3444 if (fd < 0 || fd >= fdp->fd_nfiles ||
3445 (fp = fdp->fd_ofiles[fd]) == NULL ||
3446 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
3447 return (EBADF);
3448 }
3449 if (resultfp)
3450 *resultfp = fp;
3451 return (0);
3452}
3453
3454
2d21ac55
A
3455/*
3456 * fp_getfvp
3457 *
3458 * Description: Get fileproc and vnode pointer for a given fd from the per
3459 * process open file table of the specified process, and if
3460 * successful, increment the f_iocount
3461 *
3462 * Parameters: p Process in which fd lives
3463 * fd fd to get information for
3464 * resultfp Pointer to result fileproc
3465 * pointer area, or 0 if none
3466 * resultvp Pointer to result vnode pointer
3467 * area, or 0 if none
3468 *
3469 * Returns: 0 Success
3470 * EBADF Bad file descriptor
3471 * ENOTSUP fd does not refer to a vnode
3472 *
3473 * Implicit returns:
3474 * *resultfp (modified) Fileproc pointer
3475 * *resultvp (modified) vnode pointer
3476 *
3477 * Notes: The resultfp and resultvp fields are optional, and may be
3478 * independently specified as NULL to skip returning information
3479 *
3480 * Locks: Internally takes and releases proc_fdlock
3481 */
91447636 3482int
2d21ac55 3483fp_getfvp(proc_t p, int fd, struct fileproc **resultfp, struct vnode **resultvp)
91447636
A
3484{
3485 struct filedesc *fdp = p->p_fd;
3486 struct fileproc *fp;
3487
2d21ac55 3488 proc_fdlock_spin(p);
91447636
A
3489 if (fd < 0 || fd >= fdp->fd_nfiles ||
3490 (fp = fdp->fd_ofiles[fd]) == NULL ||
3491 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
3492 proc_fdunlock(p);
3493 return (EBADF);
3494 }
3495 if (fp->f_type != DTYPE_VNODE) {
3496 proc_fdunlock(p);
3497 return(ENOTSUP);
3498 }
3499 fp->f_iocount++;
3500
3501 if (resultfp)
3502 *resultfp = fp;
3503 if (resultvp)
3504 *resultvp = (struct vnode *)fp->f_data;
3505 proc_fdunlock(p);
3506
3507 return (0);
3508}
3509
3510
2d21ac55
A
3511/*
3512 * fp_getfvpandvid
3513 *
3514 * Description: Get fileproc, vnode pointer, and vid for a given fd from the
3515 * per process open file table of the specified process, and if
3516 * successful, increment the f_iocount
3517 *
3518 * Parameters: p Process in which fd lives
3519 * fd fd to get information for
3520 * resultfp Pointer to result fileproc
3521 * pointer area, or 0 if none
3522 * resultvp Pointer to result vnode pointer
3523 * area, or 0 if none
3524 * vidp Pointer to resuld vid area
3525 *
3526 * Returns: 0 Success
3527 * EBADF Bad file descriptor
3528 * ENOTSUP fd does not refer to a vnode
3529 *
3530 * Implicit returns:
3531 * *resultfp (modified) Fileproc pointer
3532 * *resultvp (modified) vnode pointer
3533 * *vidp vid value
3534 *
3535 * Notes: The resultfp and resultvp fields are optional, and may be
3536 * independently specified as NULL to skip returning information
3537 *
3538 * Locks: Internally takes and releases proc_fdlock
3539 */
0c530ab8 3540int
2d21ac55
A
3541fp_getfvpandvid(proc_t p, int fd, struct fileproc **resultfp,
3542 struct vnode **resultvp, uint32_t *vidp)
0c530ab8
A
3543{
3544 struct filedesc *fdp = p->p_fd;
3545 struct fileproc *fp;
3546
2d21ac55 3547 proc_fdlock_spin(p);
0c530ab8
A
3548 if (fd < 0 || fd >= fdp->fd_nfiles ||
3549 (fp = fdp->fd_ofiles[fd]) == NULL ||
3550 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
3551 proc_fdunlock(p);
3552 return (EBADF);
3553 }
3554 if (fp->f_type != DTYPE_VNODE) {
3555 proc_fdunlock(p);
3556 return(ENOTSUP);
3557 }
3558 fp->f_iocount++;
3559
3560 if (resultfp)
3561 *resultfp = fp;
3562 if (resultvp)
3563 *resultvp = (struct vnode *)fp->f_data;
3564 if (vidp)
3565 *vidp = (uint32_t)vnode_vid((struct vnode *)fp->f_data);
3566 proc_fdunlock(p);
3567
3568 return (0);
3569}
3570
2d21ac55 3571
91447636 3572/*
2d21ac55
A
3573 * fp_getfsock
3574 *
3575 * Description: Get fileproc and socket pointer for a given fd from the
3576 * per process open file table of the specified process, and if
3577 * successful, increment the f_iocount
3578 *
3579 * Parameters: p Process in which fd lives
3580 * fd fd to get information for
3581 * resultfp Pointer to result fileproc
3582 * pointer area, or 0 if none
3583 * results Pointer to result socket
3584 * pointer area, or 0 if none
3585 *
91447636
A
3586 * Returns: EBADF The file descriptor is invalid
3587 * EOPNOTSUPP The file descriptor is not a socket
3588 * 0 Success
3589 *
2d21ac55
A
3590 * Implicit returns:
3591 * *resultfp (modified) Fileproc pointer
3592 * *results (modified) socket pointer
3593 *
91447636
A
3594 * Notes: EOPNOTSUPP should probably be ENOTSOCK; this function is only
3595 * ever called from accept1().
3596 */
3597int
2d21ac55
A
3598fp_getfsock(proc_t p, int fd, struct fileproc **resultfp,
3599 struct socket **results)
91447636
A
3600{
3601 struct filedesc *fdp = p->p_fd;
3602 struct fileproc *fp;
3603
2d21ac55 3604 proc_fdlock_spin(p);
91447636
A
3605 if (fd < 0 || fd >= fdp->fd_nfiles ||
3606 (fp = fdp->fd_ofiles[fd]) == NULL ||
3607 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
3608 proc_fdunlock(p);
3609 return (EBADF);
3610 }
3611 if (fp->f_type != DTYPE_SOCKET) {
3612 proc_fdunlock(p);
3613 return(EOPNOTSUPP);
3614 }
3615 fp->f_iocount++;
3616
3617 if (resultfp)
3618 *resultfp = fp;
3619 if (results)
3620 *results = (struct socket *)fp->f_data;
3621 proc_fdunlock(p);
3622
3623 return (0);
3624}
3625
3626
2d21ac55
A
3627/*
3628 * fp_getfkq
3629 *
3630 * Description: Get fileproc and kqueue pointer for a given fd from the
3631 * per process open file table of the specified process, and if
3632 * successful, increment the f_iocount
3633 *
3634 * Parameters: p Process in which fd lives
3635 * fd fd to get information for
3636 * resultfp Pointer to result fileproc
3637 * pointer area, or 0 if none
3638 * resultkq Pointer to result kqueue
3639 * pointer area, or 0 if none
3640 *
3641 * Returns: EBADF The file descriptor is invalid
3642 * EBADF The file descriptor is not a socket
3643 * 0 Success
3644 *
3645 * Implicit returns:
3646 * *resultfp (modified) Fileproc pointer
3647 * *resultkq (modified) kqueue pointer
3648 *
3649 * Notes: The second EBADF should probably be something else to make
3650 * the error condition distinct.
3651 */
91447636 3652int
2d21ac55
A
3653fp_getfkq(proc_t p, int fd, struct fileproc **resultfp,
3654 struct kqueue **resultkq)
91447636
A
3655{
3656 struct filedesc *fdp = p->p_fd;
3657 struct fileproc *fp;
3658
2d21ac55 3659 proc_fdlock_spin(p);
91447636
A
3660 if ( fd < 0 || fd >= fdp->fd_nfiles ||
3661 (fp = fdp->fd_ofiles[fd]) == NULL ||
3662 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
3663 proc_fdunlock(p);
3664 return (EBADF);
3665 }
3666 if (fp->f_type != DTYPE_KQUEUE) {
3667 proc_fdunlock(p);
3668 return(EBADF);
3669 }
3670 fp->f_iocount++;
3671
3672 if (resultfp)
3673 *resultfp = fp;
3674 if (resultkq)
3675 *resultkq = (struct kqueue *)fp->f_data;
3676 proc_fdunlock(p);
3677
3678 return (0);
3679}
3680
2d21ac55
A
3681
3682/*
3683 * fp_getfpshm
3684 *
3685 * Description: Get fileproc and POSIX shared memory pointer for a given fd
3686 * from the per process open file table of the specified process
3687 * and if successful, increment the f_iocount
3688 *
3689 * Parameters: p Process in which fd lives
3690 * fd fd to get information for
3691 * resultfp Pointer to result fileproc
3692 * pointer area, or 0 if none
3693 * resultpshm Pointer to result POSIX
3694 * shared memory pointer
3695 * pointer area, or 0 if none
3696 *
3697 * Returns: EBADF The file descriptor is invalid
3698 * EBADF The file descriptor is not a POSIX
3699 * shared memory area
3700 * 0 Success
3701 *
3702 * Implicit returns:
3703 * *resultfp (modified) Fileproc pointer
3704 * *resultpshm (modified) POSIX shared memory pointer
3705 *
3706 * Notes: The second EBADF should probably be something else to make
3707 * the error condition distinct.
3708 */
91447636 3709int
2d21ac55
A
3710fp_getfpshm(proc_t p, int fd, struct fileproc **resultfp,
3711 struct pshmnode **resultpshm)
91447636
A
3712{
3713 struct filedesc *fdp = p->p_fd;
3714 struct fileproc *fp;
3715
2d21ac55 3716 proc_fdlock_spin(p);
91447636
A
3717 if (fd < 0 || fd >= fdp->fd_nfiles ||
3718 (fp = fdp->fd_ofiles[fd]) == NULL ||
3719 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
3720 proc_fdunlock(p);
3721 return (EBADF);
3722 }
3723 if (fp->f_type != DTYPE_PSXSHM) {
3724
3725 proc_fdunlock(p);
3726 return(EBADF);
3727 }
3728 fp->f_iocount++;
3729
3730 if (resultfp)
3731 *resultfp = fp;
3732 if (resultpshm)
3733 *resultpshm = (struct pshmnode *)fp->f_data;
3734 proc_fdunlock(p);
3735
3736 return (0);
3737}
3738
3739
2d21ac55
A
3740/*
3741 * fp_getfsem
3742 *
3743 * Description: Get fileproc and POSIX semaphore pointer for a given fd from
3744 * the per process open file table of the specified process
3745 * and if successful, increment the f_iocount
3746 *
3747 * Parameters: p Process in which fd lives
3748 * fd fd to get information for
3749 * resultfp Pointer to result fileproc
3750 * pointer area, or 0 if none
3751 * resultpsem Pointer to result POSIX
3752 * semaphore pointer area, or
3753 * 0 if none
3754 *
3755 * Returns: EBADF The file descriptor is invalid
3756 * EBADF The file descriptor is not a POSIX
3757 * semaphore
3758 * 0 Success
3759 *
3760 * Implicit returns:
3761 * *resultfp (modified) Fileproc pointer
3762 * *resultpsem (modified) POSIX semaphore pointer
3763 *
3764 * Notes: The second EBADF should probably be something else to make
3765 * the error condition distinct.
3766 *
3767 * In order to support unnamed POSIX semaphores, the named
3768 * POSIX semaphores will have to move out of the per-process
3769 * open filetable, and into a global table that is shared with
3770 * unnamed POSIX semaphores, since unnamed POSIX semaphores
3771 * are typically used by declaring instances in shared memory,
3772 * and there's no other way to do this without changing the
3773 * underlying type, which would introduce binary compatibility
3774 * issues.
3775 */
91447636 3776int
2d21ac55
A
3777fp_getfpsem(proc_t p, int fd, struct fileproc **resultfp,
3778 struct psemnode **resultpsem)
91447636
A
3779{
3780 struct filedesc *fdp = p->p_fd;
3781 struct fileproc *fp;
3782
2d21ac55 3783 proc_fdlock_spin(p);
91447636
A
3784 if (fd < 0 || fd >= fdp->fd_nfiles ||
3785 (fp = fdp->fd_ofiles[fd]) == NULL ||
3786 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
3787 proc_fdunlock(p);
3788 return (EBADF);
3789 }
3790 if (fp->f_type != DTYPE_PSXSEM) {
3791 proc_fdunlock(p);
3792 return(EBADF);
3793 }
3794 fp->f_iocount++;
3795
3796 if (resultfp)
3797 *resultfp = fp;
3798 if (resultpsem)
3799 *resultpsem = (struct psemnode *)fp->f_data;
3800 proc_fdunlock(p);
3801
3802 return (0);
3803}
0c530ab8
A
3804
3805
2d21ac55
A
3806/*
3807 * fp_getfpipe
3808 *
3809 * Description: Get fileproc and pipe pointer for a given fd from the
3810 * per process open file table of the specified process
3811 * and if successful, increment the f_iocount
3812 *
3813 * Parameters: p Process in which fd lives
3814 * fd fd to get information for
3815 * resultfp Pointer to result fileproc
3816 * pointer area, or 0 if none
3817 * resultpipe Pointer to result pipe
3818 * pointer area, or 0 if none
3819 *
3820 * Returns: EBADF The file descriptor is invalid
3821 * EBADF The file descriptor is not a socket
3822 * 0 Success
3823 *
3824 * Implicit returns:
3825 * *resultfp (modified) Fileproc pointer
3826 * *resultpipe (modified) pipe pointer
3827 *
3828 * Notes: The second EBADF should probably be something else to make
3829 * the error condition distinct.
3830 */
0c530ab8 3831int
2d21ac55
A
3832fp_getfpipe(proc_t p, int fd, struct fileproc **resultfp,
3833 struct pipe **resultpipe)
0c530ab8
A
3834{
3835 struct filedesc *fdp = p->p_fd;
3836 struct fileproc *fp;
3837
2d21ac55 3838 proc_fdlock_spin(p);
0c530ab8
A
3839 if (fd < 0 || fd >= fdp->fd_nfiles ||
3840 (fp = fdp->fd_ofiles[fd]) == NULL ||
3841 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
3842 proc_fdunlock(p);
3843 return (EBADF);
3844 }
3845 if (fp->f_type != DTYPE_PIPE) {
3846 proc_fdunlock(p);
3847 return(EBADF);
3848 }
3849 fp->f_iocount++;
3850
3851 if (resultfp)
3852 *resultfp = fp;
3853 if (resultpipe)
3854 *resultpipe = (struct pipe *)fp->f_data;
3855 proc_fdunlock(p);
3856
3857 return (0);
3858}
3859
39037602 3860
2d21ac55
A
3861/*
3862 * fp_lookup
3863 *
3864 * Description: Get fileproc pointer for a given fd from the per process
3865 * open file table of the specified process and if successful,
3866 * increment the f_iocount
3867 *
3868 * Parameters: p Process in which fd lives
3869 * fd fd to get information for
3870 * resultfp Pointer to result fileproc
3871 * pointer area, or 0 if none
3872 * locked !0 if the caller holds the
3873 * proc_fdlock, 0 otherwise
3874 *
3875 * Returns: 0 Success
3876 * EBADF Bad file descriptor
3877 *
3878 * Implicit returns:
3879 * *resultfp (modified) Fileproc pointer
3880 *
3881 * Locks: If the argument 'locked' is non-zero, then the caller is
3882 * expected to have taken and held the proc_fdlock; if it is
3883 * zero, than this routine internally takes and drops this lock.
3884 */
91447636 3885int
2d21ac55 3886fp_lookup(proc_t p, int fd, struct fileproc **resultfp, int locked)
91447636
A
3887{
3888 struct filedesc *fdp = p->p_fd;
3889 struct fileproc *fp;
3890
3891 if (!locked)
2d21ac55
A
3892 proc_fdlock_spin(p);
3893 if (fd < 0 || fdp == NULL || fd >= fdp->fd_nfiles ||
91447636
A
3894 (fp = fdp->fd_ofiles[fd]) == NULL ||
3895 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
3896 if (!locked)
3897 proc_fdunlock(p);
3898 return (EBADF);
3899 }
3900 fp->f_iocount++;
3901
3902 if (resultfp)
3903 *resultfp = fp;
3904 if (!locked)
3905 proc_fdunlock(p);
39037602 3906
91447636
A
3907 return (0);
3908}
3909
2d21ac55 3910
39236c6e
A
3911/*
3912 * fp_tryswap
39037602 3913 *
39236c6e
A
3914 * Description: Swap the fileproc pointer for a given fd with a new
3915 * fileproc pointer in the per-process open file table of
3916 * the specified process. The fdlock must be held at entry.
3917 *
3918 * Parameters: p Process containing the fd
3919 * fd The fd of interest
3920 * nfp Pointer to the newfp
3921 *
3922 * Returns: 0 Success
3923 * EBADF Bad file descriptor
3924 * EINTR Interrupted
3925 * EKEEPLOOKING f_iocount changed while lock was dropped.
3926 */
3927int
3928fp_tryswap(proc_t p, int fd, struct fileproc *nfp)
3929{
3930 struct fileproc *fp;
3931 int error;
3932
3933 proc_fdlock_assert(p, LCK_MTX_ASSERT_OWNED);
3934
3935 if (0 != (error = fp_lookup(p, fd, &fp, 1)))
3936 return (error);
3937 /*
3938 * At this point, our caller (change_guardedfd_np) has
3939 * one f_iocount reference, and we just took another
3940 * one to begin the replacement.
3941 */
3942 if (fp->f_iocount < 2) {
3943 panic("f_iocount too small %d", fp->f_iocount);
3944 } else if (2 == fp->f_iocount) {
3945
3946 /* Copy the contents of *fp, preserving the "type" of *nfp */
3947
3948 nfp->f_flags = (nfp->f_flags & FP_TYPEMASK) |
3949 (fp->f_flags & ~FP_TYPEMASK);
3950 nfp->f_iocount = fp->f_iocount;
3951 nfp->f_fglob = fp->f_fglob;
3e170ce0 3952 nfp->f_wset = fp->f_wset;
39236c6e
A
3953
3954 p->p_fd->fd_ofiles[fd] = nfp;
3955 (void) fp_drop(p, fd, nfp, 1);
3956 } else {
3957 /*
3958 * Wait for all other active references to evaporate.
3959 */
3960 p->p_fpdrainwait = 1;
3961 error = msleep(&p->p_fpdrainwait, &p->p_fdmlock,
3962 PRIBIO | PCATCH, "tryswap fpdrain", NULL);
3963 if (0 == error) {
3964 /*
3965 * Return an "internal" errno to trigger a full
3966 * reevaluation of the change-guard attempt.
3967 */
3968 error = EKEEPLOOKING;
3969 printf("%s: lookup collision fd %d\n", __func__, fd);
3970 }
3971 (void) fp_drop(p, fd, fp, 1);
3972 }
3973 return (error);
3974}
3975
3976
2d21ac55
A
3977/*
3978 * fp_drop_written
3979 *
3980 * Description: Set the FP_WRITTEN flag on the fileproc and drop the I/O
3981 * reference previously taken by calling fp_lookup et. al.
3982 *
3983 * Parameters: p Process in which the fd lives
3984 * fd fd associated with the fileproc
3985 * fp fileproc on which to set the
3986 * flag and drop the reference
3987 *
3988 * Returns: 0 Success
3989 * fp_drop:EBADF Bad file descriptor
3990 *
3991 * Locks: This function internally takes and drops the proc_fdlock for
3992 * the supplied process
3993 *
3994 * Notes: The fileproc must correspond to the fd in the supplied proc
3995 */
91447636
A
3996int
3997fp_drop_written(proc_t p, int fd, struct fileproc *fp)
3998{
3999 int error;
4000
2d21ac55 4001 proc_fdlock_spin(p);
91447636
A
4002
4003 fp->f_flags |= FP_WRITTEN;
39037602 4004
91447636
A
4005 error = fp_drop(p, fd, fp, 1);
4006
4007 proc_fdunlock(p);
39037602 4008
91447636
A
4009 return (error);
4010}
4011
4012
2d21ac55
A
4013/*
4014 * fp_drop_event
4015 *
4016 * Description: Set the FP_WAITEVENT flag on the fileproc and drop the I/O
4017 * reference previously taken by calling fp_lookup et. al.
4018 *
4019 * Parameters: p Process in which the fd lives
4020 * fd fd associated with the fileproc
4021 * fp fileproc on which to set the
4022 * flag and drop the reference
4023 *
4024 * Returns: 0 Success
4025 * fp_drop:EBADF Bad file descriptor
4026 *
4027 * Locks: This function internally takes and drops the proc_fdlock for
4028 * the supplied process
4029 *
4030 * Notes: The fileproc must correspond to the fd in the supplied proc
4031 */
91447636
A
4032int
4033fp_drop_event(proc_t p, int fd, struct fileproc *fp)
4034{
4035 int error;
4036
2d21ac55 4037 proc_fdlock_spin(p);
91447636
A
4038
4039 fp->f_flags |= FP_WAITEVENT;
39037602 4040
91447636
A
4041 error = fp_drop(p, fd, fp, 1);
4042
4043 proc_fdunlock(p);
39037602 4044
91447636
A
4045 return (error);
4046}
4047
2d21ac55
A
4048
4049/*
4050 * fp_drop
4051 *
4052 * Description: Drop the I/O reference previously taken by calling fp_lookup
4053 * et. al.
4054 *
4055 * Parameters: p Process in which the fd lives
4056 * fd fd associated with the fileproc
4057 * fp fileproc on which to set the
4058 * flag and drop the reference
4059 * locked flag to internally take and
4060 * drop proc_fdlock if it is not
4061 * already held by the caller
4062 *
4063 * Returns: 0 Success
4064 * EBADF Bad file descriptor
4065 *
4066 * Locks: This function internally takes and drops the proc_fdlock for
4067 * the supplied process if 'locked' is non-zero, and assumes that
4068 * the caller already holds this lock if 'locked' is non-zero.
4069 *
4070 * Notes: The fileproc must correspond to the fd in the supplied proc
4071 */
1c79356b 4072int
2d21ac55 4073fp_drop(proc_t p, int fd, struct fileproc *fp, int locked)
1c79356b 4074{
91447636 4075 struct filedesc *fdp = p->p_fd;
2d21ac55 4076 int needwakeup = 0;
1c79356b 4077
91447636 4078 if (!locked)
2d21ac55 4079 proc_fdlock_spin(p);
91447636
A
4080 if ((fp == FILEPROC_NULL) && (fd < 0 || fd >= fdp->fd_nfiles ||
4081 (fp = fdp->fd_ofiles[fd]) == NULL ||
4082 ((fdp->fd_ofileflags[fd] & UF_RESERVED) &&
4083 !(fdp->fd_ofileflags[fd] & UF_CLOSING)))) {
4084 if (!locked)
4085 proc_fdunlock(p);
4086 return (EBADF);
4087 }
4088 fp->f_iocount--;
4089
6d2010ae
A
4090 if (fp->f_iocount == 0) {
4091 if (fp->f_flags & FP_SELCONFLICT)
4092 fp->f_flags &= ~FP_SELCONFLICT;
4093
4094 if (p->p_fpdrainwait) {
4095 p->p_fpdrainwait = 0;
4096 needwakeup = 1;
4097 }
91447636
A
4098 }
4099 if (!locked)
4100 proc_fdunlock(p);
2d21ac55
A
4101 if (needwakeup)
4102 wakeup(&p->p_fpdrainwait);
39037602 4103
1c79356b
A
4104 return (0);
4105}
4106
2d21ac55
A
4107
4108/*
4109 * file_vnode
4110 *
4111 * Description: Given an fd, look it up in the current process's per process
4112 * open file table, and return its internal vnode pointer.
4113 *
4114 * Parameters: fd fd to obtain vnode from
4115 * vpp pointer to vnode return area
4116 *
4117 * Returns: 0 Success
4118 * EINVAL The fd does not refer to a
4119 * vnode fileproc entry
4120 * fp_lookup:EBADF Bad file descriptor
4121 *
4122 * Implicit returns:
4123 * *vpp (modified) Returned vnode pointer
4124 *
4125 * Locks: This function internally takes and drops the proc_fdlock for
4126 * the current process
4127 *
4128 * Notes: If successful, this function increments the f_iocount on the
4129 * fd's corresponding fileproc.
4130 *
4131 * The fileproc referenced is not returned; because of this, care
4132 * must be taken to not drop the last reference (e.g. by closing
6d2010ae 4133 * the file). This is inherently unsafe, since the reference may
2d21ac55
A
4134 * not be recoverable from the vnode, if there is a subsequent
4135 * close that destroys the associate fileproc. The caller should
4136 * therefore retain their own reference on the fileproc so that
4137 * the f_iocount can be dropped subsequently. Failure to do this
4138 * can result in the returned pointer immediately becoming invalid
4139 * following the call.
4140 *
4141 * Use of this function is discouraged.
4142 */
91447636
A
4143int
4144file_vnode(int fd, struct vnode **vpp)
1c79356b 4145{
2d21ac55 4146 proc_t p = current_proc();
91447636
A
4147 struct fileproc *fp;
4148 int error;
39037602 4149
2d21ac55 4150 proc_fdlock_spin(p);
91447636
A
4151 if ( (error = fp_lookup(p, fd, &fp, 1)) ) {
4152 proc_fdunlock(p);
4153 return(error);
4154 }
4155 if (fp->f_type != DTYPE_VNODE) {
4156 fp_drop(p, fd, fp,1);
4157 proc_fdunlock(p);
4158 return(EINVAL);
4159 }
b0d623f7
A
4160 if (vpp != NULL)
4161 *vpp = (struct vnode *)fp->f_data;
4162 proc_fdunlock(p);
4163
4164 return(0);
4165}
4166
4167
4168/*
4169 * file_vnode_withvid
4170 *
4171 * Description: Given an fd, look it up in the current process's per process
4172 * open file table, and return its internal vnode pointer.
4173 *
4174 * Parameters: fd fd to obtain vnode from
4175 * vpp pointer to vnode return area
4176 * vidp pointer to vid of the returned vnode
4177 *
4178 * Returns: 0 Success
4179 * EINVAL The fd does not refer to a
4180 * vnode fileproc entry
4181 * fp_lookup:EBADF Bad file descriptor
4182 *
4183 * Implicit returns:
4184 * *vpp (modified) Returned vnode pointer
4185 *
4186 * Locks: This function internally takes and drops the proc_fdlock for
4187 * the current process
4188 *
4189 * Notes: If successful, this function increments the f_iocount on the
4190 * fd's corresponding fileproc.
4191 *
4192 * The fileproc referenced is not returned; because of this, care
4193 * must be taken to not drop the last reference (e.g. by closing
6d2010ae 4194 * the file). This is inherently unsafe, since the reference may
b0d623f7
A
4195 * not be recoverable from the vnode, if there is a subsequent
4196 * close that destroys the associate fileproc. The caller should
4197 * therefore retain their own reference on the fileproc so that
4198 * the f_iocount can be dropped subsequently. Failure to do this
4199 * can result in the returned pointer immediately becoming invalid
4200 * following the call.
4201 *
4202 * Use of this function is discouraged.
4203 */
4204int
4205file_vnode_withvid(int fd, struct vnode **vpp, uint32_t * vidp)
4206{
4207 proc_t p = current_proc();
4208 struct fileproc *fp;
4209 vnode_t vp;
4210 int error;
39037602 4211
b0d623f7
A
4212 proc_fdlock_spin(p);
4213 if ( (error = fp_lookup(p, fd, &fp, 1)) ) {
4214 proc_fdunlock(p);
4215 return(error);
4216 }
4217 if (fp->f_type != DTYPE_VNODE) {
4218 fp_drop(p, fd, fp,1);
4219 proc_fdunlock(p);
4220 return(EINVAL);
4221 }
4222 vp = (struct vnode *)fp->f_data;
39037602 4223 if (vpp != NULL)
b0d623f7
A
4224 *vpp = vp;
4225
39037602 4226 if ((vidp != NULL) && (vp != NULLVP))
b0d623f7
A
4227 *vidp = (uint32_t)vp->v_id;
4228
91447636
A
4229 proc_fdunlock(p);
4230
4231 return(0);
1c79356b
A
4232}
4233
91447636 4234
2d21ac55
A
4235/*
4236 * file_socket
4237 *
4238 * Description: Given an fd, look it up in the current process's per process
4239 * open file table, and return its internal socket pointer.
4240 *
4241 * Parameters: fd fd to obtain vnode from
4242 * sp pointer to socket return area
4243 *
4244 * Returns: 0 Success
4245 * ENOTSOCK Not a socket
4246 * fp_lookup:EBADF Bad file descriptor
4247 *
4248 * Implicit returns:
4249 * *sp (modified) Returned socket pointer
4250 *
4251 * Locks: This function internally takes and drops the proc_fdlock for
4252 * the current process
4253 *
4254 * Notes: If successful, this function increments the f_iocount on the
4255 * fd's corresponding fileproc.
4256 *
4257 * The fileproc referenced is not returned; because of this, care
4258 * must be taken to not drop the last reference (e.g. by closing
6d2010ae 4259 * the file). This is inherently unsafe, since the reference may
2d21ac55
A
4260 * not be recoverable from the socket, if there is a subsequent
4261 * close that destroys the associate fileproc. The caller should
4262 * therefore retain their own reference on the fileproc so that
4263 * the f_iocount can be dropped subsequently. Failure to do this
4264 * can result in the returned pointer immediately becoming invalid
4265 * following the call.
4266 *
4267 * Use of this function is discouraged.
4268 */
1c79356b 4269int
91447636 4270file_socket(int fd, struct socket **sp)
1c79356b 4271{
2d21ac55 4272 proc_t p = current_proc();
91447636
A
4273 struct fileproc *fp;
4274 int error;
39037602 4275
2d21ac55 4276 proc_fdlock_spin(p);
91447636
A
4277 if ( (error = fp_lookup(p, fd, &fp, 1)) ) {
4278 proc_fdunlock(p);
4279 return(error);
4280 }
4281 if (fp->f_type != DTYPE_SOCKET) {
4282 fp_drop(p, fd, fp,1);
4283 proc_fdunlock(p);
4284 return(ENOTSOCK);
4285 }
4286 *sp = (struct socket *)fp->f_data;
4287 proc_fdunlock(p);
1c79356b 4288
91447636
A
4289 return(0);
4290}
4291
2d21ac55
A
4292
4293/*
4294 * file_flags
4295 *
4296 * Description: Given an fd, look it up in the current process's per process
4297 * open file table, and return its fileproc's flags field.
4298 *
4299 * Parameters: fd fd whose flags are to be
4300 * retrieved
4301 * flags pointer to flags data area
4302 *
4303 * Returns: 0 Success
4304 * ENOTSOCK Not a socket
4305 * fp_lookup:EBADF Bad file descriptor
4306 *
4307 * Implicit returns:
4308 * *flags (modified) Returned flags field
4309 *
4310 * Locks: This function internally takes and drops the proc_fdlock for
4311 * the current process
4312 *
4313 * Notes: This function will internally increment and decrement the
4314 * f_iocount of the fileproc as part of its operation.
4315 */
91447636 4316int
2d21ac55 4317file_flags(int fd, int *flags)
91447636
A
4318{
4319
2d21ac55 4320 proc_t p = current_proc();
91447636
A
4321 struct fileproc *fp;
4322 int error;
39037602 4323
2d21ac55 4324 proc_fdlock_spin(p);
91447636
A
4325 if ( (error = fp_lookup(p, fd, &fp, 1)) ) {
4326 proc_fdunlock(p);
4327 return(error);
4328 }
4329 *flags = (int)fp->f_flag;
4330 fp_drop(p, fd, fp,1);
4331 proc_fdunlock(p);
4332
4333 return(0);
4334}
4335
4336
2d21ac55
A
4337/*
4338 * file_drop
4339 *
4340 * Description: Drop an iocount reference on an fd, and wake up any waiters
4341 * for draining (i.e. blocked in fileproc_drain() called during
4342 * the last attempt to close a file).
4343 *
4344 * Parameters: fd fd on which an ioreference is
4345 * to be dropped
4346 *
4347 * Returns: 0 Success
4348 * EBADF Bad file descriptor
4349 *
4350 * Description: Given an fd, look it up in the current process's per process
4351 * open file table, and drop it's fileproc's f_iocount by one
4352 *
4353 * Notes: This is intended as a corresponding operation to the functions
4354 * file_vnode() and file_socket() operations.
4355 *
4356 * Technically, the close reference is supposed to be protected
4357 * by a fileproc_drain(), however, a drain will only block if
4358 * the fd refers to a character device, and that device has had
4359 * preparefileread() called on it. If it refers to something
4360 * other than a character device, then the drain will occur and
4361 * block each close attempt, rather than merely the last close.
4362 *
4363 * Since it's possible for an fd that refers to a character
4364 * device to have an intermediate close followed by an open to
4365 * cause a different file to correspond to that descriptor,
4366 * unless there was a cautionary reference taken on the fileproc,
4367 * this is an inherently unsafe function. This happens in the
4368 * case where multiple fd's in a process refer to the same
4369 * character device (e.g. stdin/out/err pointing to a tty, etc.).
4370 *
4371 * Use of this function is discouraged.
4372 */
39037602 4373int
91447636
A
4374file_drop(int fd)
4375{
4376 struct fileproc *fp;
2d21ac55
A
4377 proc_t p = current_proc();
4378 int needwakeup = 0;
91447636 4379
2d21ac55 4380 proc_fdlock_spin(p);
91447636
A
4381 if (fd < 0 || fd >= p->p_fd->fd_nfiles ||
4382 (fp = p->p_fd->fd_ofiles[fd]) == NULL ||
4383 ((p->p_fd->fd_ofileflags[fd] & UF_RESERVED) &&
4384 !(p->p_fd->fd_ofileflags[fd] & UF_CLOSING))) {
4385 proc_fdunlock(p);
1c79356b 4386 return (EBADF);
91447636
A
4387 }
4388 fp->f_iocount --;
4389
6d2010ae
A
4390 if (fp->f_iocount == 0) {
4391 if (fp->f_flags & FP_SELCONFLICT)
4392 fp->f_flags &= ~FP_SELCONFLICT;
4393
4394 if (p->p_fpdrainwait) {
4395 p->p_fpdrainwait = 0;
4396 needwakeup = 1;
4397 }
91447636
A
4398 }
4399 proc_fdunlock(p);
1c79356b 4400
2d21ac55
A
4401 if (needwakeup)
4402 wakeup(&p->p_fpdrainwait);
4403 return(0);
1c79356b
A
4404}
4405
2d21ac55 4406
39236c6e
A
4407static int falloc_withalloc_locked(proc_t, struct fileproc **, int *,
4408 vfs_context_t, struct fileproc * (*)(void *), void *, int);
4409
2d21ac55
A
4410/*
4411 * falloc
4412 *
4413 * Description: Allocate an entry in the per process open file table and
4414 * return the corresponding fileproc and fd.
4415 *
4416 * Parameters: p The process in whose open file
4417 * table the fd is to be allocated
4418 * resultfp Pointer to fileproc pointer
4419 * return area
4420 * resultfd Pointer to fd return area
4421 * ctx VFS context
4422 *
4423 * Returns: 0 Success
4424 * falloc:ENFILE Too many open files in system
4425 * falloc:EMFILE Too many open files in process
4426 * falloc:ENOMEM M_FILEPROC or M_FILEGLOB zone
4427 * exhausted
4428 *
4429 * Implicit returns:
4430 * *resultfd (modified) Returned fileproc pointer
4431 * *resultfd (modified) Returned fd
4432 *
4433 * Locks: This function takes and drops the proc_fdlock; if this lock
6d2010ae 4434 * is already held, use falloc_locked() instead.
2d21ac55
A
4435 *
4436 * Notes: This function takes separate process and context arguments
4437 * solely to support kern_exec.c; otherwise, it would take
4438 * neither, and expect falloc_locked() to use the
4439 * vfs_context_current() routine internally.
4440 */
91447636 4441int
2d21ac55 4442falloc(proc_t p, struct fileproc **resultfp, int *resultfd, vfs_context_t ctx)
39236c6e
A
4443{
4444 return (falloc_withalloc(p, resultfp, resultfd, ctx,
4445 fileproc_alloc_init, NULL));
4446}
4447
4448/*
4449 * Like falloc, but including the fileproc allocator and create-args
4450 */
4451int
4452falloc_withalloc(proc_t p, struct fileproc **resultfp, int *resultfd,
4453 vfs_context_t ctx, fp_allocfn_t fp_zalloc, void *arg)
91447636
A
4454{
4455 int error;
4456
4457 proc_fdlock(p);
39236c6e
A
4458 error = falloc_withalloc_locked(p,
4459 resultfp, resultfd, ctx, fp_zalloc, arg, 1);
91447636
A
4460 proc_fdunlock(p);
4461
39236c6e 4462 return (error);
91447636 4463}
2d21ac55 4464
39236c6e
A
4465/*
4466 * "uninitialized" ops -- ensure fg->fg_ops->fo_type always exists
4467 */
4468static const struct fileops uninitops;
2d21ac55 4469
1c79356b 4470/*
2d21ac55
A
4471 * falloc_locked
4472 *
1c79356b 4473 * Create a new open file structure and allocate
6d2010ae 4474 * a file descriptor for the process that refers to it.
2d21ac55
A
4475 *
4476 * Returns: 0 Success
4477 *
4478 * Description: Allocate an entry in the per process open file table and
4479 * return the corresponding fileproc and fd.
4480 *
4481 * Parameters: p The process in whose open file
4482 * table the fd is to be allocated
4483 * resultfp Pointer to fileproc pointer
4484 * return area
4485 * resultfd Pointer to fd return area
4486 * ctx VFS context
4487 * locked Flag to indicate whether the
4488 * caller holds proc_fdlock
4489 *
4490 * Returns: 0 Success
4491 * ENFILE Too many open files in system
4492 * fdalloc:EMFILE Too many open files in process
4493 * ENOMEM M_FILEPROC or M_FILEGLOB zone
4494 * exhausted
4495 * fdalloc:ENOMEM
4496 *
4497 * Implicit returns:
4498 * *resultfd (modified) Returned fileproc pointer
4499 * *resultfd (modified) Returned fd
4500 *
4501 * Locks: If the parameter 'locked' is zero, this function takes and
4502 * drops the proc_fdlock; if non-zero, the caller must hold the
4503 * lock.
4504 *
4505 * Notes: If you intend to use a non-zero 'locked' parameter, use the
4506 * utility function falloc() instead.
4507 *
4508 * This function takes separate process and context arguments
4509 * solely to support kern_exec.c; otherwise, it would take
4510 * neither, and use the vfs_context_current() routine internally.
1c79356b
A
4511 */
4512int
2d21ac55
A
4513falloc_locked(proc_t p, struct fileproc **resultfp, int *resultfd,
4514 vfs_context_t ctx, int locked)
39236c6e
A
4515{
4516 return (falloc_withalloc_locked(p, resultfp, resultfd, ctx,
4517 fileproc_alloc_init, NULL, locked));
4518}
4519
4520static int
4521falloc_withalloc_locked(proc_t p, struct fileproc **resultfp, int *resultfd,
4522 vfs_context_t ctx, fp_allocfn_t fp_zalloc, void *crarg,
4523 int locked)
1c79356b 4524{
316670eb 4525 struct fileproc *fp;
91447636
A
4526 struct fileglob *fg;
4527 int error, nfd;
4528
4529 if (!locked)
4530 proc_fdlock(p);
4531 if ( (error = fdalloc(p, 0, &nfd)) ) {
4532 if (!locked)
4533 proc_fdunlock(p);
1c79356b 4534 return (error);
91447636 4535 }
1c79356b 4536 if (nfiles >= maxfiles) {
91447636
A
4537 if (!locked)
4538 proc_fdunlock(p);
1c79356b
A
4539 tablefull("file");
4540 return (ENFILE);
4541 }
2d21ac55
A
4542#if CONFIG_MACF
4543 error = mac_file_check_create(proc_ucred(p));
4544 if (error) {
4545 if (!locked)
4546 proc_fdunlock(p);
4547 return (error);
4548 }
4549#endif
4550
1c79356b
A
4551 /*
4552 * Allocate a new file descriptor.
4553 * If the process has file descriptor zero open, add to the list
4554 * of open files at that point, otherwise put it at the front of
4555 * the list of open files.
4556 */
91447636
A
4557 proc_fdunlock(p);
4558
39236c6e 4559 fp = (*fp_zalloc)(crarg);
2d21ac55
A
4560 if (fp == NULL) {
4561 if (locked)
4562 proc_fdlock(p);
4563 return (ENOMEM);
4564 }
91447636 4565 MALLOC_ZONE(fg, struct fileglob *, sizeof(struct fileglob), M_FILEGLOB, M_WAITOK);
2d21ac55 4566 if (fg == NULL) {
39236c6e 4567 fileproc_free(fp);
2d21ac55
A
4568 if (locked)
4569 proc_fdlock(p);
4570 return (ENOMEM);
4571 }
91447636
A
4572 bzero(fg, sizeof(struct fileglob));
4573 lck_mtx_init(&fg->fg_lock, file_lck_grp, file_lck_attr);
4574
4575 fp->f_iocount = 1;
4576 fg->fg_count = 1;
39236c6e 4577 fg->fg_ops = &uninitops;
91447636 4578 fp->f_fglob = fg;
2d21ac55
A
4579#if CONFIG_MACF
4580 mac_file_label_init(fg);
4581#endif
4582
4583 kauth_cred_ref(ctx->vc_ucred);
91447636
A
4584
4585 proc_fdlock(p);
4586
2d21ac55 4587 fp->f_cred = ctx->vc_ucred;
91447636 4588
2d21ac55
A
4589#if CONFIG_MACF
4590 mac_file_label_associate(fp->f_cred, fg);
4591#endif
4592
316670eb 4593 OSAddAtomic(1, &nfiles);
91447636
A
4594
4595 p->p_fd->fd_ofiles[nfd] = fp;
4596
4597 if (!locked)
4598 proc_fdunlock(p);
4599
1c79356b
A
4600 if (resultfp)
4601 *resultfp = fp;
4602 if (resultfd)
91447636
A
4603 *resultfd = nfd;
4604
1c79356b
A
4605 return (0);
4606}
4607
2d21ac55 4608
1c79356b 4609/*
2d21ac55
A
4610 * fg_free
4611 *
4612 * Description: Free a file structure; drop the global open file count, and
4613 * drop the credential reference, if the fileglob has one, and
4614 * destroy the instance mutex before freeing
4615 *
4616 * Parameters: fg Pointer to fileglob to be
4617 * freed
4618 *
4619 * Returns: void
1c79356b
A
4620 */
4621void
2d21ac55 4622fg_free(struct fileglob *fg)
1c79356b 4623{
316670eb 4624 OSAddAtomic(-1, &nfiles);
1c79356b 4625
fe8ab488
A
4626 if (fg->fg_vn_data) {
4627 fg_vn_data_free(fg->fg_vn_data);
4628 fg->fg_vn_data = NULL;
4629 }
4630
0c530ab8
A
4631 if (IS_VALID_CRED(fg->fg_cred)) {
4632 kauth_cred_unref(&fg->fg_cred);
1c79356b 4633 }
91447636 4634 lck_mtx_destroy(&fg->fg_lock, file_lck_grp);
fa4905b1 4635
2d21ac55
A
4636#if CONFIG_MACF
4637 mac_file_label_destroy(fg);
4638#endif
91447636 4639 FREE_ZONE(fg, sizeof *fg, M_FILEGLOB);
1c79356b
A
4640}
4641
2d21ac55 4642
5ba3f43e 4643
2d21ac55
A
4644/*
4645 * fdexec
4646 *
4647 * Description: Perform close-on-exec processing for all files in a process
4648 * that are either marked as close-on-exec, or which were in the
4649 * process of being opened at the time of the execve
4650 *
6d2010ae
A
4651 * Also handles the case (via posix_spawn()) where -all-
4652 * files except those marked with "inherit" as treated as
4653 * close-on-exec.
4654 *
2d21ac55
A
4655 * Parameters: p Pointer to process calling
4656 * execve
4657 *
4658 * Returns: void
4659 *
4660 * Locks: This function internally takes and drops proc_fdlock()
5ba3f43e 4661 * But assumes tables don't grow/change while unlocked.
2d21ac55 4662 *
2d21ac55 4663 */
1c79356b 4664void
5ba3f43e 4665fdexec(proc_t p, short flags, int self_exec)
1c79356b 4666{
91447636 4667 struct filedesc *fdp = p->p_fd;
b0d623f7 4668 int i;
6d2010ae 4669 boolean_t cloexec_default = (flags & POSIX_SPAWN_CLOEXEC_DEFAULT) != 0;
5ba3f43e
A
4670 thread_t self = current_thread();
4671 struct uthread *ut = get_bsdthread_info(self);
4672 struct kqueue *dealloc_kq = NULL;
4673
4674 /*
4675 * If the current thread is bound as a workq/workloop
4676 * servicing thread, we need to unbind it first.
4677 */
4678 if (ut->uu_kqueue_bound && self_exec) {
4679 kevent_qos_internal_unbind(p, 0, self,
4680 ut->uu_kqueue_flags);
4681 }
91447636 4682
91447636 4683 proc_fdlock(p);
5ba3f43e
A
4684
4685 /*
4686 * Deallocate the knotes for this process
4687 * and mark the tables non-existent so
4688 * subsequent kqueue closes go faster.
4689 */
4690 knotes_dealloc(p);
4691 assert(fdp->fd_knlistsize == -1);
4692 assert(fdp->fd_knhashmask == 0);
4693
6d2010ae
A
4694 for (i = fdp->fd_lastfile; i >= 0; i--) {
4695
4696 struct fileproc *fp = fdp->fd_ofiles[i];
4697 char *flagp = &fdp->fd_ofileflags[i];
b0d623f7 4698
316670eb 4699 if (fp && cloexec_default) {
6d2010ae
A
4700 /*
4701 * Reverse the usual semantics of file descriptor
4702 * inheritance - all of them should be closed
4703 * except files marked explicitly as "inherit" and
4704 * not marked close-on-exec.
4705 */
4706 if ((*flagp & (UF_EXCLOSE|UF_INHERIT)) != UF_INHERIT)
4707 *flagp |= UF_EXCLOSE;
4708 *flagp &= ~UF_INHERIT;
4709 }
55e303ae 4710
2d21ac55 4711 if (
6d2010ae 4712 ((*flagp & (UF_RESERVED|UF_EXCLOSE)) == UF_EXCLOSE)
2d21ac55
A
4713#if CONFIG_MACF
4714 || (fp && mac_file_check_inherit(proc_ucred(p), fp->f_fglob))
4715#endif
4716 ) {
6601e61a 4717 procfdtbl_clearfd(p, i);
1c79356b
A
4718 if (i == fdp->fd_lastfile && i > 0)
4719 fdp->fd_lastfile--;
6601e61a
A
4720 if (i < fdp->fd_freefile)
4721 fdp->fd_freefile = i;
6d2010ae
A
4722
4723 /*
4724 * Wait for any third party viewers (e.g., lsof)
4725 * to release their references to this fileproc.
4726 */
4727 while (fp->f_iocount > 0) {
4728 p->p_fpdrainwait = 1;
4729 msleep(&p->p_fpdrainwait, &p->p_fdmlock, PRIBIO,
4730 "fpdrain", NULL);
4731 }
4732
91447636 4733 closef_locked(fp, fp->f_fglob, p);
6d2010ae 4734
39236c6e 4735 fileproc_free(fp);
1c79356b 4736 }
1c79356b 4737 }
5ba3f43e
A
4738
4739 /* release the per-process workq kq */
4740 if (fdp->fd_wqkqueue) {
4741 dealloc_kq = fdp->fd_wqkqueue;
4742 fdp->fd_wqkqueue = NULL;
4743 }
4744
91447636 4745 proc_fdunlock(p);
5ba3f43e
A
4746
4747 /* Anything to free? */
4748 if (dealloc_kq)
4749 kqueue_dealloc(dealloc_kq);
1c79356b
A
4750}
4751
2d21ac55 4752
1c79356b 4753/*
2d21ac55
A
4754 * fdcopy
4755 *
4756 * Description: Copy a filedesc structure. This is normally used as part of
4757 * forkproc() when forking a new process, to copy the per process
4758 * open file table over to the new process.
4759 *
4760 * Parameters: p Process whose open file table
4761 * is to be copied (parent)
4762 * uth_cdir Per thread current working
4763 * cirectory, or NULL
4764 *
4765 * Returns: NULL Copy failed
4766 * !NULL Pointer to new struct filedesc
4767 *
4768 * Locks: This function internally takes and drops proc_fdlock()
4769 *
4770 * Notes: Files are copied directly, ignoring the new resource limits
4771 * for the process that's being copied into. Since the descriptor
4772 * references are just additional references, this does not count
4773 * against the number of open files on the system.
4774 *
4775 * The struct filedesc includes the current working directory,
4776 * and the current root directory, if the process is chroot'ed.
4777 *
4778 * If the exec was called by a thread using a per thread current
4779 * working directory, we inherit the working directory from the
4780 * thread making the call, rather than from the process.
4781 *
4782 * In the case of a failure to obtain a reference, for most cases,
6d2010ae 4783 * the file entry will be silently dropped. There's an exception
2d21ac55
A
4784 * for the case of a chroot dir, since a failure to to obtain a
4785 * reference there would constitute an "escape" from the chroot
4786 * environment, which must not be allowed. In that case, we will
4787 * deny the execve() operation, rather than allowing the escape.
1c79356b
A
4788 */
4789struct filedesc *
2d21ac55 4790fdcopy(proc_t p, vnode_t uth_cdir)
1c79356b 4791{
91447636
A
4792 struct filedesc *newfdp, *fdp = p->p_fd;
4793 int i;
4794 struct fileproc *ofp, *fp;
4795 vnode_t v_dir;
1c79356b
A
4796
4797 MALLOC_ZONE(newfdp, struct filedesc *,
6601e61a 4798 sizeof(*newfdp), M_FILEDESC, M_WAITOK);
91447636
A
4799 if (newfdp == NULL)
4800 return(NULL);
4801
4802 proc_fdlock(p);
4803
4804 /*
4805 * the FD_CHROOT flag will be inherited via this copy
4806 */
6601e61a 4807 (void) memcpy(newfdp, fdp, sizeof(*newfdp));
91447636
A
4808
4809 /*
2d21ac55
A
4810 * If we are running with per-thread current working directories,
4811 * inherit the new current working directory from the current thread
4812 * instead, before we take our references.
4813 */
4814 if (uth_cdir != NULLVP)
4815 newfdp->fd_cdir = uth_cdir;
4816
4817 /*
4818 * For both fd_cdir and fd_rdir make sure we get
91447636
A
4819 * a valid reference... if we can't, than set
4820 * set the pointer(s) to NULL in the child... this
4821 * will keep us from using a non-referenced vp
4822 * and allows us to do the vnode_rele only on
4823 * a properly referenced vp
4824 */
4825 if ( (v_dir = newfdp->fd_cdir) ) {
4826 if (vnode_getwithref(v_dir) == 0) {
4827 if ( (vnode_ref(v_dir)) )
4828 newfdp->fd_cdir = NULL;
4829 vnode_put(v_dir);
4830 } else
4831 newfdp->fd_cdir = NULL;
4832 }
4833 if (newfdp->fd_cdir == NULL && fdp->fd_cdir) {
4834 /*
4835 * we couldn't get a new reference on
4836 * the current working directory being
4837 * inherited... we might as well drop
4838 * our reference from the parent also
4839 * since the vnode has gone DEAD making
4840 * it useless... by dropping it we'll
6d2010ae 4841 * be that much closer to recycling it
91447636
A
4842 */
4843 vnode_rele(fdp->fd_cdir);
4844 fdp->fd_cdir = NULL;
4845 }
4846
4847 if ( (v_dir = newfdp->fd_rdir) ) {
4848 if (vnode_getwithref(v_dir) == 0) {
4849 if ( (vnode_ref(v_dir)) )
4850 newfdp->fd_rdir = NULL;
4851 vnode_put(v_dir);
2d21ac55 4852 } else {
91447636 4853 newfdp->fd_rdir = NULL;
2d21ac55 4854 }
91447636 4855 }
2d21ac55 4856 /* Coming from a chroot environment and unable to get a reference... */
91447636
A
4857 if (newfdp->fd_rdir == NULL && fdp->fd_rdir) {
4858 /*
2d21ac55
A
4859 * We couldn't get a new reference on
4860 * the chroot directory being
4861 * inherited... this is fatal, since
4862 * otherwise it would constitute an
4863 * escape from a chroot environment by
4864 * the new process.
91447636 4865 */
2d21ac55
A
4866 if (newfdp->fd_cdir)
4867 vnode_rele(newfdp->fd_cdir);
4868 FREE_ZONE(newfdp, sizeof *newfdp, M_FILEDESC);
4869 return(NULL);
91447636 4870 }
1c79356b
A
4871
4872 /*
4873 * If the number of open files fits in the internal arrays
4874 * of the open file structure, use them, otherwise allocate
4875 * additional memory for the number of descriptors currently
4876 * in use.
4877 */
4878 if (newfdp->fd_lastfile < NDFILE)
4879 i = NDFILE;
4880 else {
4881 /*
4882 * Compute the smallest multiple of NDEXTENT needed
4883 * for the file descriptors currently in use,
4884 * allowing the table to shrink.
4885 */
4886 i = newfdp->fd_nfiles;
3e170ce0 4887 while (i > 1 + 2 * NDEXTENT && i > 1 + newfdp->fd_lastfile * 2)
1c79356b
A
4888 i /= 2;
4889 }
91447636
A
4890 proc_fdunlock(p);
4891
4892 MALLOC_ZONE(newfdp->fd_ofiles, struct fileproc **,
1c79356b 4893 i * OFILESIZE, M_OFILETABL, M_WAITOK);
91447636
A
4894 if (newfdp->fd_ofiles == NULL) {
4895 if (newfdp->fd_cdir)
4896 vnode_rele(newfdp->fd_cdir);
4897 if (newfdp->fd_rdir)
4898 vnode_rele(newfdp->fd_rdir);
4899
2d21ac55 4900 FREE_ZONE(newfdp, sizeof(*newfdp), M_FILEDESC);
91447636
A
4901 return(NULL);
4902 }
6601e61a 4903 (void) memset(newfdp->fd_ofiles, 0, i * OFILESIZE);
91447636
A
4904 proc_fdlock(p);
4905
1c79356b
A
4906 newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];
4907 newfdp->fd_nfiles = i;
91447636 4908
1c79356b 4909 if (fdp->fd_nfiles > 0) {
91447636
A
4910 struct fileproc **fpp;
4911 char *flags;
1c79356b
A
4912
4913 (void) memcpy(newfdp->fd_ofiles, fdp->fd_ofiles,
2d21ac55 4914 (newfdp->fd_lastfile + 1) * sizeof(*fdp->fd_ofiles));
1c79356b 4915 (void) memcpy(newfdp->fd_ofileflags, fdp->fd_ofileflags,
2d21ac55 4916 (newfdp->fd_lastfile + 1) * sizeof(*fdp->fd_ofileflags));
1c79356b 4917
55e303ae
A
4918 /*
4919 * kq descriptors cannot be copied.
4920 */
4921 if (newfdp->fd_knlistsize != -1) {
4922 fpp = &newfdp->fd_ofiles[newfdp->fd_lastfile];
39236c6e
A
4923 flags = &newfdp->fd_ofileflags[newfdp->fd_lastfile];
4924 for (i = newfdp->fd_lastfile;
4925 i >= 0; i--, fpp--, flags--) {
4926 if (*flags & UF_RESERVED)
4927 continue; /* (removed below) */
55e303ae
A
4928 if (*fpp != NULL && (*fpp)->f_type == DTYPE_KQUEUE) {
4929 *fpp = NULL;
39236c6e 4930 *flags = 0;
55e303ae
A
4931 if (i < newfdp->fd_freefile)
4932 newfdp->fd_freefile = i;
4933 }
4934 if (*fpp == NULL && i == newfdp->fd_lastfile && i > 0)
4935 newfdp->fd_lastfile--;
4936 }
55e303ae 4937 }
1c79356b
A
4938 fpp = newfdp->fd_ofiles;
4939 flags = newfdp->fd_ofileflags;
91447636 4940
6601e61a 4941 for (i = newfdp->fd_lastfile + 1; --i >= 0; fpp++, flags++)
39236c6e 4942 if ((ofp = *fpp) != NULL &&
3e170ce0 4943 0 == (ofp->f_fglob->fg_lflags & FG_CONFINED) &&
39236c6e
A
4944 0 == (*flags & (UF_FORKCLOSE|UF_RESERVED))) {
4945#if DEBUG
4946 if (FILEPROC_TYPE(ofp) != FTYPE_SIMPLE)
4947 panic("complex fileproc");
4948#endif
4949 fp = fileproc_alloc_init(NULL);
2d21ac55
A
4950 if (fp == NULL) {
4951 /*
4952 * XXX no room to copy, unable to
4953 * XXX safely unwind state at present
4954 */
4955 *fpp = NULL;
4956 } else {
39236c6e
A
4957 fp->f_flags |=
4958 (ofp->f_flags & ~FP_TYPEMASK);
2d21ac55
A
4959 fp->f_fglob = ofp->f_fglob;
4960 (void)fg_ref(fp);
4961 *fpp = fp;
4962 }
1c79356b 4963 } else {
6601e61a
A
4964 if (i < newfdp->fd_freefile)
4965 newfdp->fd_freefile = i;
1c79356b
A
4966 *fpp = NULL;
4967 *flags = 0;
4968 }
6601e61a 4969 }
1c79356b 4970
91447636 4971 proc_fdunlock(p);
5ba3f43e
A
4972
4973 /*
4974 * Initialize knote and kqueue tracking structs
4975 */
4976 newfdp->fd_knlist = NULL;
4977 newfdp->fd_knlistsize = -1;
4978 newfdp->fd_knhash = NULL;
4979 newfdp->fd_knhashmask = 0;
4980 newfdp->fd_kqhash = NULL;
4981 newfdp->fd_kqhashmask = 0;
4982 newfdp->fd_wqkqueue = NULL;
4983 lck_mtx_init(&newfdp->fd_kqhashlock, proc_kqhashlock_grp, proc_lck_attr);
4984 lck_mtx_init(&newfdp->fd_knhashlock, proc_knhashlock_grp, proc_lck_attr);
4985
1c79356b
A
4986 return (newfdp);
4987}
4988
2d21ac55 4989
1c79356b 4990/*
2d21ac55
A
4991 * fdfree
4992 *
4993 * Description: Release a filedesc (per process open file table) structure;
4994 * this is done on process exit(), or from forkproc_free() if
4995 * the fork fails for some reason subsequent to a successful
4996 * call to fdcopy()
4997 *
4998 * Parameters: p Pointer to process going away
4999 *
5000 * Returns: void
5001 *
5002 * Locks: This function internally takes and drops proc_fdlock()
1c79356b
A
5003 */
5004void
2d21ac55 5005fdfree(proc_t p)
1c79356b 5006{
fa4905b1 5007 struct filedesc *fdp;
91447636 5008 struct fileproc *fp;
5ba3f43e 5009 struct kqueue *dealloc_kq = NULL;
fa4905b1 5010 int i;
91447636
A
5011
5012 proc_fdlock(p);
1c79356b 5013
39236c6e 5014 if (p == kernproc || NULL == (fdp = p->p_fd)) {
91447636 5015 proc_fdunlock(p);
1c79356b 5016 return;
91447636 5017 }
55e303ae 5018
39236c6e
A
5019 extern struct filedesc filedesc0;
5020
5021 if (&filedesc0 == fdp)
5022 panic("filedesc0");
91447636 5023
5ba3f43e
A
5024 /*
5025 * deallocate all the knotes up front and claim empty
5026 * tables to make any subsequent kqueue closes faster.
5027 */
5028 knotes_dealloc(p);
5029 assert(fdp->fd_knlistsize == -1);
5030 assert(fdp->fd_knhashmask == 0);
5031
5032 /* close file descriptors */
91447636 5033 if (fdp->fd_nfiles > 0 && fdp->fd_ofiles) {
39037602 5034 for (i = fdp->fd_lastfile; i >= 0; i--) {
55e303ae 5035 if ((fp = fdp->fd_ofiles[i]) != NULL) {
39037602 5036
91447636 5037 if (fdp->fd_ofileflags[i] & UF_RESERVED)
6d2010ae 5038 panic("fdfree: found fp with UF_RESERVED");
91447636 5039
6601e61a 5040 procfdtbl_reservefd(p, i);
91447636 5041
39037602 5042 if (fp->f_flags & FP_WAITEVENT)
91447636
A
5043 (void)waitevent_close(p, fp);
5044 (void) closef_locked(fp, fp->f_fglob, p);
39236c6e 5045 fileproc_free(fp);
55e303ae 5046 }
91447636
A
5047 }
5048 FREE_ZONE(fdp->fd_ofiles, fdp->fd_nfiles * OFILESIZE, M_OFILETABL);
5049 fdp->fd_ofiles = NULL;
5050 fdp->fd_nfiles = 0;
39037602 5051 }
55e303ae 5052
5ba3f43e
A
5053 if (fdp->fd_wqkqueue) {
5054 dealloc_kq = fdp->fd_wqkqueue;
5055 fdp->fd_wqkqueue = NULL;
5056 }
5057
91447636 5058 proc_fdunlock(p);
39037602 5059
5ba3f43e
A
5060 if (dealloc_kq)
5061 kqueue_dealloc(dealloc_kq);
5062
91447636 5063 if (fdp->fd_cdir)
5ba3f43e 5064 vnode_rele(fdp->fd_cdir);
91447636
A
5065 if (fdp->fd_rdir)
5066 vnode_rele(fdp->fd_rdir);
55e303ae 5067
2d21ac55 5068 proc_fdlock_spin(p);
91447636
A
5069 p->p_fd = NULL;
5070 proc_fdunlock(p);
55e303ae 5071
5ba3f43e
A
5072 if (fdp->fd_kqhash) {
5073 for (uint32_t j = 0; j <= fdp->fd_kqhashmask; j++)
5074 assert(SLIST_EMPTY(&fdp->fd_kqhash[j]));
5075 FREE(fdp->fd_kqhash, M_KQUEUE);
5076 }
5077
5078 lck_mtx_destroy(&fdp->fd_kqhashlock, proc_kqhashlock_grp);
5079 lck_mtx_destroy(&fdp->fd_knhashlock, proc_knhashlock_grp);
55e303ae 5080
2d21ac55 5081 FREE_ZONE(fdp, sizeof(*fdp), M_FILEDESC);
1c79356b
A
5082}
5083
5084/*
2d21ac55
A
5085 * closef_locked
5086 *
5087 * Description: Internal form of closef; called with proc_fdlock held
5088 *
5089 * Parameters: fp Pointer to fileproc for fd
5090 * fg Pointer to fileglob for fd
5091 * p Pointer to proc structure
5092 *
5093 * Returns: 0 Success
5094 * closef_finish:??? Anything returnable by a per-fileops
5095 * close function
5096 *
5097 * Note: Decrements reference count on file structure; if this was the
5098 * last reference, then closef_finish() is called
5099 *
5100 * p and fp are allowed to be NULL when closing a file that was
5101 * being passed in a message (but only if we are called when this
5102 * is NOT the last reference).
1c79356b
A
5103 */
5104int
2d21ac55 5105closef_locked(struct fileproc *fp, struct fileglob *fg, proc_t p)
1c79356b
A
5106{
5107 struct vnode *vp;
5108 struct flock lf;
91447636 5109 struct vfs_context context;
1c79356b
A
5110 int error;
5111
91447636 5112 if (fg == NULL) {
1c79356b 5113 return (0);
91447636 5114 }
2d21ac55
A
5115
5116 /* Set up context with cred stashed in fg */
5117 if (p == current_proc())
5118 context.vc_thread = current_thread();
5119 else
5120 context.vc_thread = NULL;
5121 context.vc_ucred = fg->fg_cred;
5122
1c79356b
A
5123 /*
5124 * POSIX record locking dictates that any close releases ALL
5125 * locks owned by this process. This is handled by setting
5126 * a flag in the unlock to free ONLY locks obeying POSIX
5127 * semantics, and not to free BSD-style file locks.
5128 * If the descriptor was in a message, POSIX-style locks
5129 * aren't passed with the descriptor.
5130 */
39236c6e
A
5131 if (p && (p->p_ladvflag & P_LADVLOCK) &&
5132 DTYPE_VNODE == FILEGLOB_DTYPE(fg)) {
91447636
A
5133 proc_fdunlock(p);
5134
1c79356b
A
5135 lf.l_whence = SEEK_SET;
5136 lf.l_start = 0;
5137 lf.l_len = 0;
5138 lf.l_type = F_UNLCK;
91447636
A
5139 vp = (struct vnode *)fg->fg_data;
5140
5141 if ( (error = vnode_getwithref(vp)) == 0 ) {
39236c6e 5142 (void) VNOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX, &context, NULL);
91447636
A
5143 (void)vnode_put(vp);
5144 }
5145 proc_fdlock(p);
1c79356b 5146 }
2d21ac55 5147 lck_mtx_lock_spin(&fg->fg_lock);
91447636
A
5148 fg->fg_count--;
5149
5150 if (fg->fg_count > 0) {
5151 lck_mtx_unlock(&fg->fg_lock);
1c79356b 5152 return (0);
91447636 5153 }
2d21ac55 5154#if DIAGNOSTIC
91447636 5155 if (fg->fg_count != 0)
2d21ac55
A
5156 panic("fg %p: being freed with bad fg_count (%d)", fg, fg->fg_count);
5157#endif
91447636
A
5158
5159 if (fp && (fp->f_flags & FP_WRITTEN))
5160 fg->fg_flag |= FWASWRITTEN;
5161
5162 fg->fg_lflags |= FG_TERM;
5163 lck_mtx_unlock(&fg->fg_lock);
5164
e2fac8b1
A
5165 if (p)
5166 proc_fdunlock(p);
39236c6e 5167
39037602 5168 /* Since we ensure that fg->fg_ops is always initialized,
39236c6e
A
5169 * it is safe to invoke fo_close on the fg */
5170 error = fo_close(fg, &context);
5171
5172 fg_free(fg);
39037602 5173
e2fac8b1
A
5174 if (p)
5175 proc_fdlock(p);
91447636
A
5176
5177 return(error);
5178}
5179
5180
2d21ac55
A
5181/*
5182 * fileproc_drain
5183 *
5184 * Description: Drain out pending I/O operations
5185 *
5186 * Parameters: p Process closing this file
5187 * fp fileproc struct for the open
5188 * instance on the file
5189 *
5190 * Returns: void
5191 *
5192 * Locks: Assumes the caller holds the proc_fdlock
5193 *
5194 * Notes: For character devices, this occurs on the last close of the
6d2010ae 5195 * device; for all other file descriptors, this occurs on each
2d21ac55
A
5196 * close to prevent fd's from being closed out from under
5197 * operations currently in progress and blocked
5198 *
5199 * See Also: file_vnode(), file_socket(), file_drop(), and the cautions
5200 * regarding their use and interaction with this function.
5201 */
91447636 5202void
2d21ac55 5203fileproc_drain(proc_t p, struct fileproc * fp)
91447636 5204{
2d21ac55
A
5205 struct vfs_context context;
5206
5207 context.vc_thread = proc_thread(p); /* XXX */
5208 context.vc_ucred = fp->f_fglob->fg_cred;
5209
91447636
A
5210 fp->f_iocount-- ; /* (the one the close holds) */
5211
5212 while (fp->f_iocount) {
2d21ac55
A
5213
5214 lck_mtx_convert_spin(&p->p_fdmlock);
5215
cf7d32b8
A
5216 if (fp->f_fglob->fg_ops->fo_drain) {
5217 (*fp->f_fglob->fg_ops->fo_drain)(fp, &context);
5218 }
6d2010ae 5219 if ((fp->f_flags & FP_INSELECT) == FP_INSELECT) {
3e170ce0
A
5220 if (waitq_wakeup64_all((struct waitq *)fp->f_wset, NO_EVENT64,
5221 THREAD_INTERRUPTED, WAITQ_ALL_PRIORITIES) == KERN_INVALID_ARGUMENT)
5222 panic("bad wait queue for waitq_wakeup64_all %p (fp:%p)", fp->f_wset, fp);
5223 }
6d2010ae 5224 if ((fp->f_flags & FP_SELCONFLICT) == FP_SELCONFLICT) {
3e170ce0
A
5225 if (waitq_wakeup64_all(&select_conflict_queue, NO_EVENT64,
5226 THREAD_INTERRUPTED, WAITQ_ALL_PRIORITIES) == KERN_INVALID_ARGUMENT)
6d2010ae
A
5227 panic("bad select_conflict_queue");
5228 }
91447636
A
5229 p->p_fpdrainwait = 1;
5230
2d21ac55 5231 msleep(&p->p_fpdrainwait, &p->p_fdmlock, PRIBIO, "fpdrain", NULL);
91447636 5232
91447636 5233 }
6d2010ae
A
5234#if DIAGNOSTIC
5235 if ((fp->f_flags & FP_INSELECT) != 0)
5236 panic("FP_INSELECT set on drained fp");
5237#endif
5238 if ((fp->f_flags & FP_SELCONFLICT) == FP_SELCONFLICT)
5239 fp->f_flags &= ~FP_SELCONFLICT;
91447636
A
5240}
5241
2d21ac55
A
5242
5243/*
5244 * fp_free
5245 *
5246 * Description: Release the fd and free the fileproc associated with the fd
5247 * in the per process open file table of the specified process;
5248 * these values must correspond.
5249 *
5250 * Parameters: p Process containing fd
5251 * fd fd to be released
5252 * fp fileproc to be freed
5253 *
5254 * Returns: 0 Success
5255 *
5256 * Notes: XXX function should be void - no one interprets the returns
5257 * XXX code
5258 */
91447636 5259int
2d21ac55 5260fp_free(proc_t p, int fd, struct fileproc * fp)
91447636 5261{
2d21ac55 5262 proc_fdlock_spin(p);
91447636
A
5263 fdrelse(p, fd);
5264 proc_fdunlock(p);
5265
5266 fg_free(fp->f_fglob);
39236c6e 5267 fileproc_free(fp);
2d21ac55 5268 return(0);
1c79356b
A
5269}
5270
91447636 5271
1c79356b 5272/*
2d21ac55
A
5273 * flock
5274 *
5275 * Description: Apply an advisory lock on a file descriptor.
5276 *
5277 * Parameters: p Process making request
5278 * uap->fd fd on which the lock is to be
5279 * attempted
5280 * uap->how (Un)Lock bits, including type
5281 * retval Pointer to the call return area
39037602 5282 *
2d21ac55
A
5283 * Returns: 0 Success
5284 * fp_getfvp:EBADF Bad file descriptor
5285 * fp_getfvp:ENOTSUP fd does not refer to a vnode
5286 * vnode_getwithref:???
5287 * VNOP_ADVLOCK:???
1c79356b 5288 *
2d21ac55
A
5289 * Implicit returns:
5290 * *retval (modified) Size of dtable
5291 *
5292 * Notes: Just attempt to get a record lock of the requested type on
5293 * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
1c79356b 5294 */
1c79356b 5295int
b0d623f7 5296flock(proc_t p, struct flock_args *uap, __unused int32_t *retval)
1c79356b
A
5297{
5298 int fd = uap->fd;
5299 int how = uap->how;
91447636 5300 struct fileproc *fp;
1c79356b
A
5301 struct vnode *vp;
5302 struct flock lf;
2d21ac55 5303 vfs_context_t ctx = vfs_context_current();
91447636 5304 int error=0;
1c79356b 5305
55e303ae 5306 AUDIT_ARG(fd, uap->fd);
91447636
A
5307 if ( (error = fp_getfvp(p, fd, &fp, &vp)) ) {
5308 return(error);
5309 }
5310 if ( (error = vnode_getwithref(vp)) ) {
5311 goto out1;
5312 }
55e303ae 5313 AUDIT_ARG(vnpath, vp, ARG_VNODE1);
91447636 5314
1c79356b
A
5315 lf.l_whence = SEEK_SET;
5316 lf.l_start = 0;
5317 lf.l_len = 0;
5318 if (how & LOCK_UN) {
5319 lf.l_type = F_UNLCK;
5320 fp->f_flag &= ~FHASLOCK;
39236c6e 5321 error = VNOP_ADVLOCK(vp, (caddr_t)fp->f_fglob, F_UNLCK, &lf, F_FLOCK, ctx, NULL);
91447636 5322 goto out;
1c79356b
A
5323 }
5324 if (how & LOCK_EX)
5325 lf.l_type = F_WRLCK;
5326 else if (how & LOCK_SH)
5327 lf.l_type = F_RDLCK;
91447636
A
5328 else {
5329 error = EBADF;
5330 goto out;
5331 }
2d21ac55
A
5332#if CONFIG_MACF
5333 error = mac_file_check_lock(proc_ucred(p), fp->f_fglob, F_SETLK, &lf);
5334 if (error)
5335 goto out;
5336#endif
39037602
A
5337 error = VNOP_ADVLOCK(vp, (caddr_t)fp->f_fglob, F_SETLK, &lf,
5338 (how & LOCK_NB ? F_FLOCK : F_FLOCK | F_WAIT),
5339 ctx, NULL);
5340 if (!error)
5341 fp->f_flag |= FHASLOCK;
91447636
A
5342out:
5343 (void)vnode_put(vp);
5344out1:
5345 fp_drop(p, fd, fp, 0);
5346 return(error);
5347
1c79356b
A
5348}
5349
d1ecb069
A
5350/*
5351 * fileport_makeport
5352 *
5353 * Description: Obtain a Mach send right for a given file descriptor.
5354 *
5355 * Parameters: p Process calling fileport
5356 * uap->fd The fd to reference
5357 * uap->portnamep User address at which to place port name.
5358 *
5359 * Returns: 0 Success.
5360 * EBADF Bad file descriptor.
5361 * EINVAL File descriptor had type that cannot be sent, misc. other errors.
5362 * EFAULT Address at which to store port name is not valid.
5363 * EAGAIN Resource shortage.
5364 *
5365 * Implicit returns:
39037602 5366 * On success, name of send right is stored at user-specified address.
d1ecb069
A
5367 */
5368int
5369fileport_makeport(proc_t p, struct fileport_makeport_args *uap,
5370 __unused int *retval)
5371{
5372 int err;
5373 int fd = uap->fd;
5374 user_addr_t user_portaddr = uap->portnamep;
5375 struct fileproc *fp = FILEPROC_NULL;
5376 struct fileglob *fg = NULL;
5377 ipc_port_t fileport;
5378 mach_port_name_t name = MACH_PORT_NULL;
5379
3e170ce0
A
5380 proc_fdlock(p);
5381 err = fp_lookup(p, fd, &fp, 1);
d1ecb069 5382 if (err != 0) {
3e170ce0 5383 goto out_unlock;
d1ecb069
A
5384 }
5385
3e170ce0 5386 if (!file_issendable(p, fp)) {
d1ecb069 5387 err = EINVAL;
3e170ce0 5388 goto out_unlock;
d1ecb069
A
5389 }
5390
39236c6e 5391 if (FP_ISGUARDED(fp, GUARD_FILEPORT)) {
39236c6e 5392 err = fp_guard_exception(p, fd, fp, kGUARD_EXC_FILEPORT);
3e170ce0 5393 goto out_unlock;
39236c6e
A
5394 }
5395
d1ecb069
A
5396 /* Dropped when port is deallocated */
5397 fg = fp->f_fglob;
5398 fg_ref(fp);
5399
3e170ce0
A
5400 proc_fdunlock(p);
5401
d1ecb069
A
5402 /* Allocate and initialize a port */
5403 fileport = fileport_alloc(fg);
5404 if (fileport == IPC_PORT_NULL) {
5405 err = EAGAIN;
5406 fg_drop(fp);
5407 goto out;
5408 }
39037602 5409
d1ecb069
A
5410 /* Add an entry. Deallocates port on failure. */
5411 name = ipc_port_copyout_send(fileport, get_task_ipcspace(p->task));
5412 if (!MACH_PORT_VALID(name)) {
5413 err = EINVAL;
5414 goto out;
39037602
A
5415 }
5416
d1ecb069
A
5417 err = copyout(&name, user_portaddr, sizeof(mach_port_name_t));
5418 if (err != 0) {
5419 goto out;
5420 }
5421
5422 /* Tag the fileglob for debugging purposes */
5423 lck_mtx_lock_spin(&fg->fg_lock);
5424 fg->fg_lflags |= FG_PORTMADE;
5425 lck_mtx_unlock(&fg->fg_lock);
5426
5427 fp_drop(p, fd, fp, 0);
5428
5429 return 0;
5430
3e170ce0
A
5431out_unlock:
5432 proc_fdunlock(p);
d1ecb069
A
5433out:
5434 if (MACH_PORT_VALID(name)) {
5435 /* Don't care if another thread races us to deallocate the entry */
5436 (void) mach_port_deallocate(get_task_ipcspace(p->task), name);
5437 }
5438
5439 if (fp != FILEPROC_NULL) {
5440 fp_drop(p, fd, fp, 0);
5441 }
5442
5443 return err;
5444}
5445
5446void
5447fileport_releasefg(struct fileglob *fg)
5448{
5449 (void)closef_locked(NULL, fg, PROC_NULL);
5450
5451 return;
5452}
5453
5454
5455/*
5456 * fileport_makefd
5457 *
5458 * Description: Obtain the file descriptor for a given Mach send right.
5459 *
5460 * Parameters: p Process calling fileport
5461 * uap->port Name of send right to file port.
5462 *
5463 * Returns: 0 Success
5464 * EINVAL Invalid Mach port name, or port is not for a file.
5465 * fdalloc:EMFILE
5466 * fdalloc:ENOMEM Unable to allocate fileproc or extend file table.
5467 *
5468 * Implicit returns:
5469 * *retval (modified) The new descriptor
5470 */
5471int
5472fileport_makefd(proc_t p, struct fileport_makefd_args *uap, int32_t *retval)
5473{
5474 struct fileglob *fg;
5475 struct fileproc *fp = FILEPROC_NULL;
5476 ipc_port_t port = IPC_PORT_NULL;
5477 mach_port_name_t send = uap->port;
5478 kern_return_t res;
5479 int fd;
5480 int err;
5481
5482 res = ipc_object_copyin(get_task_ipcspace(p->task),
5483 send, MACH_MSG_TYPE_COPY_SEND, &port);
5484
5485 if (res != KERN_SUCCESS) {
5486 err = EINVAL;
5487 goto out;
5488 }
5489
5490 fg = fileport_port_to_fileglob(port);
5491 if (fg == NULL) {
5492 err = EINVAL;
5493 goto out;
5494 }
6d2010ae 5495
39236c6e 5496 fp = fileproc_alloc_init(NULL);
d1ecb069
A
5497 if (fp == FILEPROC_NULL) {
5498 err = ENOMEM;
5499 goto out;
5500 }
5501
d1ecb069
A
5502 fp->f_fglob = fg;
5503 fg_ref(fp);
5504
5505 proc_fdlock(p);
5506 err = fdalloc(p, 0, &fd);
5507 if (err != 0) {
5508 proc_fdunlock(p);
5ba3f43e 5509 fg_drop(fp);
d1ecb069
A
5510 goto out;
5511 }
6d2010ae 5512 *fdflags(p, fd) |= UF_EXCLOSE;
d1ecb069
A
5513
5514 procfdtbl_releasefd(p, fd, fp);
5515 proc_fdunlock(p);
5516
5517 *retval = fd;
5518 err = 0;
5519out:
5520 if ((fp != NULL) && (0 != err)) {
39236c6e 5521 fileproc_free(fp);
39037602 5522 }
d1ecb069
A
5523
5524 if (IPC_PORT_NULL != port) {
5525 ipc_port_release_send(port);
5526 }
5527
5528 return err;
5529}
d1ecb069
A
5530
5531
1c79356b 5532/*
2d21ac55 5533 * dupfdopen
1c79356b 5534 *
2d21ac55
A
5535 * Description: Duplicate the specified descriptor to a free descriptor;
5536 * this is the second half of fdopen(), above.
5537 *
5538 * Parameters: fdp filedesc pointer to fill in
5539 * indx fd to dup to
5540 * dfd fd to dup from
5541 * mode mode to set on new fd
5542 * error command code
5543 *
5544 * Returns: 0 Success
5545 * EBADF Source fd is bad
5546 * EACCES Requested mode not allowed
5547 * !0 'error', if not ENODEV or
5548 * ENXIO
5549 *
5550 * Notes: XXX This is not thread safe; see fdopen() above
1c79356b
A
5551 */
5552int
6d2010ae 5553dupfdopen(struct filedesc *fdp, int indx, int dfd, int flags, int error)
1c79356b 5554{
91447636
A
5555 struct fileproc *wfp;
5556 struct fileproc *fp;
2d21ac55
A
5557#if CONFIG_MACF
5558 int myerror;
5559#endif
5560 proc_t p = current_proc();
1c79356b
A
5561
5562 /*
5563 * If the to-be-dup'd fd number is greater than the allowed number
5564 * of file descriptors, or the fd to be dup'd has already been
5565 * closed, reject. Note, check for new == old is necessary as
5566 * falloc could allocate an already closed to-be-dup'd descriptor
5567 * as the new descriptor.
5568 */
91447636
A
5569 proc_fdlock(p);
5570
1c79356b 5571 fp = fdp->fd_ofiles[indx];
91447636 5572 if (dfd < 0 || dfd >= fdp->fd_nfiles ||
1c79356b 5573 (wfp = fdp->fd_ofiles[dfd]) == NULL || wfp == fp ||
91447636 5574 (fdp->fd_ofileflags[dfd] & UF_RESERVED)) {
1c79356b 5575
91447636
A
5576 proc_fdunlock(p);
5577 return (EBADF);
5578 }
2d21ac55
A
5579#if CONFIG_MACF
5580 myerror = mac_file_check_dup(proc_ucred(p), wfp->f_fglob, dfd);
5581 if (myerror) {
5582 proc_fdunlock(p);
5583 return (myerror);
5584 }
5585#endif
1c79356b
A
5586 /*
5587 * There are two cases of interest here.
5588 *
5589 * For ENODEV simply dup (dfd) to file descriptor
5590 * (indx) and return.
5591 *
5592 * For ENXIO steal away the file structure from (dfd) and
5593 * store it in (indx). (dfd) is effectively closed by
5594 * this operation.
5595 *
5596 * Any other error code is just returned.
5597 */
5598 switch (error) {
5599 case ENODEV:
39236c6e 5600 if (FP_ISGUARDED(wfp, GUARD_DUP)) {
39236c6e 5601 proc_fdunlock(p);
3e170ce0 5602 return (EPERM);
39236c6e
A
5603 }
5604
1c79356b
A
5605 /*
5606 * Check that the mode the file is being opened for is a
5607 * subset of the mode of the existing descriptor.
5608 */
6d2010ae 5609 if (((flags & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag) {
91447636 5610 proc_fdunlock(p);
1c79356b 5611 return (EACCES);
91447636 5612 }
1c79356b 5613 if (indx > fdp->fd_lastfile)
91447636
A
5614 fdp->fd_lastfile = indx;
5615 (void)fg_ref(wfp);
5616
5617 if (fp->f_fglob)
5618 fg_free(fp->f_fglob);
5619 fp->f_fglob = wfp->f_fglob;
5620
6d2010ae
A
5621 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd] |
5622 (flags & O_CLOEXEC) ? UF_EXCLOSE : 0;
91447636
A
5623
5624 proc_fdunlock(p);
1c79356b
A
5625 return (0);
5626
1c79356b 5627 default:
91447636 5628 proc_fdunlock(p);
1c79356b
A
5629 return (error);
5630 }
5631 /* NOTREACHED */
5632}
5633
2d21ac55
A
5634
5635/*
5636 * fg_ref
5637 *
5638 * Description: Add a reference to a fileglob by fileproc
5639 *
5640 * Parameters: fp fileproc containing fileglob
5641 * pointer
5642 *
5643 * Returns: void
5644 *
5645 * Notes: XXX Should use OSAddAtomic?
5646 */
91447636
A
5647void
5648fg_ref(struct fileproc * fp)
1c79356b 5649{
91447636
A
5650 struct fileglob *fg;
5651
5652 fg = fp->f_fglob;
5653
2d21ac55
A
5654 lck_mtx_lock_spin(&fg->fg_lock);
5655
5656#if DIAGNOSTIC
5657 if ((fp->f_flags & ~((unsigned int)FP_VALID_FLAGS)) != 0)
6d2010ae 5658 panic("fg_ref: invalid bits on fp %p", fp);
2d21ac55
A
5659
5660 if (fg->fg_count == 0)
6d2010ae
A
5661 panic("fg_ref: adding fgcount to zeroed fg: fp %p fg %p",
5662 fp, fg);
2d21ac55 5663#endif
91447636
A
5664 fg->fg_count++;
5665 lck_mtx_unlock(&fg->fg_lock);
1c79356b
A
5666}
5667
2d21ac55
A
5668
5669/*
5670 * fg_drop
5671 *
5672 * Description: Remove a reference to a fileglob by fileproc
5673 *
5674 * Parameters: fp fileproc containing fileglob
5675 * pointer
5676 *
5677 * Returns: void
5678 *
5679 * Notes: XXX Should use OSAddAtomic?
5680 */
91447636
A
5681void
5682fg_drop(struct fileproc * fp)
1c79356b 5683{
91447636
A
5684 struct fileglob *fg;
5685
5686 fg = fp->f_fglob;
2d21ac55 5687 lck_mtx_lock_spin(&fg->fg_lock);
91447636
A
5688 fg->fg_count--;
5689 lck_mtx_unlock(&fg->fg_lock);
1c79356b
A
5690}
5691
39236c6e 5692#if SOCKETS
2d21ac55 5693/*
3e170ce0 5694 * fg_insertuipc_mark
2d21ac55 5695 *
3e170ce0
A
5696 * Description: Mark fileglob for insertion onto message queue if needed
5697 * Also takes fileglob reference
2d21ac55 5698 *
3e170ce0 5699 * Parameters: fg Fileglob pointer to insert
2d21ac55 5700 *
3e170ce0 5701 * Returns: true, if the fileglob needs to be inserted onto msg queue
2d21ac55
A
5702 *
5703 * Locks: Takes and drops fg_lock, potentially many times
5704 */
3e170ce0
A
5705boolean_t
5706fg_insertuipc_mark(struct fileglob * fg)
9bccf70c 5707{
3e170ce0 5708 boolean_t insert = FALSE;
9bccf70c 5709
2d21ac55 5710 lck_mtx_lock_spin(&fg->fg_lock);
91447636 5711 while (fg->fg_lflags & FG_RMMSGQ) {
2d21ac55
A
5712 lck_mtx_convert_spin(&fg->fg_lock);
5713
91447636 5714 fg->fg_lflags |= FG_WRMMSGQ;
2d21ac55 5715 msleep(&fg->fg_lflags, &fg->fg_lock, 0, "fg_insertuipc", NULL);
91447636 5716 }
9bccf70c 5717
91447636
A
5718 fg->fg_count++;
5719 fg->fg_msgcount++;
5720 if (fg->fg_msgcount == 1) {
5721 fg->fg_lflags |= FG_INSMSGQ;
3e170ce0 5722 insert = TRUE;
9bccf70c 5723 }
91447636 5724 lck_mtx_unlock(&fg->fg_lock);
3e170ce0
A
5725 return (insert);
5726}
91447636 5727
3e170ce0
A
5728/*
5729 * fg_insertuipc
5730 *
5731 * Description: Insert marked fileglob onto message queue
5732 *
5733 * Parameters: fg Fileglob pointer to insert
5734 *
5735 * Returns: void
5736 *
5737 * Locks: Takes and drops fg_lock & uipc_lock
5738 * DO NOT call this function with proc_fdlock held as unp_gc()
5739 * can potentially try to acquire proc_fdlock, which can result
5740 * in a deadlock if this function is in unp_gc_wait().
5741 */
5742void
5743fg_insertuipc(struct fileglob * fg)
5744{
5745 if (fg->fg_lflags & FG_INSMSGQ) {
2d21ac55 5746 lck_mtx_lock_spin(uipc_lock);
6601e61a 5747 unp_gc_wait();
91447636
A
5748 LIST_INSERT_HEAD(&fmsghead, fg, f_msglist);
5749 lck_mtx_unlock(uipc_lock);
5750 lck_mtx_lock(&fg->fg_lock);
5751 fg->fg_lflags &= ~FG_INSMSGQ;
5752 if (fg->fg_lflags & FG_WINSMSGQ) {
5753 fg->fg_lflags &= ~FG_WINSMSGQ;
5754 wakeup(&fg->fg_lflags);
5755 }
5756 lck_mtx_unlock(&fg->fg_lock);
5757 }
91447636 5758}
9bccf70c 5759
2d21ac55 5760/*
3e170ce0 5761 * fg_removeuipc_mark
2d21ac55 5762 *
3e170ce0
A
5763 * Description: Mark the fileglob for removal from message queue if needed
5764 * Also releases fileglob message queue reference
2d21ac55 5765 *
3e170ce0 5766 * Parameters: fg Fileglob pointer to remove
2d21ac55 5767 *
3e170ce0 5768 * Returns: true, if the fileglob needs to be removed from msg queue
2d21ac55
A
5769 *
5770 * Locks: Takes and drops fg_lock, potentially many times
5771 */
3e170ce0
A
5772boolean_t
5773fg_removeuipc_mark(struct fileglob * fg)
91447636 5774{
3e170ce0 5775 boolean_t remove = FALSE;
91447636 5776
2d21ac55 5777 lck_mtx_lock_spin(&fg->fg_lock);
91447636 5778 while (fg->fg_lflags & FG_INSMSGQ) {
2d21ac55
A
5779 lck_mtx_convert_spin(&fg->fg_lock);
5780
91447636 5781 fg->fg_lflags |= FG_WINSMSGQ;
2d21ac55 5782 msleep(&fg->fg_lflags, &fg->fg_lock, 0, "fg_removeuipc", NULL);
91447636
A
5783 }
5784 fg->fg_msgcount--;
5785 if (fg->fg_msgcount == 0) {
5786 fg->fg_lflags |= FG_RMMSGQ;
3e170ce0 5787 remove = TRUE;
9bccf70c 5788 }
91447636 5789 lck_mtx_unlock(&fg->fg_lock);
3e170ce0
A
5790 return (remove);
5791}
91447636 5792
3e170ce0
A
5793/*
5794 * fg_removeuipc
5795 *
5796 * Description: Remove marked fileglob from message queue
5797 *
5798 * Parameters: fg Fileglob pointer to remove
5799 *
5800 * Returns: void
5801 *
5802 * Locks: Takes and drops fg_lock & uipc_lock
5803 * DO NOT call this function with proc_fdlock held as unp_gc()
5804 * can potentially try to acquire proc_fdlock, which can result
5805 * in a deadlock if this function is in unp_gc_wait().
5806 */
5807void
5808fg_removeuipc(struct fileglob * fg)
5809{
5810 if (fg->fg_lflags & FG_RMMSGQ) {
2d21ac55 5811 lck_mtx_lock_spin(uipc_lock);
6601e61a 5812 unp_gc_wait();
91447636
A
5813 LIST_REMOVE(fg, f_msglist);
5814 lck_mtx_unlock(uipc_lock);
5815 lck_mtx_lock(&fg->fg_lock);
5816 fg->fg_lflags &= ~FG_RMMSGQ;
5817 if (fg->fg_lflags & FG_WRMMSGQ) {
5818 fg->fg_lflags &= ~FG_WRMMSGQ;
5819 wakeup(&fg->fg_lflags);
5820 }
5821 lck_mtx_unlock(&fg->fg_lock);
5822 }
5823}
39236c6e 5824#endif /* SOCKETS */
91447636 5825
2d21ac55
A
5826/*
5827 * fo_read
5828 *
5829 * Description: Generic fileops read indirected through the fileops pointer
5830 * in the fileproc structure
5831 *
5832 * Parameters: fp fileproc structure pointer
5833 * uio user I/O structure pointer
5834 * flags FOF_ flags
5835 * ctx VFS context for operation
5836 *
5837 * Returns: 0 Success
5838 * !0 Errno from read
5839 */
91447636 5840int
2d21ac55 5841fo_read(struct fileproc *fp, struct uio *uio, int flags, vfs_context_t ctx)
91447636 5842{
2d21ac55 5843 return ((*fp->f_ops->fo_read)(fp, uio, flags, ctx));
91447636
A
5844}
5845
2d21ac55
A
5846
5847/*
5848 * fo_write
5849 *
5850 * Description: Generic fileops write indirected through the fileops pointer
5851 * in the fileproc structure
5852 *
5853 * Parameters: fp fileproc structure pointer
5854 * uio user I/O structure pointer
5855 * flags FOF_ flags
5856 * ctx VFS context for operation
5857 *
5858 * Returns: 0 Success
5859 * !0 Errno from write
5860 */
91447636 5861int
2d21ac55 5862fo_write(struct fileproc *fp, struct uio *uio, int flags, vfs_context_t ctx)
91447636 5863{
2d21ac55 5864 return((*fp->f_ops->fo_write)(fp, uio, flags, ctx));
91447636
A
5865}
5866
2d21ac55
A
5867
5868/*
5869 * fo_ioctl
5870 *
5871 * Description: Generic fileops ioctl indirected through the fileops pointer
5872 * in the fileproc structure
5873 *
5874 * Parameters: fp fileproc structure pointer
5875 * com ioctl command
5876 * data pointer to internalized copy
5877 * of user space ioctl command
5878 * parameter data in kernel space
5879 * ctx VFS context for operation
5880 *
5881 * Returns: 0 Success
5882 * !0 Errno from ioctl
5883 *
5884 * Locks: The caller is assumed to have held the proc_fdlock; this
5885 * function releases and reacquires this lock. If the caller
5886 * accesses data protected by this lock prior to calling this
5887 * function, it will need to revalidate/reacquire any cached
5888 * protected data obtained prior to the call.
5889 */
39037602 5890int
2d21ac55 5891fo_ioctl(struct fileproc *fp, u_long com, caddr_t data, vfs_context_t ctx)
91447636 5892{
2d21ac55 5893 int error;
91447636 5894
2d21ac55
A
5895 proc_fdunlock(vfs_context_proc(ctx));
5896 error = (*fp->f_ops->fo_ioctl)(fp, com, data, ctx);
5897 proc_fdlock(vfs_context_proc(ctx));
91447636 5898 return(error);
39037602 5899}
91447636 5900
2d21ac55
A
5901
5902/*
5903 * fo_select
5904 *
5905 * Description: Generic fileops select indirected through the fileops pointer
5906 * in the fileproc structure
5907 *
5908 * Parameters: fp fileproc structure pointer
5909 * which select which
5910 * wql pointer to wait queue list
5911 * ctx VFS context for operation
5912 *
5913 * Returns: 0 Success
5914 * !0 Errno from select
5915 */
91447636 5916int
2d21ac55 5917fo_select(struct fileproc *fp, int which, void *wql, vfs_context_t ctx)
39037602 5918{
2d21ac55 5919 return((*fp->f_ops->fo_select)(fp, which, wql, ctx));
91447636
A
5920}
5921
2d21ac55
A
5922
5923/*
5924 * fo_close
5925 *
5926 * Description: Generic fileops close indirected through the fileops pointer
5927 * in the fileproc structure
5928 *
5929 * Parameters: fp fileproc structure pointer for
5930 * file to close
5931 * ctx VFS context for operation
5932 *
5933 * Returns: 0 Success
5934 * !0 Errno from close
5935 */
91447636 5936int
2d21ac55 5937fo_close(struct fileglob *fg, vfs_context_t ctx)
39037602 5938{
2d21ac55 5939 return((*fg->fg_ops->fo_close)(fg, ctx));
9bccf70c
A
5940}
5941
2d21ac55
A
5942
5943/*
5944 * fo_kqfilter
5945 *
5946 * Description: Generic fileops kqueue filter indirected through the fileops
5947 * pointer in the fileproc structure
5948 *
5949 * Parameters: fp fileproc structure pointer
5950 * kn pointer to knote to filter on
5951 * ctx VFS context for operation
5952 *
39037602
A
5953 * Returns: (kn->kn_flags & EV_ERROR) error in kn->kn_data
5954 * 0 Filter is not active
5955 * !0 Filter is active
2d21ac55 5956 */
1c79356b 5957int
5ba3f43e
A
5958fo_kqfilter(struct fileproc *fp, struct knote *kn,
5959 struct kevent_internal_s *kev, vfs_context_t ctx)
1c79356b 5960{
5ba3f43e 5961 return ((*fp->f_ops->fo_kqfilter)(fp, kn, kev, ctx));
1c79356b 5962}
b0d623f7
A
5963
5964/*
5965 * The ability to send a file descriptor to another
5966 * process is opt-in by file type.
5967 */
5968boolean_t
39037602 5969file_issendable(proc_t p, struct fileproc *fp)
b0d623f7 5970{
3e170ce0
A
5971 proc_fdlock_assert(p, LCK_MTX_ASSERT_OWNED);
5972
5973 switch (fp->f_type) {
5974 case DTYPE_VNODE:
5975 case DTYPE_SOCKET:
5976 case DTYPE_PIPE:
5977 case DTYPE_PSXSHM:
5ba3f43e 5978 case DTYPE_NETPOLICY:
3e170ce0
A
5979 return (0 == (fp->f_fglob->fg_lflags & FG_CONFINED));
5980 default:
5981 /* DTYPE_KQUEUE, DTYPE_FSEVENTS, DTYPE_PSXSEM */
5982 return FALSE;
b0d623f7
A
5983 }
5984}
39236c6e
A
5985
5986
5987struct fileproc *
5988fileproc_alloc_init(__unused void *arg)
5989{
5990 struct fileproc *fp;
5991
5992 MALLOC_ZONE(fp, struct fileproc *, sizeof (*fp), M_FILEPROC, M_WAITOK);
5993 if (fp)
5994 bzero(fp, sizeof (*fp));
5995
5996 return (fp);
5997}
5998
5999void
6000fileproc_free(struct fileproc *fp)
6001{
6002 switch (FILEPROC_TYPE(fp)) {
6003 case FTYPE_SIMPLE:
6004 FREE_ZONE(fp, sizeof (*fp), M_FILEPROC);
6005 break;
6006 case FTYPE_GUARDED:
6007 guarded_fileproc_free(fp);
6008 break;
6009 default:
6010 panic("%s: corrupt fp %p flags %x", __func__, fp, fp->f_flags);
6011 }
6012}