]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/kern_descrip.c
xnu-1228.9.59.tar.gz
[apple/xnu.git] / bsd / kern / kern_descrip.c
CommitLineData
1c79356b 1/*
2d21ac55 2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
5d5c5d0d 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 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.
8f6c56a5 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.
17 *
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.
8f6c56a5 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>
1c79356b
A
83#include <sys/socket.h>
84#include <sys/socketvar.h>
85#include <sys/stat.h>
86#include <sys/ioctl.h>
87#include <sys/fcntl.h>
88#include <sys/malloc.h>
91447636 89#include <sys/mman.h>
1c79356b
A
90#include <sys/syslog.h>
91#include <sys/unistd.h>
92#include <sys/resourcevar.h>
55e303ae 93#include <sys/aio_kern.h>
91447636
A
94#include <sys/ev.h>
95#include <kern/lock.h>
e5568f75
A
96
97#include <bsm/audit_kernel.h>
1c79356b 98
91447636
A
99#include <sys/mount_internal.h>
100#include <sys/kdebug.h>
101#include <sys/sysproto.h>
102#include <sys/pipe.h>
103#include <kern/kern_types.h>
104#include <kern/kalloc.h>
b36670ce 105#include <libkern/OSAtomic.h>
91447636 106
593a1d5f 107#include <sys/ubc_internal.h>
2d21ac55 108
91447636
A
109struct psemnode;
110struct pshmnode;
111
2d21ac55
A
112int fdopen(dev_t dev, int mode, int type, proc_t p);
113int finishdup(proc_t p, struct filedesc *fdp, int old, int new, register_t *retval);
91447636 114
2d21ac55
A
115int falloc_locked(proc_t p, struct fileproc **resultfp, int *resultfd, vfs_context_t ctx, int locked);
116int fdgetf_noref(proc_t p, int fd, struct fileproc **resultfp);
91447636
A
117void fg_drop(struct fileproc * fp);
118void fg_free(struct fileglob *fg);
119void fg_ref(struct fileproc * fp);
91447636 120
2d21ac55
A
121/* flags for close_internal_locked */
122#define FD_DUP2RESV 1
123static int close_internal_locked(struct proc *p, int fd, struct fileproc *fp, int flags);
124
125static int closef_finish(struct fileproc *fp, struct fileglob *fg, proc_t p, vfs_context_t ctx);
126
127/* We don't want these exported */
128__private_extern__
129int open1(vfs_context_t, struct nameidata *, int, struct vnode_attr *, register_t *);
130
131__private_extern__
132int unlink1(vfs_context_t, struct nameidata *, int);
133
134static void _fdrelse(struct proc * p, int fd);
91447636 135
2d21ac55
A
136
137extern void file_lock_init(void) __attribute__((section("__TEXT, initcode")));
138extern int kqueue_stat(struct fileproc *fp, void *ub, int isstat4, proc_t p);
139#if SOCKETS
140extern int soo_stat(struct socket *so, void *ub, int isstat64);
141#endif /* SOCKETS */
91447636
A
142
143extern kauth_scope_t kauth_scope_fileop;
144
593a1d5f
A
145extern int cs_debug;
146
91447636
A
147#define f_flag f_fglob->fg_flag
148#define f_type f_fglob->fg_type
149#define f_msgcount f_fglob->fg_msgcount
150#define f_cred f_fglob->fg_cred
151#define f_ops f_fglob->fg_ops
152#define f_offset f_fglob->fg_offset
153#define f_data f_fglob->fg_data
1c79356b
A
154/*
155 * Descriptor management.
156 */
157struct filelist filehead; /* head of list of open files */
91447636
A
158struct fmsglist fmsghead; /* head of list of open files */
159struct fmsglist fmsg_ithead; /* head of list of open files */
1c79356b
A
160int nfiles; /* actual number of open files */
161
91447636
A
162
163lck_grp_attr_t * file_lck_grp_attr;
164lck_grp_t * file_lck_grp;
165lck_attr_t * file_lck_attr;
166
167lck_mtx_t * uipc_lock;
91447636
A
168lck_mtx_t * file_flist_lock;
169
170
2d21ac55
A
171/*
172 * file_lock_init
173 *
174 * Description: Initialize the file lock group and the uipc and flist locks
175 *
176 * Parameters: (void)
177 *
178 * Returns: void
179 *
180 * Notes: Called at system startup from bsd_init().
181 */
91447636
A
182void
183file_lock_init(void)
184{
91447636
A
185 /* allocate file lock group attribute and group */
186 file_lck_grp_attr= lck_grp_attr_alloc_init();
91447636
A
187
188 file_lck_grp = lck_grp_alloc_init("file", file_lck_grp_attr);
189
190 /* Allocate file lock attribute */
191 file_lck_attr = lck_attr_alloc_init();
91447636
A
192
193 uipc_lock = lck_mtx_alloc_init(file_lck_grp, file_lck_attr);
91447636 194 file_flist_lock = lck_mtx_alloc_init(file_lck_grp, file_lck_attr);
2d21ac55 195}
91447636 196
91447636 197
2d21ac55
A
198/*
199 * proc_fdlock, proc_fdlock_spin
200 *
201 * Description: Lock to control access to the per process struct fileproc
202 * and struct filedesc
203 *
204 * Parameters: p Process to take the lock on
205 *
206 * Returns: void
207 *
208 * Notes: The lock is initialized in forkproc() and destroyed in
209 * reap_child_process().
210 */
211void
212proc_fdlock(proc_t p)
213{
214 lck_mtx_lock(&p->p_fdmlock);
91447636
A
215}
216
2d21ac55
A
217void
218proc_fdlock_spin(proc_t p)
219{
220 lck_mtx_lock_spin(&p->p_fdmlock);
221}
91447636
A
222
223void
2d21ac55 224proc_fdlock_assert(proc_t p, int assertflags)
91447636 225{
2d21ac55 226 lck_mtx_assert(&p->p_fdmlock, assertflags);
91447636
A
227}
228
2d21ac55
A
229
230/*
231 * proc_fdunlock
232 *
233 * Description: Unlock the lock previously locked by a call to proc_fdlock()
234 *
235 * Parameters: p Process to drop the lock on
236 *
237 * Returns: void
238 */
91447636 239void
2d21ac55 240proc_fdunlock(proc_t p)
91447636
A
241{
242 lck_mtx_unlock(&p->p_fdmlock);
243}
9bccf70c 244
2d21ac55 245
1c79356b
A
246/*
247 * System calls on descriptors.
248 */
91447636 249
2d21ac55
A
250
251/*
252 * getdtablesize
253 *
254 * Description: Returns the per process maximum size of the descriptor table
255 *
256 * Parameters: p Process being queried
257 * retval Pointer to the call return area
258 *
259 * Returns: 0 Success
260 *
261 * Implicit returns:
262 * *retval (modified) Size of dtable
263 */
1c79356b 264int
2d21ac55 265getdtablesize(proc_t p, __unused struct getdtablesize_args *uap, register_t *retval)
1c79356b 266{
2d21ac55 267 proc_fdlock_spin(p);
1c79356b 268 *retval = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
91447636
A
269 proc_fdunlock(p);
270
1c79356b
A
271 return (0);
272}
273
1c79356b 274
6601e61a
A
275void
276procfdtbl_reservefd(struct proc * p, int fd)
277{
278 p->p_fd->fd_ofiles[fd] = NULL;
279 p->p_fd->fd_ofileflags[fd] |= UF_RESERVED;
280}
281
282void
283procfdtbl_markclosefd(struct proc * p, int fd)
284{
285 p->p_fd->fd_ofileflags[fd] |= (UF_RESERVED | UF_CLOSING);
286}
287
288void
289procfdtbl_releasefd(struct proc * p, int fd, struct fileproc * fp)
290{
291 if (fp != NULL)
292 p->p_fd->fd_ofiles[fd] = fp;
293 p->p_fd->fd_ofileflags[fd] &= ~UF_RESERVED;
294 if ((p->p_fd->fd_ofileflags[fd] & UF_RESVWAIT) == UF_RESVWAIT) {
295 p->p_fd->fd_ofileflags[fd] &= ~UF_RESVWAIT;
296 wakeup(&p->p_fd);
297 }
298}
299
300void
301procfdtbl_waitfd(struct proc * p, int fd)
302{
303 p->p_fd->fd_ofileflags[fd] |= UF_RESVWAIT;
304 msleep(&p->p_fd, &p->p_fdmlock, PRIBIO, "ftbl_waitfd", NULL);
305}
306
307
308void
309procfdtbl_clearfd(struct proc * p, int fd)
310{
311 int waiting;
312
313 waiting = (p->p_fd->fd_ofileflags[fd] & UF_RESVWAIT);
314 p->p_fd->fd_ofiles[fd] = NULL;
315 p->p_fd->fd_ofileflags[fd] = 0;
316 if ( waiting == UF_RESVWAIT) {
317 wakeup(&p->p_fd);
318 }
319}
320
2d21ac55
A
321/*
322 * _fdrelse
323 *
324 * Description: Inline utility function to free an fd in a filedesc
325 *
326 * Parameters: fdp Pointer to filedesc fd lies in
327 * fd fd to free
328 * reserv fd should be reserved
329 *
330 * Returns: void
331 *
332 * Locks: Assumes proc_fdlock for process pointing to fdp is held by
333 * the caller
334 */
335static void
336_fdrelse(struct proc * p, int fd)
1c79356b 337{
2d21ac55
A
338 struct filedesc *fdp = p->p_fd;
339 int nfd = 0;
6601e61a 340
1c79356b
A
341 if (fd < fdp->fd_freefile)
342 fdp->fd_freefile = fd;
343#if DIAGNOSTIC
344 if (fd > fdp->fd_lastfile)
2d21ac55 345 panic("fdrelse: fd_lastfile inconsistent");
1c79356b 346#endif
6601e61a 347 procfdtbl_clearfd(p, fd);
91447636 348
6601e61a
A
349 while ((nfd = fdp->fd_lastfile) > 0 &&
350 fdp->fd_ofiles[nfd] == NULL &&
351 !(fdp->fd_ofileflags[nfd] & UF_RESERVED))
1c79356b
A
352 fdp->fd_lastfile--;
353}
354
2d21ac55 355
1c79356b 356/*
2d21ac55
A
357 * dup
358 *
359 * Description: Duplicate a file descriptor.
360 *
361 * Parameters: p Process performing the dup
362 * uap->fd The fd to dup
363 * retval Pointer to the call return area
364 *
365 * Returns: 0 Success
366 * !0 Errno
367 *
368 * Implicit returns:
369 * *retval (modified) The new descriptor
1c79356b 370 */
1c79356b 371int
2d21ac55 372dup(proc_t p, struct dup_args *uap, register_t *retval)
1c79356b 373{
2d21ac55
A
374 struct filedesc *fdp = p->p_fd;
375 int old = uap->fd;
1c79356b 376 int new, error;
91447636 377 struct fileproc *fp;
1c79356b 378
91447636
A
379 proc_fdlock(p);
380 if ( (error = fp_lookup(p, old, &fp, 1)) ) {
381 proc_fdunlock(p);
382 return(error);
383 }
384 if ( (error = fdalloc(p, 0, &new)) ) {
385 fp_drop(p, old, fp, 1);
386 proc_fdunlock(p);
1c79356b 387 return (error);
91447636
A
388 }
389 error = finishdup(p, fdp, old, new, retval);
390 fp_drop(p, old, fp, 1);
391 proc_fdunlock(p);
392
393 return (error);
1c79356b
A
394}
395
2d21ac55 396
1c79356b 397/*
2d21ac55
A
398 * dup2
399 *
400 * Description: Duplicate a file descriptor to a particular value.
401 *
402 * Parameters: p Process performing the dup
403 * uap->fd The fd to dup
404 * uap->to The fd to dup it to
405 * retval Pointer to the call return area
406 *
407 * Returns: 0 Success
408 * !0 Errno
409 *
410 * Implicit returns:
411 * *retval (modified) The new descriptor
1c79356b 412 */
1c79356b 413int
2d21ac55 414dup2(proc_t p, struct dup2_args *uap, register_t *retval)
1c79356b 415{
2d21ac55
A
416 struct filedesc *fdp = p->p_fd;
417 int old = uap->from, new = uap->to;
1c79356b 418 int i, error;
6601e61a 419 struct fileproc *fp, *nfp;
1c79356b 420
91447636
A
421 proc_fdlock(p);
422
6601e61a 423startover:
91447636
A
424 if ( (error = fp_lookup(p, old, &fp, 1)) ) {
425 proc_fdunlock(p);
426 return(error);
427 }
428 if (new < 0 ||
2d21ac55 429 (rlim_t)new >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
91447636
A
430 new >= maxfiles) {
431 fp_drop(p, old, fp, 1);
432 proc_fdunlock(p);
1c79356b 433 return (EBADF);
91447636 434 }
1c79356b 435 if (old == new) {
91447636 436 fp_drop(p, old, fp, 1);
1c79356b 437 *retval = new;
91447636 438 proc_fdunlock(p);
1c79356b
A
439 return (0);
440 }
91447636
A
441 if (new < 0 || new >= fdp->fd_nfiles) {
442 if ( (error = fdalloc(p, new, &i)) ) {
443 fp_drop(p, old, fp, 1);
444 proc_fdunlock(p);
1c79356b 445 return (error);
91447636 446 }
1c79356b 447 if (new != i) {
2d21ac55 448 fdrelse(p, i);
1c79356b
A
449 goto closeit;
450 }
fa4905b1 451 } else {
1c79356b 452closeit:
6601e61a
A
453 while ((fdp->fd_ofileflags[new] & UF_RESERVED) == UF_RESERVED) {
454 fp_drop(p, old, fp, 1);
455 procfdtbl_waitfd(p, new);
2d21ac55
A
456#if DIAGNOSTIC
457 proc_fdlock_assert(p, LCK_MTX_ASSERT_OWNED);
458#endif
6601e61a 459 goto startover;
91447636
A
460 }
461
6601e61a
A
462 if ((fdp->fd_ofiles[new] != NULL) && ((error = fp_lookup(p, new, &nfp, 1)) == 0)) {
463 fp_drop(p, old, fp, 1);
2d21ac55
A
464 (void)close_internal_locked(p, new, nfp, FD_DUP2RESV);
465#if DIAGNOSTIC
466 proc_fdlock_assert(p, LCK_MTX_ASSERT_OWNED);
467#endif
6601e61a
A
468 procfdtbl_clearfd(p, new);
469 goto startover;
470 } else {
2d21ac55
A
471#if DIAGNOSTIC
472 if (fdp->fd_ofiles[new] != NULL)
473 panic("dup2: unable to get ref on a fileproc %d\n", new);
474#endif
6601e61a 475 procfdtbl_reservefd(p, new);
1c79356b 476 }
2d21ac55
A
477
478#if DIAGNOSTIC
479 proc_fdlock_assert(p, LCK_MTX_ASSERT_OWNED);
480#endif
481
1c79356b 482 }
2d21ac55
A
483#if DIAGNOSTIC
484 if (fdp->fd_ofiles[new] != 0)
485 panic("dup2-1: overwriting fd_ofiles with new %d\n", new);
486 if ((fdp->fd_ofileflags[new] & UF_RESERVED) == 0)
487 panic("dup2-1: unreserved fileflags with new %d\n", new);
488#endif
91447636
A
489 error = finishdup(p, fdp, old, new, retval);
490 fp_drop(p, old, fp, 1);
491 proc_fdunlock(p);
492
493 return(error);
1c79356b
A
494}
495
2d21ac55
A
496
497/*
498 * fcntl
499 *
500 * Description: The file control system call.
501 *
502 * Parameters: p Process performing the fcntl
503 * uap->fd The fd to operate against
504 * uap->cmd The command to perform
505 * uap->arg Pointer to the command argument
506 * retval Pointer to the call return area
507 *
508 * Returns: 0 Success
509 * !0 Errno (see fcntl_nocancel)
510 *
511 * Implicit returns:
512 * *retval (modified) fcntl return value (if any)
513 *
514 * Notes: This system call differs from fcntl_nocancel() in that it
515 * tests for cancellation prior to performing a potentially
516 * blocking operation.
517 */
518int
519fcntl(proc_t p, struct fcntl_args *uap, register_t *retval)
520{
521 __pthread_testcancel(1);
522 return(fcntl_nocancel(p, (struct fcntl_nocancel_args *)uap, retval));
523}
524
525
1c79356b 526/*
2d21ac55
A
527 * fcntl_nocancel
528 *
529 * Description: A non-cancel-testing file control system call.
530 *
531 * Parameters: p Process performing the fcntl
532 * uap->fd The fd to operate against
533 * uap->cmd The command to perform
534 * uap->arg Pointer to the command argument
535 * retval Pointer to the call return area
536 *
537 * Returns: 0 Success
538 * EINVAL
539 * fp_lookup:EBADF Bad file descriptor
540 * [F_DUPFD]
541 * fdalloc:EMFILE
542 * fdalloc:ENOMEM
543 * finishdup:EBADF
544 * finishdup:ENOMEM
545 * [F_SETOWN]
546 * ESRCH
547 * [F_SETLK]
548 * EBADF
549 * EOVERFLOW
550 * copyin:EFAULT
551 * vnode_getwithref:???
552 * VNOP_ADVLOCK:???
553 * [F_GETLK]
554 * EBADF
555 * EOVERFLOW
556 * copyin:EFAULT
557 * copyout:EFAULT
558 * vnode_getwithref:???
559 * VNOP_ADVLOCK:???
560 * [F_PREALLOCATE]
561 * EBADF
562 * EINVAL
563 * copyin:EFAULT
564 * copyout:EFAULT
565 * vnode_getwithref:???
566 * VNOP_ALLOCATE:???
567 * [F_SETSIZE,F_RDADVISE]
568 * EBADF
569 * copyin:EFAULT
570 * vnode_getwithref:???
571 * [F_RDAHEAD,F_NOCACHE]
572 * EBADF
573 * vnode_getwithref:???
574 * [???]
575 *
576 * Implicit returns:
577 * *retval (modified) fcntl return value (if any)
1c79356b 578 */
1c79356b 579int
2d21ac55 580fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, register_t *retval)
1c79356b
A
581{
582 int fd = uap->fd;
91447636
A
583 struct filedesc *fdp = p->p_fd;
584 struct fileproc *fp;
585 char *pop;
2d21ac55 586 struct vnode *vp = NULLVP; /* for AUDIT_ARG() at end */
1c79356b
A
587 int i, tmp, error, error2, flg = F_POSIX;
588 struct flock fl;
91447636
A
589 struct vfs_context context;
590 off_t offset;
1c79356b 591 int newmin;
91447636 592 daddr64_t lbn, bn;
1c79356b 593 int devBlockSize = 0;
91447636
A
594 unsigned int fflag;
595 user_addr_t argp;
1c79356b 596
55e303ae
A
597 AUDIT_ARG(fd, uap->fd);
598 AUDIT_ARG(cmd, uap->cmd);
91447636
A
599
600 proc_fdlock(p);
601 if ( (error = fp_lookup(p, fd, &fp, 1)) ) {
602 proc_fdunlock(p);
603 return(error);
604 }
2d21ac55 605 context.vc_thread = current_thread();
91447636
A
606 context.vc_ucred = fp->f_cred;
607 if (proc_is64bit(p)) {
608 argp = uap->arg;
609 }
610 else {
2d21ac55
A
611 /*
612 * Since the arg parameter is defined as a long but may be
613 * either a long or a pointer we must take care to handle
614 * sign extension issues. Our sys call munger will sign
615 * extend a long when we are called from a 32-bit process.
616 * Since we can never have an address greater than 32-bits
617 * from a 32-bit process we lop off the top 32-bits to avoid
618 * getting the wrong address
91447636
A
619 */
620 argp = CAST_USER_ADDR_T(uap->arg);
621 }
622
1c79356b 623 pop = &fdp->fd_ofileflags[fd];
55e303ae 624
2d21ac55
A
625#if CONFIG_MACF
626 error = mac_file_check_fcntl(proc_ucred(p), fp->f_fglob, uap->cmd,
627 uap->arg);
628 if (error)
629 goto out;
630#endif
631
1c79356b
A
632 switch (uap->cmd) {
633
634 case F_DUPFD:
91447636 635 newmin = CAST_DOWN(int, uap->arg);
1c79356b 636 if ((u_int)newmin >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
91447636
A
637 newmin >= maxfiles) {
638 error = EINVAL;
639 goto out;
640 }
641 if ( (error = fdalloc(p, newmin, &i)) )
642 goto out;
643 error = finishdup(p, fdp, fd, i, retval);
644 goto out;
1c79356b
A
645
646 case F_GETFD:
647 *retval = (*pop & UF_EXCLOSE)? 1 : 0;
91447636
A
648 error = 0;
649 goto out;
1c79356b
A
650
651 case F_SETFD:
652 *pop = (*pop &~ UF_EXCLOSE) |
91447636
A
653 (uap->arg & 1)? UF_EXCLOSE : 0;
654 error = 0;
655 goto out;
1c79356b
A
656
657 case F_GETFL:
658 *retval = OFLAGS(fp->f_flag);
91447636
A
659 error = 0;
660 goto out;
1c79356b
A
661
662 case F_SETFL:
663 fp->f_flag &= ~FCNTLFLAGS;
91447636
A
664 tmp = CAST_DOWN(int, uap->arg);
665 fp->f_flag |= FFLAGS(tmp) & FCNTLFLAGS;
1c79356b 666 tmp = fp->f_flag & FNONBLOCK;
2d21ac55 667 error = fo_ioctl(fp, FIONBIO, (caddr_t)&tmp, &context);
1c79356b 668 if (error)
91447636 669 goto out;
1c79356b 670 tmp = fp->f_flag & FASYNC;
2d21ac55 671 error = fo_ioctl(fp, FIOASYNC, (caddr_t)&tmp, &context);
1c79356b 672 if (!error)
91447636 673 goto out;
1c79356b
A
674 fp->f_flag &= ~FNONBLOCK;
675 tmp = 0;
2d21ac55 676 (void)fo_ioctl(fp, FIONBIO, (caddr_t)&tmp, &context);
91447636 677 goto out;
1c79356b
A
678
679 case F_GETOWN:
680 if (fp->f_type == DTYPE_SOCKET) {
681 *retval = ((struct socket *)fp->f_data)->so_pgid;
91447636
A
682 error = 0;
683 goto out;
1c79356b 684 }
2d21ac55 685 error = fo_ioctl(fp, (int)TIOCGPGRP, (caddr_t)retval, &context);
1c79356b 686 *retval = -*retval;
91447636 687 goto out;
1c79356b
A
688
689 case F_SETOWN:
91447636 690 tmp = CAST_DOWN(pid_t, uap->arg);
1c79356b 691 if (fp->f_type == DTYPE_SOCKET) {
91447636
A
692 ((struct socket *)fp->f_data)->so_pgid = tmp;
693 error =0;
694 goto out;
1c79356b 695 }
91447636 696 if (fp->f_type == DTYPE_PIPE) {
2d21ac55 697 error = fo_ioctl(fp, (int)TIOCSPGRP, (caddr_t)&tmp, &context);
91447636
A
698 goto out;
699 }
700
701 if (tmp <= 0) {
702 tmp = -tmp;
1c79356b 703 } else {
2d21ac55 704 proc_t p1 = proc_find(tmp);
91447636
A
705 if (p1 == 0) {
706 error = ESRCH;
707 goto out;
708 }
2d21ac55
A
709 tmp = (int)p1->p_pgrpid;
710 proc_rele(p1);
1c79356b 711 }
2d21ac55 712 error = fo_ioctl(fp, (int)TIOCSPGRP, (caddr_t)&tmp, &context);
91447636 713 goto out;
1c79356b
A
714
715 case F_SETLKW:
716 flg |= F_WAIT;
717 /* Fall into F_SETLK */
718
719 case F_SETLK:
91447636
A
720 if (fp->f_type != DTYPE_VNODE) {
721 error = EBADF;
722 goto out;
723 }
1c79356b 724 vp = (struct vnode *)fp->f_data;
ccc36f2f 725
91447636
A
726 fflag = fp->f_flag;
727 offset = fp->f_offset;
728 proc_fdunlock(p);
729
1c79356b 730 /* Copy in the lock structure */
2d21ac55 731 error = copyin(argp, (caddr_t)&fl, sizeof(fl));
91447636
A
732 if (error) {
733 goto outdrop;
734 }
2d21ac55
A
735
736 if ((fl.l_whence == SEEK_CUR) && (fl.l_start + offset < fl.l_start)) {
737 error = EOVERFLOW;
738 goto outdrop;
739 }
740
91447636
A
741 if ( (error = vnode_getwithref(vp)) ) {
742 goto outdrop;
743 }
1c79356b 744 if (fl.l_whence == SEEK_CUR)
91447636
A
745 fl.l_start += offset;
746
2d21ac55
A
747#if CONFIG_MACF
748 error = mac_file_check_lock(proc_ucred(p), fp->f_fglob,
749 F_SETLK, &fl);
750 if (error) {
751 (void)vnode_put(vp);
752 goto outdrop;
753 }
754#endif
1c79356b
A
755 switch (fl.l_type) {
756
757 case F_RDLCK:
91447636
A
758 if ((fflag & FREAD) == 0) {
759 (void)vnode_put(vp);
ccc36f2f 760 error = EBADF;
91447636
A
761 goto outdrop;
762 }
2d21ac55
A
763 // XXX UInt32 unsafe for LP64 kernel
764 OSBitOrAtomic(P_LADVLOCK, (UInt32 *)&p->p_ladvflag);
91447636
A
765 error = VNOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg, &context);
766 (void)vnode_put(vp);
767 goto outdrop;
1c79356b
A
768
769 case F_WRLCK:
91447636
A
770 if ((fflag & FWRITE) == 0) {
771 (void)vnode_put(vp);
ccc36f2f 772 error = EBADF;
91447636
A
773 goto outdrop;
774 }
2d21ac55
A
775 // XXX UInt32 unsafe for LP64 kernel
776 OSBitOrAtomic(P_LADVLOCK, (UInt32 *)&p->p_ladvflag);
91447636
A
777 error = VNOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg, &context);
778 (void)vnode_put(vp);
779 goto outdrop;
1c79356b
A
780
781 case F_UNLCK:
91447636
A
782 error = VNOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl,
783 F_POSIX, &context);
784 (void)vnode_put(vp);
785 goto outdrop;
1c79356b
A
786
787 default:
91447636 788 (void)vnode_put(vp);
ccc36f2f 789 error = EINVAL;
91447636 790 goto outdrop;
1c79356b
A
791 }
792
793 case F_GETLK:
91447636
A
794 if (fp->f_type != DTYPE_VNODE) {
795 error = EBADF;
796 goto out;
797 }
1c79356b 798 vp = (struct vnode *)fp->f_data;
ccc36f2f 799
91447636
A
800 offset = fp->f_offset;
801 proc_fdunlock(p);
802
1c79356b 803 /* Copy in the lock structure */
2d21ac55 804 error = copyin(argp, (caddr_t)&fl, sizeof(fl));
1c79356b 805 if (error)
91447636
A
806 goto outdrop;
807
2d21ac55
A
808 /* Check starting byte and ending byte for EOVERFLOW in SEEK_CUR */
809 /* and ending byte for EOVERFLOW in SEEK_SET */
810 if (((fl.l_whence == SEEK_CUR) &&
811 ((fl.l_start + offset < fl.l_start) ||
812 ((fl.l_len > 0) && (fl.l_start+offset + fl.l_len - 1 < fl.l_start+offset)))) ||
813 ((fl.l_whence == SEEK_SET) && (fl.l_len > 0) && (fl.l_start + fl.l_len - 1 < fl.l_start)))
814 {
815 /* lf_advlock doesn't check start/end for F_GETLK if file has no locks */
816 error = EOVERFLOW;
817 goto outdrop;
818 }
819
820 if ((fl.l_whence == SEEK_SET) && (fl.l_start < 0)) {
821 error = EINVAL;
822 goto outdrop;
823 }
824
825 switch (fl.l_type) {
826 case F_RDLCK:
827 case F_UNLCK:
828 case F_WRLCK:
829 break;
830 default:
831 error = EINVAL;
832 goto outdrop;
833 }
834
835 switch (fl.l_whence) {
836 case SEEK_CUR:
837 case SEEK_SET:
838 case SEEK_END:
839 break;
840 default:
841 error = EINVAL;
842 goto outdrop;
843 }
844
91447636
A
845 if ( (error = vnode_getwithref(vp)) == 0 ) {
846 if (fl.l_whence == SEEK_CUR)
847 fl.l_start += offset;
848
2d21ac55
A
849#if CONFIG_MACF
850 error = mac_file_check_lock(proc_ucred(p), fp->f_fglob,
851 F_GETLK, &fl);
852 if (error == 0)
853#endif
91447636
A
854 error = VNOP_ADVLOCK(vp, (caddr_t)p, F_GETLK, &fl, F_POSIX, &context);
855
856 (void)vnode_put(vp);
857
858 if (error == 0)
2d21ac55 859 error = copyout((caddr_t)&fl, argp, sizeof(fl));
91447636
A
860 }
861 goto outdrop;
862
863 case F_PREALLOCATE: {
864 fstore_t alloc_struct; /* structure for allocate command */
865 u_int32_t alloc_flags = 0;
866
867 if (fp->f_type != DTYPE_VNODE) {
868 error = EBADF;
869 goto out;
870 }
1c79356b 871
ccc36f2f 872 vp = (struct vnode *)fp->f_data;
91447636 873 proc_fdunlock(p);
9bccf70c
A
874
875 /* make sure that we have write permission */
ccc36f2f
A
876 if ((fp->f_flag & FWRITE) == 0) {
877 error = EBADF;
91447636 878 goto outdrop;
ccc36f2f 879 }
1c79356b 880
2d21ac55 881 error = copyin(argp, (caddr_t)&alloc_struct, sizeof(alloc_struct));
1c79356b 882 if (error)
91447636 883 goto outdrop;
1c79356b 884
9bccf70c 885 /* now set the space allocated to 0 */
1c79356b
A
886 alloc_struct.fst_bytesalloc = 0;
887
9bccf70c
A
888 /*
889 * Do some simple parameter checking
890 */
1c79356b
A
891
892 /* set up the flags */
893
894 alloc_flags |= PREALLOCATE;
895
9bccf70c 896 if (alloc_struct.fst_flags & F_ALLOCATECONTIG)
1c79356b 897 alloc_flags |= ALLOCATECONTIG;
1c79356b 898
9bccf70c
A
899 if (alloc_struct.fst_flags & F_ALLOCATEALL)
900 alloc_flags |= ALLOCATEALL;
1c79356b 901
9bccf70c
A
902 /*
903 * Do any position mode specific stuff. The only
904 * position mode supported now is PEOFPOSMODE
905 */
1c79356b
A
906
907 switch (alloc_struct.fst_posmode) {
908
909 case F_PEOFPOSMODE:
91447636 910 if (alloc_struct.fst_offset != 0) {
ccc36f2f 911 error = EINVAL;
91447636
A
912 goto outdrop;
913 }
914
915 alloc_flags |= ALLOCATEFROMPEOF;
1c79356b
A
916 break;
917
0b4e3aa0 918 case F_VOLPOSMODE:
91447636 919 if (alloc_struct.fst_offset <= 0) {
ccc36f2f 920 error = EINVAL;
91447636
A
921 goto outdrop;
922 }
923
924 alloc_flags |= ALLOCATEFROMVOL;
0b4e3aa0
A
925 break;
926
91447636 927 default: {
ccc36f2f 928 error = EINVAL;
91447636
A
929 goto outdrop;
930 }
1c79356b 931 }
91447636
A
932 if ( (error = vnode_getwithref(vp)) == 0 ) {
933 /*
934 * call allocate to get the space
935 */
936 error = VNOP_ALLOCATE(vp,alloc_struct.fst_length,alloc_flags,
937 &alloc_struct.fst_bytesalloc, alloc_struct.fst_offset,
938 &context);
939 (void)vnode_put(vp);
1c79356b 940
2d21ac55 941 error2 = copyout((caddr_t)&alloc_struct, argp, sizeof(alloc_struct));
1c79356b 942
91447636 943 if (error == 0)
ccc36f2f 944 error = error2;
1c79356b 945 }
91447636 946 goto outdrop;
1c79356b 947
91447636 948 }
9bccf70c 949 case F_SETSIZE:
91447636
A
950 if (fp->f_type != DTYPE_VNODE) {
951 error = EBADF;
952 goto out;
953 }
2d21ac55 954 vp = (struct vnode *)fp->f_data;
91447636 955 proc_fdunlock(p);
ccc36f2f 956
91447636 957 error = copyin(argp, (caddr_t)&offset, sizeof (off_t));
1c79356b 958 if (error)
91447636 959 goto outdrop;
1c79356b 960
2d21ac55
A
961 error = vnode_getwithref(vp);
962 if (error)
963 goto outdrop;
964
965#if CONFIG_MACF
966 error = mac_vnode_check_truncate(&context,
967 fp->f_fglob->fg_cred, vp);
968 if (error) {
969 (void)vnode_put(vp);
970 goto outdrop;
971 }
972#endif
9bccf70c
A
973 /*
974 * Make sure that we are root. Growing a file
975 * without zero filling the data is a security hole
976 * root would have access anyway so we'll allow it
977 */
ccc36f2f
A
978 if (!is_suser()) {
979 error = EACCES;
2d21ac55
A
980 } else {
981 /*
91447636
A
982 * set the file size
983 */
2d21ac55
A
984 error = vnode_setsize(vp, offset, IO_NOZEROFILL,
985 &context);
91447636 986 }
2d21ac55
A
987
988 (void)vnode_put(vp);
91447636 989 goto outdrop;
9bccf70c
A
990
991 case F_RDAHEAD:
91447636
A
992 if (fp->f_type != DTYPE_VNODE) {
993 error = EBADF;
994 goto out;
995 }
2d21ac55
A
996 if (uap->arg)
997 fp->f_fglob->fg_flag &= ~FNORDAHEAD;
998 else
999 fp->f_fglob->fg_flag |= FNORDAHEAD;
91447636 1000
2d21ac55 1001 goto out;
1c79356b 1002
9bccf70c 1003 case F_NOCACHE:
91447636
A
1004 if (fp->f_type != DTYPE_VNODE) {
1005 error = EBADF;
1006 goto out;
1007 }
2d21ac55
A
1008 if (uap->arg)
1009 fp->f_fglob->fg_flag |= FNOCACHE;
1010 else
1011 fp->f_fglob->fg_flag &= ~FNOCACHE;
1012
1013 goto out;
1014
1015 case F_GLOBAL_NOCACHE:
1016 if (fp->f_type != DTYPE_VNODE) {
1017 error = EBADF;
1018 goto out;
1019 }
9bccf70c 1020 vp = (struct vnode *)fp->f_data;
91447636 1021 proc_fdunlock(p);
9bccf70c 1022
91447636 1023 if ( (error = vnode_getwithref(vp)) == 0 ) {
2d21ac55
A
1024
1025 *retval = vnode_isnocache(vp);
1026
1027 if (uap->arg)
91447636
A
1028 vnode_setnocache(vp);
1029 else
1030 vnode_clearnocache(vp);
1c79356b 1031
91447636
A
1032 (void)vnode_put(vp);
1033 }
1034 goto outdrop;
1c79356b 1035
2d21ac55
A
1036 case F_CHECK_OPENEVT:
1037 if (fp->f_type != DTYPE_VNODE) {
1038 error = EBADF;
3a60a9f5
A
1039 goto out;
1040 }
1041 vp = (struct vnode *)fp->f_data;
1042 proc_fdunlock(p);
1043
1044 if ( (error = vnode_getwithref(vp)) == 0 ) {
1045
2d21ac55 1046 *retval = vnode_is_openevt(vp);
3a60a9f5 1047
2d21ac55
A
1048 if (uap->arg)
1049 vnode_set_openevt(vp);
3a60a9f5 1050 else
2d21ac55 1051 vnode_clear_openevt(vp);
3a60a9f5
A
1052
1053 (void)vnode_put(vp);
1054 }
1055 goto outdrop;
1056
91447636
A
1057 case F_RDADVISE: {
1058 struct radvisory ra_struct;
9bccf70c 1059
91447636
A
1060 if (fp->f_type != DTYPE_VNODE) {
1061 error = EBADF;
1062 goto out;
1063 }
55e303ae 1064 vp = (struct vnode *)fp->f_data;
91447636 1065 proc_fdunlock(p);
55e303ae 1066
2d21ac55 1067 if ( (error = copyin(argp, (caddr_t)&ra_struct, sizeof(ra_struct))) )
91447636
A
1068 goto outdrop;
1069 if ( (error = vnode_getwithref(vp)) == 0 ) {
1070 error = VNOP_IOCTL(vp, F_RDADVISE, (caddr_t)&ra_struct, 0, &context);
1071
1072 (void)vnode_put(vp);
1073 }
1074 goto outdrop;
1075 }
55e303ae 1076
1c79356b 1077 case F_READBOOTSTRAP:
91447636
A
1078 case F_WRITEBOOTSTRAP: {
1079 fbootstraptransfer_t fbt_struct;
1080 user_fbootstraptransfer_t user_fbt_struct;
1081 int sizeof_struct;
1082 caddr_t boot_structp;
1083
1084 if (fp->f_type != DTYPE_VNODE) {
1085 error = EBADF;
1086 goto out;
1087 }
ccc36f2f 1088 vp = (struct vnode *)fp->f_data;
91447636 1089 proc_fdunlock(p);
1c79356b 1090
91447636
A
1091 if (IS_64BIT_PROCESS(p)) {
1092 sizeof_struct = sizeof(user_fbt_struct);
1093 boot_structp = (caddr_t) &user_fbt_struct;
1094 }
1095 else {
1096 sizeof_struct = sizeof(fbt_struct);
1097 boot_structp = (caddr_t) &fbt_struct;
1098 }
1099 error = copyin(argp, boot_structp, sizeof_struct);
1c79356b 1100 if (error)
91447636
A
1101 goto outdrop;
1102 if ( (error = vnode_getwithref(vp)) ) {
1103 goto outdrop;
1104 }
1c79356b 1105 if (uap->cmd == F_WRITEBOOTSTRAP) {
91447636
A
1106 /*
1107 * Make sure that we are root. Updating the
1108 * bootstrap on a disk could be a security hole
1109 */
ccc36f2f 1110 if (!is_suser()) {
91447636 1111 (void)vnode_put(vp);
ccc36f2f 1112 error = EACCES;
91447636 1113 goto outdrop;
ccc36f2f 1114 }
9bccf70c 1115 }
2d21ac55
A
1116 if (strncmp(vnode_mount(vp)->mnt_vfsstat.f_fstypename, "hfs",
1117 sizeof(vnode_mount(vp)->mnt_vfsstat.f_fstypename)) != 0) {
9bccf70c 1118 error = EINVAL;
91447636
A
1119 } else {
1120 /*
1121 * call vnop_ioctl to handle the I/O
1122 */
1123 error = VNOP_IOCTL(vp, uap->cmd, boot_structp, 0, &context);
9bccf70c 1124 }
91447636
A
1125 (void)vnode_put(vp);
1126 goto outdrop;
1127 }
1128 case F_LOG2PHYS: {
1129 struct log2phys l2p_struct; /* structure for allocate command */
9bccf70c 1130
91447636
A
1131 if (fp->f_type != DTYPE_VNODE) {
1132 error = EBADF;
1133 goto out;
1134 }
1c79356b 1135 vp = (struct vnode *)fp->f_data;
91447636
A
1136 proc_fdunlock(p);
1137 if ( (error = vnode_getwithref(vp)) ) {
1138 goto outdrop;
1139 }
1140 error = VNOP_OFFTOBLK(vp, fp->f_offset, &lbn);
1141 if (error) {
1142 (void)vnode_put(vp);
1143 goto outdrop;
1144 }
1145 error = VNOP_BLKTOOFF(vp, lbn, &offset);
1146 if (error) {
1147 (void)vnode_put(vp);
1148 goto outdrop;
1149 }
1150 devBlockSize = vfs_devblocksize(vnode_mount(vp));
1151
1152 error = VNOP_BLOCKMAP(vp, offset, devBlockSize, &bn, NULL, NULL, 0, &context);
1153
1154 (void)vnode_put(vp);
ccc36f2f 1155
1c79356b
A
1156 if (!error) {
1157 l2p_struct.l2p_flags = 0; /* for now */
1158 l2p_struct.l2p_contigbytes = 0; /* for now */
1159 l2p_struct.l2p_devoffset = bn * devBlockSize;
1160 l2p_struct.l2p_devoffset += fp->f_offset - offset;
2d21ac55 1161 error = copyout((caddr_t)&l2p_struct, argp, sizeof(l2p_struct));
91447636
A
1162 }
1163 goto outdrop;
1c79356b 1164 }
55e303ae 1165 case F_GETPATH: {
91447636
A
1166 char *pathbufp;
1167 int pathlen;
55e303ae 1168
91447636
A
1169 if (fp->f_type != DTYPE_VNODE) {
1170 error = EBADF;
1171 goto out;
1172 }
55e303ae 1173 vp = (struct vnode *)fp->f_data;
91447636 1174 proc_fdunlock(p);
55e303ae 1175
91447636
A
1176 pathlen = MAXPATHLEN;
1177 MALLOC(pathbufp, char *, pathlen, M_TEMP, M_WAITOK);
1178 if (pathbufp == NULL) {
1179 error = ENOMEM;
1180 goto outdrop;
1181 }
1182 if ( (error = vnode_getwithref(vp)) == 0 ) {
1183 error = vn_getpath(vp, pathbufp, &pathlen);
1184 (void)vnode_put(vp);
4a249263 1185
91447636
A
1186 if (error == 0)
1187 error = copyout((caddr_t)pathbufp, argp, pathlen);
1188 }
1189 FREE(pathbufp, M_TEMP);
1190 goto outdrop;
55e303ae
A
1191 }
1192
91447636
A
1193 case F_PATHPKG_CHECK: {
1194 char *pathbufp;
1195 size_t pathlen;
1196
1197 if (fp->f_type != DTYPE_VNODE) {
1198 error = EBADF;
1199 goto out;
1200 }
55e303ae 1201 vp = (struct vnode *)fp->f_data;
91447636 1202 proc_fdunlock(p);
55e303ae 1203
91447636
A
1204 pathlen = MAXPATHLEN;
1205 pathbufp = kalloc(MAXPATHLEN);
1206
1207 if ( (error = copyinstr(argp, pathbufp, MAXPATHLEN, &pathlen)) == 0 ) {
1208 if ( (error = vnode_getwithref(vp)) == 0 ) {
1209 error = vn_path_package_check(vp, pathbufp, pathlen, retval);
1210
1211 (void)vnode_put(vp);
1212 }
1213 }
1214 kfree(pathbufp, MAXPATHLEN);
1215 goto outdrop;
1216 }
1217
1218 case F_CHKCLEAN: // used by regression tests to see if all dirty pages got cleaned by fsync()
1219 case F_FULLFSYNC: // fsync + flush the journal + DKIOCSYNCHRONIZECACHE
1220 case F_FREEZE_FS: // freeze all other fs operations for the fs of this fd
1221 case F_THAW_FS: { // thaw all frozen fs operations for the fs of this fd
1222 if (fp->f_type != DTYPE_VNODE) {
1223 error = EBADF;
1224 goto out;
1225 }
1226 vp = (struct vnode *)fp->f_data;
1227 proc_fdunlock(p);
ccc36f2f 1228
91447636
A
1229 if ( (error = vnode_getwithref(vp)) == 0 ) {
1230 error = VNOP_IOCTL(vp, uap->cmd, (caddr_t)NULL, 0, &context);
1231
1232 (void)vnode_put(vp);
1233 }
ccc36f2f 1234 break;
55e303ae 1235 }
2d21ac55
A
1236
1237 /*
1238 * SPI (private) for opening a file starting from a dir fd
1239 */
1240 case F_OPENFROM: {
1241 struct user_fopenfrom fopen;
1242 struct vnode_attr va;
1243 struct nameidata nd;
1244 int cmode;
1245
1246 /* Check if this isn't a valid file descriptor */
1247 if ((fp->f_type != DTYPE_VNODE) ||
1248 (fp->f_flag & FREAD) == 0) {
1249 error = EBADF;
91447636
A
1250 goto out;
1251 }
2d21ac55
A
1252 vp = (struct vnode *)fp->f_data;
1253 proc_fdunlock(p);
91447636 1254
2d21ac55
A
1255 if (vnode_getwithref(vp)) {
1256 error = ENOENT;
1257 goto outdrop;
1258 }
1259
1260 /* Only valid for directories */
1261 if (vp->v_type != VDIR) {
1262 vnode_put(vp);
1263 error = ENOTDIR;
1264 goto outdrop;
1265 }
91447636 1266
2d21ac55
A
1267 /* Get flags, mode and pathname arguments. */
1268 if (IS_64BIT_PROCESS(p)) {
1269 error = copyin(argp, &fopen, sizeof(fopen));
1270 } else {
1271 struct fopenfrom fopen32;
1272
1273 error = copyin(argp, &fopen32, sizeof(fopen32));
1274 fopen.o_flags = fopen32.o_flags;
1275 fopen.o_mode = fopen32.o_mode;
1276 fopen.o_pathname = CAST_USER_ADDR_T(fopen32.o_pathname);
1277 }
1278 if (error) {
1279 vnode_put(vp);
1280 goto outdrop;
1281 }
1282 VATTR_INIT(&va);
1283 /* Mask off all but regular access permissions */
1284 cmode = ((fopen.o_mode &~ fdp->fd_cmask) & ALLPERMS) & ~S_ISTXT;
1285 VATTR_SET(&va, va_mode, cmode & ACCESSPERMS);
1286
1287 /* Start the lookup relative to the file descriptor's vnode. */
1288 NDINIT(&nd, LOOKUP, USEDVP | FOLLOW | AUDITVNPATH1, UIO_USERSPACE,
1289 fopen.o_pathname, &context);
1290 nd.ni_dvp = vp;
1291
1292 error = open1(&context, &nd, fopen.o_flags, &va, retval);
1293
1294 vnode_put(vp);
1295 break;
1296 }
1297 /*
1298 * SPI (private) for unlinking a file starting from a dir fd
1299 */
1300 case F_UNLINKFROM: {
1301 struct nameidata nd;
1302 user_addr_t pathname;
1303
1304 /* Check if this isn't a valid file descriptor */
1305 if ((fp->f_type != DTYPE_VNODE) ||
1306 (fp->f_flag & FREAD) == 0) {
91447636
A
1307 error = EBADF;
1308 goto out;
1309 }
1310 vp = (struct vnode *)fp->f_data;
1311 proc_fdunlock(p);
1312
2d21ac55
A
1313 if (vnode_getwithref(vp)) {
1314 error = ENOENT;
1315 goto outdrop;
1316 }
1317
1318 /* Only valid for directories */
1319 if (vp->v_type != VDIR) {
1320 vnode_put(vp);
1321 error = ENOTDIR;
1322 goto outdrop;
1323 }
91447636 1324
2d21ac55
A
1325 /* Get flags, mode and pathname arguments. */
1326 if (IS_64BIT_PROCESS(p)) {
1327 pathname = (user_addr_t)argp;
1328 } else {
1329 pathname = CAST_USER_ADDR_T(argp);
91447636 1330 }
ccc36f2f 1331
2d21ac55
A
1332 /* Start the lookup relative to the file descriptor's vnode. */
1333 NDINIT(&nd, DELETE, USEDVP | AUDITVNPATH1, UIO_USERSPACE, pathname, &context);
1334 nd.ni_dvp = vp;
1c79356b 1335
2d21ac55
A
1336 error = unlink1(&context, &nd, 0);
1337
1338 vnode_put(vp);
1339 break;
1c79356b 1340
1c79356b 1341 }
2d21ac55
A
1342
1343 case F_ADDSIGS: {
1344 struct user_fsignatures fs;
1345 kern_return_t kr;
1346 vm_address_t kernel_blob_addr;
1347 vm_size_t kernel_blob_size;
1348
1349 if (fp->f_type != DTYPE_VNODE) {
1350 error = EBADF;
1351 goto out;
1352 }
1353 vp = (struct vnode *)fp->f_data;
1354 proc_fdunlock(p);
1355 error = vnode_getwithref(vp);
1356 if (error)
1357 goto outdrop;
1358
1359 if (IS_64BIT_PROCESS(p)) {
1360 error = copyin(argp, &fs, sizeof (fs));
1361 } else {
1362 struct fsignatures fs32;
1363
1364 error = copyin(argp, &fs32, sizeof (fs32));
1365 fs.fs_file_start = fs32.fs_file_start;
1366 fs.fs_blob_start = CAST_USER_ADDR_T(fs32.fs_blob_start);
1367 fs.fs_blob_size = fs32.fs_blob_size;
1368 }
1369
1370 if (error) {
1371 vnode_put(vp);
1372 goto outdrop;
1373 }
1374
593a1d5f
A
1375 if(ubc_cs_blob_get(vp, CPU_TYPE_ANY, fs.fs_file_start))
1376 {
1377 if(cs_debug)
1378 printf("CODE SIGNING: resident blob offered for: %s\n", vp->v_name);
1379 vnode_put(vp);
1380 goto outdrop;
1381 }
1382
2d21ac55
A
1383#define CS_MAX_BLOB_SIZE (1ULL * 1024 * 1024) /* XXX ? */
1384 if (fs.fs_blob_size > CS_MAX_BLOB_SIZE) {
1385 error = E2BIG;
1386 vnode_put(vp);
1387 goto outdrop;
1388 }
1389
1390 kernel_blob_size = CAST_DOWN(vm_size_t, fs.fs_blob_size);
593a1d5f 1391 kr = ubc_cs_blob_allocate(&kernel_blob_addr, &kernel_blob_size);
2d21ac55
A
1392 if (kr != KERN_SUCCESS) {
1393 error = ENOMEM;
1394 vnode_put(vp);
1395 goto outdrop;
1396 }
1397
1398 error = copyin(fs.fs_blob_start,
1399 (void *) kernel_blob_addr,
1400 kernel_blob_size);
1401 if (error) {
593a1d5f
A
1402 ubc_cs_blob_deallocate(kernel_blob_addr,
1403 kernel_blob_size);
2d21ac55
A
1404 vnode_put(vp);
1405 goto outdrop;
1406 }
1407
1408 error = ubc_cs_blob_add(
1409 vp,
1410 CPU_TYPE_ANY, /* not for a specific architecture */
1411 fs.fs_file_start,
1412 kernel_blob_addr,
1413 kernel_blob_size);
1414 if (error) {
593a1d5f
A
1415 ubc_cs_blob_deallocate(kernel_blob_addr,
1416 kernel_blob_size);
2d21ac55 1417 } else {
593a1d5f 1418 /* ubc_blob_add() has consumed "kernel_blob_addr" */
2d21ac55
A
1419 }
1420
1421 (void) vnode_put(vp);
1422 break;
1423 }
1424
1425 case F_MARKDEPENDENCY: {
1426 struct vnode *root_vp;
1427 struct vnode_attr va;
1428 vfs_context_t ctx = vfs_context_current();
1429 kauth_cred_t cred;
1430
1431 if ((current_proc()->p_flag & P_DEPENDENCY_CAPABLE) == 0) {
1432 error = EPERM;
1433 goto out;
1434 }
1435
1436 if (fp->f_type != DTYPE_VNODE) {
1437 error = EBADF;
1438 goto out;
1439 }
1440
1441 vp = (struct vnode *)fp->f_data;
1442 proc_fdunlock(p);
1443
1444 if (vnode_getwithref(vp)) {
1445 error = ENOENT;
1446 goto outdrop;
1447 }
1448
1449 // the passed in vnode must be the root dir of the file system
1450 if (VFS_ROOT(vp->v_mount, &root_vp, ctx) != 0 || vp != root_vp) {
1451 error = EINVAL;
1452 vnode_put(vp);
1453 goto outdrop;
1454 }
1455 vnode_put(root_vp);
1456
1457 // get the owner of the root dir
1458 VATTR_INIT(&va);
1459 VATTR_WANTED(&va, va_uid);
1460 if (vnode_getattr(vp, &va, ctx) != 0) {
1461 error = EINVAL;
1462 vnode_put(vp);
1463 goto outdrop;
1464 }
1465
1466 // and last, check that the caller is the super user or
1467 // the owner of the mount point
1468 cred = vfs_context_ucred(ctx);
1469 if (!is_suser() && va.va_uid != kauth_cred_getuid(cred)) {
1470 error = EACCES;
1471 vnode_put(vp);
1472 goto outdrop;
1473 }
1474
1475 // if all those checks pass then we can mark the dependency
1476 vfs_markdependency(vp->v_mount);
1477 error = 0;
1478
1479 vnode_put(vp);
1480
1481 break;
1482 }
1483
1484 default:
1485 if (uap->cmd < FCNTL_FS_SPECIFIC_BASE) {
1486 error = EINVAL;
1487 goto out;
1488 }
1489
1490 // if it's a fs-specific fcntl() then just pass it through
1491
1492 if (fp->f_type != DTYPE_VNODE) {
1493 error = EBADF;
1494 goto out;
1495 }
1496 vp = (struct vnode *)fp->f_data;
1497 proc_fdunlock(p);
1498
1499 if ( (error = vnode_getwithref(vp)) == 0 ) {
1500 error = VNOP_IOCTL(vp, uap->cmd, CAST_DOWN(caddr_t, argp), 0, &context);
1501
1502 (void)vnode_put(vp);
1503 }
1504 break;
1505
1506 }
1507
1508outdrop:
1509 AUDIT_ARG(vnpath_withref, vp, ARG_VNODE1);
1510 fp_drop(p, fd, fp, 0);
1511 return(error);
1512out:
1513 fp_drop(p, fd, fp, 1);
1514 proc_fdunlock(p);
1515 return(error);
1516}
1517
1518
1519/*
1520 * finishdup
1521 *
1522 * Description: Common code for dup, dup2, and fcntl(F_DUPFD).
1523 *
1524 * Parameters: p Process performing the dup
1525 * old The fd to dup
1526 * new The fd to dup it to
1527 * retval Pointer to the call return area
1528 *
1529 * Returns: 0 Success
1530 * EBADF
1531 * ENOMEM
1532 *
1533 * Implicit returns:
1534 * *retval (modified) The new descriptor
1535 *
1536 * Locks: Assumes proc_fdlock for process pointing to fdp is held by
1537 * the caller
1538 *
1539 * Notes: This function may drop and reacquire this lock; it is unsafe
1540 * for a caller to assume that other state protected by the lock
1541 * has not been subsequently changes out from under it.
1542 */
1543int
1544finishdup(proc_t p, struct filedesc *fdp, int old, int new, register_t *retval)
1545{
1546 struct fileproc *nfp;
1547 struct fileproc *ofp;
1548#if CONFIG_MACF
1549 int error;
1550#endif
1551
1552#if DIAGNOSTIC
1553 proc_fdlock_assert(p, LCK_MTX_ASSERT_OWNED);
1554#endif
1555
1556 if ((ofp = fdp->fd_ofiles[old]) == NULL ||
1557 (fdp->fd_ofileflags[old] & UF_RESERVED)) {
1558 fdrelse(p, new);
1559 return (EBADF);
1560 }
1561 fg_ref(ofp);
1562
1563#if CONFIG_MACF
1564 error = mac_file_check_dup(proc_ucred(p), ofp->f_fglob, new);
1565 if (error) {
1566 fg_drop(ofp);
1567 fdrelse(p, new);
1568 return (error);
1569 }
1570#endif
1571
1572 proc_fdunlock(p);
91447636
A
1573
1574 MALLOC_ZONE(nfp, struct fileproc *, sizeof(struct fileproc), M_FILEPROC, M_WAITOK);
2d21ac55 1575 /* Failure check follows proc_fdlock() due to handling requirements */
91447636
A
1576
1577 proc_fdlock(p);
2d21ac55
A
1578
1579 if (nfp == NULL) {
1580 fg_drop(ofp);
1581 fdrelse(p, new);
1582 return (ENOMEM);
1583 }
1584
1585 bzero(nfp, sizeof(struct fileproc));
1586
6601e61a 1587 nfp->f_flags = 0;
91447636
A
1588 nfp->f_fglob = ofp->f_fglob;
1589 nfp->f_iocount = 0;
1590
2d21ac55
A
1591#if DIAGNOSTIC
1592 if (fdp->fd_ofiles[new] != 0)
1593 panic("finishdup: overwriting fd_ofiles with new %d\n", new);
1594 if ((fdp->fd_ofileflags[new] & UF_RESERVED) == 0)
1595 panic("finishdup: unreserved fileflags with new %d\n", new);
1596#endif
1597
1c79356b
A
1598 if (new > fdp->fd_lastfile)
1599 fdp->fd_lastfile = new;
6601e61a 1600 procfdtbl_releasefd(p, new, nfp);
1c79356b
A
1601 *retval = new;
1602 return (0);
1603}
1604
91447636 1605
2d21ac55
A
1606/*
1607 * close
1608 *
1609 * Description: The implementation of the close(2) system call
1610 *
1611 * Parameters: p Process in whose per process file table
1612 * the close is to occur
1613 * uap->fd fd to be closed
1614 * retval <unused>
1615 *
1616 * Returns: 0 Success
1617 * fp_lookup:EBADF Bad file descriptor
1618 * close_internal:EBADF
1619 * close_internal:??? Anything returnable by a per-fileops
1620 * close function
1621 */
1622int
1623close(proc_t p, struct close_args *uap, register_t *retval)
1624{
1625 __pthread_testcancel(1);
1626 return(close_nocancel(p, (struct close_nocancel_args *)uap, retval));
1627}
1628
1629
1c79356b 1630int
2d21ac55 1631close_nocancel(proc_t p, struct close_nocancel_args *uap, __unused register_t *retval)
1c79356b 1632{
91447636 1633 struct fileproc *fp;
1c79356b 1634 int fd = uap->fd;
91447636 1635 int error =0;
1c79356b 1636
e5568f75 1637 AUDIT_SYSCLOSE(p, fd);
91447636
A
1638
1639 proc_fdlock(p);
1640
1641 if ( (error = fp_lookup(p,fd,&fp, 1)) ) {
1642 proc_fdunlock(p);
1643 return(error);
1644 }
1645
2d21ac55 1646 error = close_internal_locked(p, fd, fp, 0);
91447636
A
1647
1648 proc_fdunlock(p);
1649
1650 return(error);
1651}
1652
1653
1654/*
2d21ac55
A
1655 * close_internal_locked
1656 *
91447636 1657 * Close a file descriptor.
2d21ac55
A
1658 *
1659 * Parameters: p Process in whose per process file table
1660 * the close is to occur
1661 * fd fd to be closed
1662 * fp fileproc associated with the fd
1663 *
1664 * Returns: 0 Success
1665 * EBADF fd already in close wait state
1666 * closef_locked:??? Anything returnable by a per-fileops
1667 * close function
1668 *
1669 * Locks: Assumes proc_fdlock for process is held by the caller and returns
1670 * with lock held
1671 *
1672 * Notes: This function may drop and reacquire this lock; it is unsafe
1673 * for a caller to assume that other state protected by the lock
1674 * has not been subsequently changes out from under it, if the
1675 * caller made the call with the lock held.
91447636 1676 */
2d21ac55
A
1677static int
1678close_internal_locked(proc_t p, int fd, struct fileproc *fp, int flags)
91447636
A
1679{
1680 struct filedesc *fdp = p->p_fd;
1681 int error =0;
2d21ac55 1682 int resvfd = flags & FD_DUP2RESV;
91447636 1683
2d21ac55
A
1684
1685#if DIAGNOSTIC
1686 proc_fdlock_assert(p, LCK_MTX_ASSERT_OWNED);
1687#endif
55e303ae
A
1688
1689 /* Keep people from using the filedesc while we are closing it */
6601e61a 1690 procfdtbl_markclosefd(p, fd);
2d21ac55
A
1691
1692
6601e61a
A
1693 if ((fp->f_flags & FP_CLOSING) == FP_CLOSING) {
1694 panic("close_internal_locked: being called on already closing fd\n");
1695 }
91447636
A
1696
1697
2d21ac55
A
1698#if DIAGNOSTIC
1699 if ((fdp->fd_ofileflags[fd] & UF_RESERVED) == 0)
1700 panic("close_internal: unreserved fileflags with fd %d\n", fd);
1701#endif
91447636
A
1702
1703 fp->f_flags |= FP_CLOSING;
91447636
A
1704
1705 if ( (fp->f_flags & FP_AIOISSUED) || kauth_authorize_fileop_has_listeners() ) {
1706
1707 proc_fdunlock(p);
1708
1709 if ( (fp->f_type == DTYPE_VNODE) && kauth_authorize_fileop_has_listeners() ) {
1710 /*
1711 * call out to allow 3rd party notification of close.
1712 * Ignore result of kauth_authorize_fileop call.
1713 */
1714 if (vnode_getwithref((vnode_t)fp->f_data) == 0) {
1715 u_int fileop_flags = 0;
1716 if ((fp->f_flags & FP_WRITTEN) != 0)
1717 fileop_flags |= KAUTH_FILEOP_CLOSE_MODIFIED;
1718 kauth_authorize_fileop(fp->f_fglob->fg_cred, KAUTH_FILEOP_CLOSE,
1719 (uintptr_t)fp->f_data, (uintptr_t)fileop_flags);
1720 vnode_put((vnode_t)fp->f_data);
1721 }
1722 }
1723 if (fp->f_flags & FP_AIOISSUED)
1724 /*
1725 * cancel all async IO requests that can be cancelled.
1726 */
1727 _aio_close( p, fd );
1728
1729 proc_fdlock(p);
1730 }
1731
1732 if (fd < fdp->fd_knlistsize)
55e303ae
A
1733 knote_fdclose(p, fd);
1734
91447636
A
1735 if (fp->f_flags & FP_WAITEVENT)
1736 (void)waitevent_close(p, fp);
1737
1738 if ((fp->f_flags & FP_INCHRREAD) == 0)
1739 fileproc_drain(p, fp);
2d21ac55
A
1740
1741 if (resvfd == 0)
6601e61a 1742 _fdrelse(p, fd);
2d21ac55 1743
91447636
A
1744 error = closef_locked(fp, fp->f_fglob, p);
1745 if ((fp->f_flags & FP_WAITCLOSE) == FP_WAITCLOSE)
1746 wakeup(&fp->f_flags);
1747 fp->f_flags &= ~(FP_WAITCLOSE | FP_CLOSING);
1748
2d21ac55
A
1749 proc_fdunlock(p);
1750
1751 FREE_ZONE(fp, sizeof(*fp), M_FILEPROC);
1752
1753 proc_fdlock(p);
1754
1755#if DIAGNOSTIC
1756 if (resvfd != 0) {
1757 if ((fdp->fd_ofileflags[fd] & UF_RESERVED) == 0)
1758 panic("close with reserved fd returns with freed fd:%d: proc: %x\n", fd, (unsigned int)p);
1759 }
1760#endif
91447636 1761
91447636 1762 return(error);
1c79356b
A
1763}
1764
2d21ac55 1765
1c79356b 1766/*
2d21ac55
A
1767 * fstat1
1768 *
1769 * Description: Return status information about a file descriptor.
1770 *
1771 * Parameters: p The process doing the fstat
1772 * fd The fd to stat
1773 * ub The user stat buffer
1774 * xsecurity The user extended security
1775 * buffer, or 0 if none
1776 * xsecurity_size The size of xsecurity, or 0
1777 * if no xsecurity
1778 * isstat64 Flag to indicate 64 bit version
1779 * for inode size, etc.
1780 *
1781 * Returns: 0 Success
1782 * EBADF
1783 * EFAULT
1784 * fp_lookup:EBADF Bad file descriptor
1785 * vnode_getwithref:???
1786 * copyout:EFAULT
1787 * vnode_getwithref:???
1788 * vn_stat:???
1789 * soo_stat:???
1790 * pipe_stat:???
1791 * pshm_stat:???
1792 * kqueue_stat:???
1793 *
1794 * Notes: Internal implementation for all other fstat() related
1795 * functions
91447636 1796 *
2d21ac55
A
1797 * XXX switch on node type is bogus; need a stat in struct
1798 * XXX fileops instead.
1c79356b 1799 */
91447636 1800static int
2d21ac55 1801fstat1(proc_t p, int fd, user_addr_t ub, user_addr_t xsecurity, user_addr_t xsecurity_size, int isstat64)
1c79356b 1802{
91447636
A
1803 struct fileproc *fp;
1804 struct stat sb;
2d21ac55 1805 struct stat64 sb64;
91447636 1806 struct user_stat user_sb;
2d21ac55 1807 struct user_stat64 user_sb64;
91447636
A
1808 int error, my_size;
1809 int funnel_state;
8f6c56a5 1810 file_type_t type;
91447636
A
1811 caddr_t data;
1812 kauth_filesec_t fsec;
2d21ac55
A
1813 user_size_t xsecurity_bufsize;
1814 vfs_context_t ctx = vfs_context_current();
1815 void * sbptr;
1c79356b 1816
91447636
A
1817
1818 AUDIT_ARG(fd, fd);
1819
2d21ac55 1820 if ((error = fp_lookup(p, fd, &fp, 0)) != 0) {
91447636 1821 return(error);
2d21ac55 1822 }
91447636
A
1823 type = fp->f_type;
1824 data = fp->f_data;
1825 fsec = KAUTH_FILESEC_NONE;
1826
2d21ac55
A
1827 sbptr = (isstat64 != 0) ? (void *)&sb64: (void *)&sb;
1828
91447636 1829 switch (type) {
1c79356b
A
1830
1831 case DTYPE_VNODE:
91447636
A
1832 if ((error = vnode_getwithref((vnode_t)data)) == 0) {
1833 /*
2d21ac55
A
1834 * If the caller has the file open, and is not
1835 * requesting extended security information, we are
1836 * going to let them get the basic stat information.
91447636
A
1837 */
1838 if (xsecurity == USER_ADDR_NULL) {
2d21ac55 1839 error = vn_stat_noauth((vnode_t)data, sbptr, NULL, isstat64, ctx);
91447636 1840 } else {
2d21ac55 1841 error = vn_stat((vnode_t)data, sbptr, &fsec, isstat64, ctx);
91447636
A
1842 }
1843
1844 AUDIT_ARG(vnpath, (struct vnode *)data, ARG_VNODE1);
1845 (void)vnode_put((vnode_t)data);
55e303ae 1846 }
1c79356b
A
1847 break;
1848
2d21ac55 1849#if SOCKETS
1c79356b 1850 case DTYPE_SOCKET:
2d21ac55 1851 error = soo_stat((struct socket *)data, sbptr, isstat64);
91447636 1852 break;
2d21ac55 1853#endif /* SOCKETS */
91447636
A
1854
1855 case DTYPE_PIPE:
2d21ac55 1856 error = pipe_stat((void *)data, sbptr, isstat64);
1c79356b
A
1857 break;
1858
1859 case DTYPE_PSXSHM:
2d21ac55 1860 error = pshm_stat((void *)data, sbptr, isstat64);
1c79356b 1861 break;
55e303ae
A
1862
1863 case DTYPE_KQUEUE:
91447636 1864 funnel_state = thread_funnel_set(kernel_flock, TRUE);
2d21ac55 1865 error = kqueue_stat(fp, sbptr, isstat64, p);
91447636
A
1866 thread_funnel_set(kernel_flock, funnel_state);
1867 break;
55e303ae 1868
1c79356b 1869 default:
91447636
A
1870 error = EBADF;
1871 goto out;
1872 }
91447636
A
1873 if (error == 0) {
1874 caddr_t sbp;
2d21ac55
A
1875
1876 if (isstat64 != 0) {
1877 sb64.st_lspare = 0;
1878 sb64.st_qspare[0] = 0LL;
1879 sb64.st_qspare[1] = 0LL;
1880 if (IS_64BIT_PROCESS(current_proc())) {
1881 munge_stat64(&sb64, &user_sb64);
1882 my_size = sizeof(user_sb64);
1883 sbp = (caddr_t)&user_sb64;
1884 } else {
1885 my_size = sizeof(sb64);
1886 sbp = (caddr_t)&sb64;
1887 }
1888 } else {
1889 sb.st_lspare = 0;
1890 sb.st_qspare[0] = 0LL;
1891 sb.st_qspare[1] = 0LL;
1892 if (IS_64BIT_PROCESS(current_proc())) {
1893 munge_stat(&sb, &user_sb);
1894 my_size = sizeof(user_sb);
1895 sbp = (caddr_t)&user_sb;
1896 } else {
1897 my_size = sizeof(sb);
1898 sbp = (caddr_t)&sb;
1899 }
91447636 1900 }
2d21ac55 1901
91447636 1902 error = copyout(sbp, ub, my_size);
1c79356b 1903 }
1c79356b 1904
91447636
A
1905 /* caller wants extended security information? */
1906 if (xsecurity != USER_ADDR_NULL) {
1c79356b 1907
91447636
A
1908 /* did we get any? */
1909 if (fsec == KAUTH_FILESEC_NONE) {
1910 if (susize(xsecurity_size, 0) != 0) {
1911 error = EFAULT;
1912 goto out;
1913 }
1914 } else {
1915 /* find the user buffer size */
1916 xsecurity_bufsize = fusize(xsecurity_size);
1c79356b 1917
91447636
A
1918 /* copy out the actual data size */
1919 if (susize(xsecurity_size, KAUTH_FILESEC_COPYSIZE(fsec)) != 0) {
1920 error = EFAULT;
1921 goto out;
1922 }
1c79356b 1923
91447636
A
1924 /* if the caller supplied enough room, copy out to it */
1925 if (xsecurity_bufsize >= KAUTH_FILESEC_COPYSIZE(fsec))
1926 error = copyout(fsec, xsecurity, KAUTH_FILESEC_COPYSIZE(fsec));
1927 }
1c79356b 1928 }
91447636
A
1929out:
1930 fp_drop(p, fd, fp, 0);
1931 if (fsec != NULL)
1932 kauth_filesec_free(fsec);
1c79356b
A
1933 return (error);
1934}
91447636 1935
2d21ac55
A
1936
1937/*
1938 * fstat_extended
1939 *
1940 * Description: Extended version of fstat supporting returning extended
1941 * security information
1942 *
1943 * Parameters: p The process doing the fstat
1944 * uap->fd The fd to stat
1945 * uap->ub The user stat buffer
1946 * uap->xsecurity The user extended security
1947 * buffer, or 0 if none
1948 * uap->xsecurity_size The size of xsecurity, or 0
1949 *
1950 * Returns: 0 Success
1951 * !0 Errno (see fstat1)
1952 */
91447636 1953int
2d21ac55 1954fstat_extended(proc_t p, struct fstat_extended_args *uap, __unused register_t *retval)
91447636 1955{
2d21ac55 1956 return(fstat1(p, uap->fd, uap->ub, uap->xsecurity, uap->xsecurity_size, 0));
91447636
A
1957}
1958
2d21ac55
A
1959
1960/*
1961 * fstat
1962 *
1963 * Description: Get file status for the file associated with fd
1964 *
1965 * Parameters: p The process doing the fstat
1966 * uap->fd The fd to stat
1967 * uap->ub The user stat buffer
1968 *
1969 * Returns: 0 Success
1970 * !0 Errno (see fstat1)
1971 */
1972int
1973fstat(proc_t p, register struct fstat_args *uap, __unused register_t *retval)
1974{
1975 return(fstat1(p, uap->fd, uap->ub, 0, 0, 0));
1976}
1977
1978
1979/*
1980 * fstat64_extended
1981 *
1982 * Description: Extended version of fstat64 supporting returning extended
1983 * security information
1984 *
1985 * Parameters: p The process doing the fstat
1986 * uap->fd The fd to stat
1987 * uap->ub The user stat buffer
1988 * uap->xsecurity The user extended security
1989 * buffer, or 0 if none
1990 * uap->xsecurity_size The size of xsecurity, or 0
1991 *
1992 * Returns: 0 Success
1993 * !0 Errno (see fstat1)
1994 */
1995int
1996fstat64_extended(proc_t p, struct fstat64_extended_args *uap, __unused register_t *retval)
1997{
1998 return(fstat1(p, uap->fd, uap->ub, uap->xsecurity, uap->xsecurity_size, 1));
1999}
2000
2001
2002/*
2003 * fstat64
2004 *
2005 * Description: Get 64 bit version of the file status for the file associated
2006 * with fd
2007 *
2008 * Parameters: p The process doing the fstat
2009 * uap->fd The fd to stat
2010 * uap->ub The user stat buffer
2011 *
2012 * Returns: 0 Success
2013 * !0 Errno (see fstat1)
2014 */
91447636 2015int
2d21ac55 2016fstat64(proc_t p, register struct fstat64_args *uap, __unused register_t *retval)
91447636 2017{
2d21ac55 2018 return(fstat1(p, uap->fd, uap->ub, 0, 0, 1));
91447636 2019}
1c79356b 2020
2d21ac55 2021
1c79356b 2022/*
2d21ac55
A
2023 * fpathconf
2024 *
2025 * Description: Return pathconf information about a file descriptor.
2026 *
2027 * Parameters: p Process making the request
2028 * uap->fd fd to get information about
2029 * uap->name Name of information desired
2030 * retval Pointer to the call return area
2031 *
2032 * Returns: 0 Success
2033 * EINVAL
2034 * fp_lookup:EBADF Bad file descriptor
2035 * vnode_getwithref:???
2036 * vn_pathconf:???
2037 *
2038 * Implicit returns:
2039 * *retval (modified) Returned information (numeric)
1c79356b 2040 */
91447636 2041int
2d21ac55 2042fpathconf(proc_t p, struct fpathconf_args *uap, register_t *retval)
1c79356b
A
2043{
2044 int fd = uap->fd;
91447636 2045 struct fileproc *fp;
1c79356b 2046 struct vnode *vp;
91447636 2047 int error = 0;
8f6c56a5 2048 file_type_t type;
91447636
A
2049 caddr_t data;
2050
1c79356b 2051
55e303ae 2052 AUDIT_ARG(fd, uap->fd);
91447636
A
2053 if ( (error = fp_lookup(p, fd, &fp, 0)) )
2054 return(error);
2055 type = fp->f_type;
2056 data = fp->f_data;
2057
2058 switch (type) {
1c79356b
A
2059
2060 case DTYPE_SOCKET:
91447636
A
2061 if (uap->name != _PC_PIPE_BUF) {
2062 error = EINVAL;
2063 goto out;
2064 }
1c79356b 2065 *retval = PIPE_BUF;
91447636
A
2066 error = 0;
2067 goto out;
2068
2069 case DTYPE_PIPE:
2070 *retval = PIPE_BUF;
2071 error = 0;
2072 goto out;
1c79356b
A
2073
2074 case DTYPE_VNODE:
91447636
A
2075 vp = (struct vnode *)data;
2076
2077 if ( (error = vnode_getwithref(vp)) == 0) {
2078 AUDIT_ARG(vnpath, vp, ARG_VNODE1);
2079
2d21ac55 2080 error = vn_pathconf(vp, uap->name, retval, vfs_context_current());
91447636
A
2081
2082 (void)vnode_put(vp);
2083 }
2084 goto out;
55e303ae 2085
91447636 2086 case DTYPE_PSXSHM:
8f6c56a5 2087 case DTYPE_PSXSEM:
91447636 2088 case DTYPE_KQUEUE:
8f6c56a5 2089 case DTYPE_FSEVENTS:
91447636
A
2090 error = EINVAL;
2091 goto out;
1c79356b 2092
1c79356b
A
2093 }
2094 /*NOTREACHED*/
91447636
A
2095out:
2096 fp_drop(p, fd, fp, 0);
2097 return(error);
1c79356b
A
2098}
2099
2100/*
2d21ac55
A
2101 * Statistics counter for the number of times a process calling fdalloc()
2102 * has resulted in an expansion of the per process open file table.
2103 *
2104 * XXX This would likely be of more use if it were per process
1c79356b
A
2105 */
2106int fdexpand;
2107
2d21ac55
A
2108
2109/*
2110 * fdalloc
2111 *
2112 * Description: Allocate a file descriptor for the process.
2113 *
2114 * Parameters: p Process to allocate the fd in
2115 * want The fd we would prefer to get
2116 * result Pointer to fd we got
2117 *
2118 * Returns: 0 Success
2119 * EMFILE
2120 * ENOMEM
2121 *
2122 * Implicit returns:
2123 * *result (modified) The fd which was allocated
2124 */
1c79356b 2125int
2d21ac55 2126fdalloc(proc_t p, int want, int *result)
1c79356b 2127{
2d21ac55
A
2128 struct filedesc *fdp = p->p_fd;
2129 int i;
91447636
A
2130 int lim, last, numfiles, oldnfiles;
2131 struct fileproc **newofiles, **ofiles;
6601e61a 2132 char *newofileflags;
1c79356b
A
2133
2134 /*
2135 * Search for a free descriptor starting at the higher
2136 * of want or fd_freefile. If that fails, consider
2137 * expanding the ofile array.
2138 */
2d21ac55
A
2139#if DIAGNOSTIC
2140 proc_fdlock_assert(p, LCK_MTX_ASSERT_OWNED);
2141#endif
2142
1c79356b
A
2143 lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
2144 for (;;) {
2145 last = min(fdp->fd_nfiles, lim);
2146 if ((i = want) < fdp->fd_freefile)
2147 i = fdp->fd_freefile;
1c79356b 2148 for (; i < last; i++) {
6601e61a
A
2149 if (fdp->fd_ofiles[i] == NULL && !(fdp->fd_ofileflags[i] & UF_RESERVED)) {
2150 procfdtbl_reservefd(p, i);
1c79356b
A
2151 if (i > fdp->fd_lastfile)
2152 fdp->fd_lastfile = i;
2153 if (want <= fdp->fd_freefile)
2154 fdp->fd_freefile = i;
2155 *result = i;
2156 return (0);
2157 }
1c79356b
A
2158 }
2159
2160 /*
2161 * No space in current array. Expand?
2162 */
2163 if (fdp->fd_nfiles >= lim)
2164 return (EMFILE);
2165 if (fdp->fd_nfiles < NDEXTENT)
91447636 2166 numfiles = NDEXTENT;
1c79356b 2167 else
91447636 2168 numfiles = 2 * fdp->fd_nfiles;
1c79356b 2169 /* Enforce lim */
91447636
A
2170 if (numfiles > lim)
2171 numfiles = lim;
2172 proc_fdunlock(p);
2173 MALLOC_ZONE(newofiles, struct fileproc **,
2174 numfiles * OFILESIZE, M_OFILETABL, M_WAITOK);
2175 proc_fdlock(p);
2176 if (newofiles == NULL) {
2177 return (ENOMEM);
2178 }
2179 if (fdp->fd_nfiles >= numfiles) {
2180 FREE_ZONE(newofiles, numfiles * OFILESIZE, M_OFILETABL);
1c79356b
A
2181 continue;
2182 }
91447636 2183 newofileflags = (char *) &newofiles[numfiles];
1c79356b
A
2184 /*
2185 * Copy the existing ofile and ofileflags arrays
2186 * and zero the new portion of each array.
2187 */
2188 oldnfiles = fdp->fd_nfiles;
2189 (void) memcpy(newofiles, fdp->fd_ofiles,
2d21ac55 2190 oldnfiles * sizeof(*fdp->fd_ofiles));
1c79356b 2191 (void) memset(&newofiles[oldnfiles], 0,
2d21ac55 2192 (numfiles - oldnfiles) * sizeof(*fdp->fd_ofiles));
1c79356b
A
2193
2194 (void) memcpy(newofileflags, fdp->fd_ofileflags,
2d21ac55 2195 oldnfiles * sizeof(*fdp->fd_ofileflags));
1c79356b 2196 (void) memset(&newofileflags[oldnfiles], 0,
91447636 2197 (numfiles - oldnfiles) *
2d21ac55 2198 sizeof(*fdp->fd_ofileflags));
1c79356b
A
2199 ofiles = fdp->fd_ofiles;
2200 fdp->fd_ofiles = newofiles;
2201 fdp->fd_ofileflags = newofileflags;
91447636 2202 fdp->fd_nfiles = numfiles;
1c79356b
A
2203 FREE_ZONE(ofiles, oldnfiles * OFILESIZE, M_OFILETABL);
2204 fdexpand++;
2205 }
2206}
2207
2d21ac55 2208
91447636 2209/*
2d21ac55
A
2210 * fdavail
2211 *
2212 * Description: Check to see whether n user file descriptors are available
2213 * to the process p.
2214 *
2215 * Parameters: p Process to check in
2216 * n The number of fd's desired
2217 *
2218 * Returns: 0 No
2219 * 1 Yes
2220 *
2221 * Locks: Assumes proc_fdlock for process is held by the caller
2222 *
2223 * Notes: The answer only remains valid so long as the proc_fdlock is
2224 * held by the caller.
91447636
A
2225 */
2226int
2d21ac55 2227fdavail(proc_t p, int n)
91447636
A
2228{
2229 struct filedesc *fdp = p->p_fd;
2230 struct fileproc **fpp;
2231 char *flags;
2232 int i, lim;
2233
2234 lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
2235 if ((i = lim - fdp->fd_nfiles) > 0 && (n -= i) <= 0)
2236 return (1);
2237 fpp = &fdp->fd_ofiles[fdp->fd_freefile];
2238 flags = &fdp->fd_ofileflags[fdp->fd_freefile];
2239 for (i = fdp->fd_nfiles - fdp->fd_freefile; --i >= 0; fpp++, flags++)
2240 if (*fpp == NULL && !(*flags & UF_RESERVED) && --n <= 0)
2241 return (1);
2242 return (0);
2243}
2244
91447636 2245
2d21ac55
A
2246/*
2247 * fdrelse
2248 *
2249 * Description: Legacy KPI wrapper function for _fdrelse
2250 *
2251 * Parameters: p Process in which fd lives
2252 * fd fd to free
2253 *
2254 * Returns: void
2255 *
2256 * Locks: Assumes proc_fdlock for process is held by the caller
2257 */
91447636 2258void
2d21ac55 2259fdrelse(proc_t p, int fd)
91447636 2260{
2d21ac55 2261 _fdrelse(p, fd);
91447636
A
2262}
2263
2264
2d21ac55
A
2265/*
2266 * fdgetf_noref
2267 *
2268 * Description: Get the fileproc pointer for the given fd from the per process
2269 * open file table without taking an explicit reference on it.
2270 *
2271 * Parameters: p Process containing fd
2272 * fd fd to obtain fileproc for
2273 * resultfp Pointer to pointer return area
2274 *
2275 * Returns: 0 Success
2276 * EBADF
2277 *
2278 * Implicit returns:
2279 * *resultfp (modified) Pointer to fileproc pointer
2280 *
2281 * Locks: Assumes proc_fdlock for process is held by the caller
2282 *
2283 * Notes: Because there is no reference explicitly taken, the returned
2284 * fileproc pointer is only valid so long as the proc_fdlock
2285 * remains held by the caller.
2286 */
91447636 2287int
2d21ac55 2288fdgetf_noref(proc_t p, int fd, struct fileproc **resultfp)
91447636
A
2289{
2290 struct filedesc *fdp = p->p_fd;
2291 struct fileproc *fp;
2292
2293 if (fd < 0 || fd >= fdp->fd_nfiles ||
2294 (fp = fdp->fd_ofiles[fd]) == NULL ||
2295 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
2296 return (EBADF);
2297 }
2298 if (resultfp)
2299 *resultfp = fp;
2300 return (0);
2301}
2302
2303
2d21ac55
A
2304/*
2305 * fp_getfvp
2306 *
2307 * Description: Get fileproc and vnode pointer for a given fd from the per
2308 * process open file table of the specified process, and if
2309 * successful, increment the f_iocount
2310 *
2311 * Parameters: p Process in which fd lives
2312 * fd fd to get information for
2313 * resultfp Pointer to result fileproc
2314 * pointer area, or 0 if none
2315 * resultvp Pointer to result vnode pointer
2316 * area, or 0 if none
2317 *
2318 * Returns: 0 Success
2319 * EBADF Bad file descriptor
2320 * ENOTSUP fd does not refer to a vnode
2321 *
2322 * Implicit returns:
2323 * *resultfp (modified) Fileproc pointer
2324 * *resultvp (modified) vnode pointer
2325 *
2326 * Notes: The resultfp and resultvp fields are optional, and may be
2327 * independently specified as NULL to skip returning information
2328 *
2329 * Locks: Internally takes and releases proc_fdlock
2330 */
91447636 2331int
2d21ac55 2332fp_getfvp(proc_t p, int fd, struct fileproc **resultfp, struct vnode **resultvp)
91447636
A
2333{
2334 struct filedesc *fdp = p->p_fd;
2335 struct fileproc *fp;
2336
2d21ac55 2337 proc_fdlock_spin(p);
91447636
A
2338 if (fd < 0 || fd >= fdp->fd_nfiles ||
2339 (fp = fdp->fd_ofiles[fd]) == NULL ||
2340 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
2341 proc_fdunlock(p);
2342 return (EBADF);
2343 }
2344 if (fp->f_type != DTYPE_VNODE) {
2345 proc_fdunlock(p);
2346 return(ENOTSUP);
2347 }
2348 fp->f_iocount++;
2349
2350 if (resultfp)
2351 *resultfp = fp;
2352 if (resultvp)
2353 *resultvp = (struct vnode *)fp->f_data;
2354 proc_fdunlock(p);
2355
2356 return (0);
2357}
2358
2359
2d21ac55
A
2360/*
2361 * fp_getfvpandvid
2362 *
2363 * Description: Get fileproc, vnode pointer, and vid for a given fd from the
2364 * per process open file table of the specified process, and if
2365 * successful, increment the f_iocount
2366 *
2367 * Parameters: p Process in which fd lives
2368 * fd fd to get information for
2369 * resultfp Pointer to result fileproc
2370 * pointer area, or 0 if none
2371 * resultvp Pointer to result vnode pointer
2372 * area, or 0 if none
2373 * vidp Pointer to resuld vid area
2374 *
2375 * Returns: 0 Success
2376 * EBADF Bad file descriptor
2377 * ENOTSUP fd does not refer to a vnode
2378 *
2379 * Implicit returns:
2380 * *resultfp (modified) Fileproc pointer
2381 * *resultvp (modified) vnode pointer
2382 * *vidp vid value
2383 *
2384 * Notes: The resultfp and resultvp fields are optional, and may be
2385 * independently specified as NULL to skip returning information
2386 *
2387 * Locks: Internally takes and releases proc_fdlock
2388 */
0c530ab8 2389int
2d21ac55
A
2390fp_getfvpandvid(proc_t p, int fd, struct fileproc **resultfp,
2391 struct vnode **resultvp, uint32_t *vidp)
0c530ab8
A
2392{
2393 struct filedesc *fdp = p->p_fd;
2394 struct fileproc *fp;
2395
2d21ac55 2396 proc_fdlock_spin(p);
0c530ab8
A
2397 if (fd < 0 || fd >= fdp->fd_nfiles ||
2398 (fp = fdp->fd_ofiles[fd]) == NULL ||
2399 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
2400 proc_fdunlock(p);
2401 return (EBADF);
2402 }
2403 if (fp->f_type != DTYPE_VNODE) {
2404 proc_fdunlock(p);
2405 return(ENOTSUP);
2406 }
2407 fp->f_iocount++;
2408
2409 if (resultfp)
2410 *resultfp = fp;
2411 if (resultvp)
2412 *resultvp = (struct vnode *)fp->f_data;
2413 if (vidp)
2414 *vidp = (uint32_t)vnode_vid((struct vnode *)fp->f_data);
2415 proc_fdunlock(p);
2416
2417 return (0);
2418}
2419
2d21ac55 2420
91447636 2421/*
2d21ac55
A
2422 * fp_getfsock
2423 *
2424 * Description: Get fileproc and socket pointer for a given fd from the
2425 * per process open file table of the specified process, and if
2426 * successful, increment the f_iocount
2427 *
2428 * Parameters: p Process in which fd lives
2429 * fd fd to get information for
2430 * resultfp Pointer to result fileproc
2431 * pointer area, or 0 if none
2432 * results Pointer to result socket
2433 * pointer area, or 0 if none
2434 *
91447636
A
2435 * Returns: EBADF The file descriptor is invalid
2436 * EOPNOTSUPP The file descriptor is not a socket
2437 * 0 Success
2438 *
2d21ac55
A
2439 * Implicit returns:
2440 * *resultfp (modified) Fileproc pointer
2441 * *results (modified) socket pointer
2442 *
91447636
A
2443 * Notes: EOPNOTSUPP should probably be ENOTSOCK; this function is only
2444 * ever called from accept1().
2445 */
2446int
2d21ac55
A
2447fp_getfsock(proc_t p, int fd, struct fileproc **resultfp,
2448 struct socket **results)
91447636
A
2449{
2450 struct filedesc *fdp = p->p_fd;
2451 struct fileproc *fp;
2452
2d21ac55 2453 proc_fdlock_spin(p);
91447636
A
2454 if (fd < 0 || fd >= fdp->fd_nfiles ||
2455 (fp = fdp->fd_ofiles[fd]) == NULL ||
2456 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
2457 proc_fdunlock(p);
2458 return (EBADF);
2459 }
2460 if (fp->f_type != DTYPE_SOCKET) {
2461 proc_fdunlock(p);
2462 return(EOPNOTSUPP);
2463 }
2464 fp->f_iocount++;
2465
2466 if (resultfp)
2467 *resultfp = fp;
2468 if (results)
2469 *results = (struct socket *)fp->f_data;
2470 proc_fdunlock(p);
2471
2472 return (0);
2473}
2474
2475
2d21ac55
A
2476/*
2477 * fp_getfkq
2478 *
2479 * Description: Get fileproc and kqueue pointer for a given fd from the
2480 * per process open file table of the specified process, and if
2481 * successful, increment the f_iocount
2482 *
2483 * Parameters: p Process in which fd lives
2484 * fd fd to get information for
2485 * resultfp Pointer to result fileproc
2486 * pointer area, or 0 if none
2487 * resultkq Pointer to result kqueue
2488 * pointer area, or 0 if none
2489 *
2490 * Returns: EBADF The file descriptor is invalid
2491 * EBADF The file descriptor is not a socket
2492 * 0 Success
2493 *
2494 * Implicit returns:
2495 * *resultfp (modified) Fileproc pointer
2496 * *resultkq (modified) kqueue pointer
2497 *
2498 * Notes: The second EBADF should probably be something else to make
2499 * the error condition distinct.
2500 */
91447636 2501int
2d21ac55
A
2502fp_getfkq(proc_t p, int fd, struct fileproc **resultfp,
2503 struct kqueue **resultkq)
91447636
A
2504{
2505 struct filedesc *fdp = p->p_fd;
2506 struct fileproc *fp;
2507
2d21ac55 2508 proc_fdlock_spin(p);
91447636
A
2509 if ( fd < 0 || fd >= fdp->fd_nfiles ||
2510 (fp = fdp->fd_ofiles[fd]) == NULL ||
2511 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
2512 proc_fdunlock(p);
2513 return (EBADF);
2514 }
2515 if (fp->f_type != DTYPE_KQUEUE) {
2516 proc_fdunlock(p);
2517 return(EBADF);
2518 }
2519 fp->f_iocount++;
2520
2521 if (resultfp)
2522 *resultfp = fp;
2523 if (resultkq)
2524 *resultkq = (struct kqueue *)fp->f_data;
2525 proc_fdunlock(p);
2526
2527 return (0);
2528}
2529
2d21ac55
A
2530
2531/*
2532 * fp_getfpshm
2533 *
2534 * Description: Get fileproc and POSIX shared memory pointer for a given fd
2535 * from the per process open file table of the specified process
2536 * and if successful, increment the f_iocount
2537 *
2538 * Parameters: p Process in which fd lives
2539 * fd fd to get information for
2540 * resultfp Pointer to result fileproc
2541 * pointer area, or 0 if none
2542 * resultpshm Pointer to result POSIX
2543 * shared memory pointer
2544 * pointer area, or 0 if none
2545 *
2546 * Returns: EBADF The file descriptor is invalid
2547 * EBADF The file descriptor is not a POSIX
2548 * shared memory area
2549 * 0 Success
2550 *
2551 * Implicit returns:
2552 * *resultfp (modified) Fileproc pointer
2553 * *resultpshm (modified) POSIX shared memory pointer
2554 *
2555 * Notes: The second EBADF should probably be something else to make
2556 * the error condition distinct.
2557 */
91447636 2558int
2d21ac55
A
2559fp_getfpshm(proc_t p, int fd, struct fileproc **resultfp,
2560 struct pshmnode **resultpshm)
91447636
A
2561{
2562 struct filedesc *fdp = p->p_fd;
2563 struct fileproc *fp;
2564
2d21ac55 2565 proc_fdlock_spin(p);
91447636
A
2566 if (fd < 0 || fd >= fdp->fd_nfiles ||
2567 (fp = fdp->fd_ofiles[fd]) == NULL ||
2568 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
2569 proc_fdunlock(p);
2570 return (EBADF);
2571 }
2572 if (fp->f_type != DTYPE_PSXSHM) {
2573
2574 proc_fdunlock(p);
2575 return(EBADF);
2576 }
2577 fp->f_iocount++;
2578
2579 if (resultfp)
2580 *resultfp = fp;
2581 if (resultpshm)
2582 *resultpshm = (struct pshmnode *)fp->f_data;
2583 proc_fdunlock(p);
2584
2585 return (0);
2586}
2587
2588
2d21ac55
A
2589/*
2590 * fp_getfsem
2591 *
2592 * Description: Get fileproc and POSIX semaphore pointer for a given fd from
2593 * the per process open file table of the specified process
2594 * and if successful, increment the f_iocount
2595 *
2596 * Parameters: p Process in which fd lives
2597 * fd fd to get information for
2598 * resultfp Pointer to result fileproc
2599 * pointer area, or 0 if none
2600 * resultpsem Pointer to result POSIX
2601 * semaphore pointer area, or
2602 * 0 if none
2603 *
2604 * Returns: EBADF The file descriptor is invalid
2605 * EBADF The file descriptor is not a POSIX
2606 * semaphore
2607 * 0 Success
2608 *
2609 * Implicit returns:
2610 * *resultfp (modified) Fileproc pointer
2611 * *resultpsem (modified) POSIX semaphore pointer
2612 *
2613 * Notes: The second EBADF should probably be something else to make
2614 * the error condition distinct.
2615 *
2616 * In order to support unnamed POSIX semaphores, the named
2617 * POSIX semaphores will have to move out of the per-process
2618 * open filetable, and into a global table that is shared with
2619 * unnamed POSIX semaphores, since unnamed POSIX semaphores
2620 * are typically used by declaring instances in shared memory,
2621 * and there's no other way to do this without changing the
2622 * underlying type, which would introduce binary compatibility
2623 * issues.
2624 */
91447636 2625int
2d21ac55
A
2626fp_getfpsem(proc_t p, int fd, struct fileproc **resultfp,
2627 struct psemnode **resultpsem)
91447636
A
2628{
2629 struct filedesc *fdp = p->p_fd;
2630 struct fileproc *fp;
2631
2d21ac55 2632 proc_fdlock_spin(p);
91447636
A
2633 if (fd < 0 || fd >= fdp->fd_nfiles ||
2634 (fp = fdp->fd_ofiles[fd]) == NULL ||
2635 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
2636 proc_fdunlock(p);
2637 return (EBADF);
2638 }
2639 if (fp->f_type != DTYPE_PSXSEM) {
2640 proc_fdunlock(p);
2641 return(EBADF);
2642 }
2643 fp->f_iocount++;
2644
2645 if (resultfp)
2646 *resultfp = fp;
2647 if (resultpsem)
2648 *resultpsem = (struct psemnode *)fp->f_data;
2649 proc_fdunlock(p);
2650
2651 return (0);
2652}
0c530ab8
A
2653
2654
2d21ac55
A
2655/*
2656 * fp_getfpipe
2657 *
2658 * Description: Get fileproc and pipe pointer for a given fd from the
2659 * per process open file table of the specified process
2660 * and if successful, increment the f_iocount
2661 *
2662 * Parameters: p Process in which fd lives
2663 * fd fd to get information for
2664 * resultfp Pointer to result fileproc
2665 * pointer area, or 0 if none
2666 * resultpipe Pointer to result pipe
2667 * pointer area, or 0 if none
2668 *
2669 * Returns: EBADF The file descriptor is invalid
2670 * EBADF The file descriptor is not a socket
2671 * 0 Success
2672 *
2673 * Implicit returns:
2674 * *resultfp (modified) Fileproc pointer
2675 * *resultpipe (modified) pipe pointer
2676 *
2677 * Notes: The second EBADF should probably be something else to make
2678 * the error condition distinct.
2679 */
0c530ab8 2680int
2d21ac55
A
2681fp_getfpipe(proc_t p, int fd, struct fileproc **resultfp,
2682 struct pipe **resultpipe)
0c530ab8
A
2683{
2684 struct filedesc *fdp = p->p_fd;
2685 struct fileproc *fp;
2686
2d21ac55 2687 proc_fdlock_spin(p);
0c530ab8
A
2688 if (fd < 0 || fd >= fdp->fd_nfiles ||
2689 (fp = fdp->fd_ofiles[fd]) == NULL ||
2690 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
2691 proc_fdunlock(p);
2692 return (EBADF);
2693 }
2694 if (fp->f_type != DTYPE_PIPE) {
2695 proc_fdunlock(p);
2696 return(EBADF);
2697 }
2698 fp->f_iocount++;
2699
2700 if (resultfp)
2701 *resultfp = fp;
2702 if (resultpipe)
2703 *resultpipe = (struct pipe *)fp->f_data;
2704 proc_fdunlock(p);
2705
2706 return (0);
2707}
2708
2709
2d21ac55
A
2710#define DTYPE_ATALK -1 /* XXX This does not belong here */
2711
2712
2713/*
2714 * fp_getfatalk
2715 *
2716 * Description: Get fileproc and atalk pointer for a given fd from the
2717 * per process open file table of the specified process
2718 * and if successful, increment the f_iocount
2719 *
2720 * Parameters: p Process in which fd lives
2721 * fd fd to get information for
2722 * resultfp Pointer to result fileproc
2723 * pointer area, or 0 if none
2724 * resultatalk Pointer to result atalk
2725 * pointer area, or 0 if none
2726 * Returns: EBADF The file descriptor is invalid
2727 * EBADF The file descriptor is not a socket
2728 * 0 Success
2729 *
2730 * Implicit returns:
2731 * *resultfp (modified) Fileproc pointer
2732 * *resultatalk (modified) atalk pointer
2733 *
2734 * Notes: The second EBADF should probably be something else to make
2735 * the error condition distinct.
2736 *
2737 * XXX This code is specific to AppleTalk protocol support, and
2738 * XXX should be conditionally compiled
2739 */
0c530ab8 2740int
2d21ac55
A
2741fp_getfatalk(proc_t p, int fd, struct fileproc **resultfp,
2742 struct atalk **resultatalk)
0c530ab8
A
2743{
2744 struct filedesc *fdp = p->p_fd;
2745 struct fileproc *fp;
2746
2d21ac55 2747 proc_fdlock_spin(p);
0c530ab8
A
2748 if (fd < 0 || fd >= fdp->fd_nfiles ||
2749 (fp = fdp->fd_ofiles[fd]) == NULL ||
2750 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
2751 proc_fdunlock(p);
2752 return (EBADF);
2753 }
2754 if (fp->f_type != (DTYPE_ATALK+1)) {
2755 proc_fdunlock(p);
2756 return(EBADF);
2757 }
2758 fp->f_iocount++;
2759
2760 if (resultfp)
2761 *resultfp = fp;
2762 if (resultatalk)
2763 *resultatalk = (struct atalk *)fp->f_data;
2764 proc_fdunlock(p);
2765
2766 return (0);
2767}
2768
2d21ac55
A
2769
2770/*
2771 * fp_lookup
2772 *
2773 * Description: Get fileproc pointer for a given fd from the per process
2774 * open file table of the specified process and if successful,
2775 * increment the f_iocount
2776 *
2777 * Parameters: p Process in which fd lives
2778 * fd fd to get information for
2779 * resultfp Pointer to result fileproc
2780 * pointer area, or 0 if none
2781 * locked !0 if the caller holds the
2782 * proc_fdlock, 0 otherwise
2783 *
2784 * Returns: 0 Success
2785 * EBADF Bad file descriptor
2786 *
2787 * Implicit returns:
2788 * *resultfp (modified) Fileproc pointer
2789 *
2790 * Locks: If the argument 'locked' is non-zero, then the caller is
2791 * expected to have taken and held the proc_fdlock; if it is
2792 * zero, than this routine internally takes and drops this lock.
2793 */
91447636 2794int
2d21ac55 2795fp_lookup(proc_t p, int fd, struct fileproc **resultfp, int locked)
91447636
A
2796{
2797 struct filedesc *fdp = p->p_fd;
2798 struct fileproc *fp;
2799
2800 if (!locked)
2d21ac55
A
2801 proc_fdlock_spin(p);
2802 if (fd < 0 || fdp == NULL || fd >= fdp->fd_nfiles ||
91447636
A
2803 (fp = fdp->fd_ofiles[fd]) == NULL ||
2804 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
2805 if (!locked)
2806 proc_fdunlock(p);
2807 return (EBADF);
2808 }
2809 fp->f_iocount++;
2810
2811 if (resultfp)
2812 *resultfp = fp;
2813 if (!locked)
2814 proc_fdunlock(p);
2815
2816 return (0);
2817}
2818
2d21ac55
A
2819
2820/*
2821 * fp_drop_written
2822 *
2823 * Description: Set the FP_WRITTEN flag on the fileproc and drop the I/O
2824 * reference previously taken by calling fp_lookup et. al.
2825 *
2826 * Parameters: p Process in which the fd lives
2827 * fd fd associated with the fileproc
2828 * fp fileproc on which to set the
2829 * flag and drop the reference
2830 *
2831 * Returns: 0 Success
2832 * fp_drop:EBADF Bad file descriptor
2833 *
2834 * Locks: This function internally takes and drops the proc_fdlock for
2835 * the supplied process
2836 *
2837 * Notes: The fileproc must correspond to the fd in the supplied proc
2838 */
91447636
A
2839int
2840fp_drop_written(proc_t p, int fd, struct fileproc *fp)
2841{
2842 int error;
2843
2d21ac55 2844 proc_fdlock_spin(p);
91447636
A
2845
2846 fp->f_flags |= FP_WRITTEN;
2847
2848 error = fp_drop(p, fd, fp, 1);
2849
2850 proc_fdunlock(p);
2851
2852 return (error);
2853}
2854
2855
2d21ac55
A
2856/*
2857 * fp_drop_event
2858 *
2859 * Description: Set the FP_WAITEVENT flag on the fileproc and drop the I/O
2860 * reference previously taken by calling fp_lookup et. al.
2861 *
2862 * Parameters: p Process in which the fd lives
2863 * fd fd associated with the fileproc
2864 * fp fileproc on which to set the
2865 * flag and drop the reference
2866 *
2867 * Returns: 0 Success
2868 * fp_drop:EBADF Bad file descriptor
2869 *
2870 * Locks: This function internally takes and drops the proc_fdlock for
2871 * the supplied process
2872 *
2873 * Notes: The fileproc must correspond to the fd in the supplied proc
2874 */
91447636
A
2875int
2876fp_drop_event(proc_t p, int fd, struct fileproc *fp)
2877{
2878 int error;
2879
2d21ac55 2880 proc_fdlock_spin(p);
91447636
A
2881
2882 fp->f_flags |= FP_WAITEVENT;
2883
2884 error = fp_drop(p, fd, fp, 1);
2885
2886 proc_fdunlock(p);
2887
2888 return (error);
2889}
2890
2d21ac55
A
2891
2892/*
2893 * fp_drop
2894 *
2895 * Description: Drop the I/O reference previously taken by calling fp_lookup
2896 * et. al.
2897 *
2898 * Parameters: p Process in which the fd lives
2899 * fd fd associated with the fileproc
2900 * fp fileproc on which to set the
2901 * flag and drop the reference
2902 * locked flag to internally take and
2903 * drop proc_fdlock if it is not
2904 * already held by the caller
2905 *
2906 * Returns: 0 Success
2907 * EBADF Bad file descriptor
2908 *
2909 * Locks: This function internally takes and drops the proc_fdlock for
2910 * the supplied process if 'locked' is non-zero, and assumes that
2911 * the caller already holds this lock if 'locked' is non-zero.
2912 *
2913 * Notes: The fileproc must correspond to the fd in the supplied proc
2914 */
1c79356b 2915int
2d21ac55 2916fp_drop(proc_t p, int fd, struct fileproc *fp, int locked)
1c79356b 2917{
91447636 2918 struct filedesc *fdp = p->p_fd;
2d21ac55 2919 int needwakeup = 0;
1c79356b 2920
91447636 2921 if (!locked)
2d21ac55 2922 proc_fdlock_spin(p);
91447636
A
2923 if ((fp == FILEPROC_NULL) && (fd < 0 || fd >= fdp->fd_nfiles ||
2924 (fp = fdp->fd_ofiles[fd]) == NULL ||
2925 ((fdp->fd_ofileflags[fd] & UF_RESERVED) &&
2926 !(fdp->fd_ofileflags[fd] & UF_CLOSING)))) {
2927 if (!locked)
2928 proc_fdunlock(p);
2929 return (EBADF);
2930 }
2931 fp->f_iocount--;
2932
2933 if (p->p_fpdrainwait && fp->f_iocount == 0) {
2934 p->p_fpdrainwait = 0;
2d21ac55 2935 needwakeup = 1;
91447636
A
2936 }
2937 if (!locked)
2938 proc_fdunlock(p);
2d21ac55
A
2939 if (needwakeup)
2940 wakeup(&p->p_fpdrainwait);
91447636 2941
1c79356b
A
2942 return (0);
2943}
2944
2d21ac55
A
2945
2946/*
2947 * file_vnode
2948 *
2949 * Description: Given an fd, look it up in the current process's per process
2950 * open file table, and return its internal vnode pointer.
2951 *
2952 * Parameters: fd fd to obtain vnode from
2953 * vpp pointer to vnode return area
2954 *
2955 * Returns: 0 Success
2956 * EINVAL The fd does not refer to a
2957 * vnode fileproc entry
2958 * fp_lookup:EBADF Bad file descriptor
2959 *
2960 * Implicit returns:
2961 * *vpp (modified) Returned vnode pointer
2962 *
2963 * Locks: This function internally takes and drops the proc_fdlock for
2964 * the current process
2965 *
2966 * Notes: If successful, this function increments the f_iocount on the
2967 * fd's corresponding fileproc.
2968 *
2969 * The fileproc referenced is not returned; because of this, care
2970 * must be taken to not drop the last reference (e.g. by closing
2971 * the file). This is inhernely unsafe, since the reference may
2972 * not be recoverable from the vnode, if there is a subsequent
2973 * close that destroys the associate fileproc. The caller should
2974 * therefore retain their own reference on the fileproc so that
2975 * the f_iocount can be dropped subsequently. Failure to do this
2976 * can result in the returned pointer immediately becoming invalid
2977 * following the call.
2978 *
2979 * Use of this function is discouraged.
2980 */
91447636
A
2981int
2982file_vnode(int fd, struct vnode **vpp)
1c79356b 2983{
2d21ac55 2984 proc_t p = current_proc();
91447636
A
2985 struct fileproc *fp;
2986 int error;
2987
2d21ac55 2988 proc_fdlock_spin(p);
91447636
A
2989 if ( (error = fp_lookup(p, fd, &fp, 1)) ) {
2990 proc_fdunlock(p);
2991 return(error);
2992 }
2993 if (fp->f_type != DTYPE_VNODE) {
2994 fp_drop(p, fd, fp,1);
2995 proc_fdunlock(p);
2996 return(EINVAL);
2997 }
2998 *vpp = (struct vnode *)fp->f_data;
2999 proc_fdunlock(p);
3000
3001 return(0);
1c79356b
A
3002}
3003
91447636 3004
2d21ac55
A
3005/*
3006 * file_socket
3007 *
3008 * Description: Given an fd, look it up in the current process's per process
3009 * open file table, and return its internal socket pointer.
3010 *
3011 * Parameters: fd fd to obtain vnode from
3012 * sp pointer to socket return area
3013 *
3014 * Returns: 0 Success
3015 * ENOTSOCK Not a socket
3016 * fp_lookup:EBADF Bad file descriptor
3017 *
3018 * Implicit returns:
3019 * *sp (modified) Returned socket pointer
3020 *
3021 * Locks: This function internally takes and drops the proc_fdlock for
3022 * the current process
3023 *
3024 * Notes: If successful, this function increments the f_iocount on the
3025 * fd's corresponding fileproc.
3026 *
3027 * The fileproc referenced is not returned; because of this, care
3028 * must be taken to not drop the last reference (e.g. by closing
3029 * the file). This is inhernely unsafe, since the reference may
3030 * not be recoverable from the socket, if there is a subsequent
3031 * close that destroys the associate fileproc. The caller should
3032 * therefore retain their own reference on the fileproc so that
3033 * the f_iocount can be dropped subsequently. Failure to do this
3034 * can result in the returned pointer immediately becoming invalid
3035 * following the call.
3036 *
3037 * Use of this function is discouraged.
3038 */
1c79356b 3039int
91447636 3040file_socket(int fd, struct socket **sp)
1c79356b 3041{
2d21ac55 3042 proc_t p = current_proc();
91447636
A
3043 struct fileproc *fp;
3044 int error;
3045
2d21ac55 3046 proc_fdlock_spin(p);
91447636
A
3047 if ( (error = fp_lookup(p, fd, &fp, 1)) ) {
3048 proc_fdunlock(p);
3049 return(error);
3050 }
3051 if (fp->f_type != DTYPE_SOCKET) {
3052 fp_drop(p, fd, fp,1);
3053 proc_fdunlock(p);
3054 return(ENOTSOCK);
3055 }
3056 *sp = (struct socket *)fp->f_data;
3057 proc_fdunlock(p);
1c79356b 3058
91447636
A
3059 return(0);
3060}
3061
2d21ac55
A
3062
3063/*
3064 * file_flags
3065 *
3066 * Description: Given an fd, look it up in the current process's per process
3067 * open file table, and return its fileproc's flags field.
3068 *
3069 * Parameters: fd fd whose flags are to be
3070 * retrieved
3071 * flags pointer to flags data area
3072 *
3073 * Returns: 0 Success
3074 * ENOTSOCK Not a socket
3075 * fp_lookup:EBADF Bad file descriptor
3076 *
3077 * Implicit returns:
3078 * *flags (modified) Returned flags field
3079 *
3080 * Locks: This function internally takes and drops the proc_fdlock for
3081 * the current process
3082 *
3083 * Notes: This function will internally increment and decrement the
3084 * f_iocount of the fileproc as part of its operation.
3085 */
91447636 3086int
2d21ac55 3087file_flags(int fd, int *flags)
91447636
A
3088{
3089
2d21ac55 3090 proc_t p = current_proc();
91447636
A
3091 struct fileproc *fp;
3092 int error;
3093
2d21ac55 3094 proc_fdlock_spin(p);
91447636
A
3095 if ( (error = fp_lookup(p, fd, &fp, 1)) ) {
3096 proc_fdunlock(p);
3097 return(error);
3098 }
3099 *flags = (int)fp->f_flag;
3100 fp_drop(p, fd, fp,1);
3101 proc_fdunlock(p);
3102
3103 return(0);
3104}
3105
3106
2d21ac55
A
3107/*
3108 * file_drop
3109 *
3110 * Description: Drop an iocount reference on an fd, and wake up any waiters
3111 * for draining (i.e. blocked in fileproc_drain() called during
3112 * the last attempt to close a file).
3113 *
3114 * Parameters: fd fd on which an ioreference is
3115 * to be dropped
3116 *
3117 * Returns: 0 Success
3118 * EBADF Bad file descriptor
3119 *
3120 * Description: Given an fd, look it up in the current process's per process
3121 * open file table, and drop it's fileproc's f_iocount by one
3122 *
3123 * Notes: This is intended as a corresponding operation to the functions
3124 * file_vnode() and file_socket() operations.
3125 *
3126 * Technically, the close reference is supposed to be protected
3127 * by a fileproc_drain(), however, a drain will only block if
3128 * the fd refers to a character device, and that device has had
3129 * preparefileread() called on it. If it refers to something
3130 * other than a character device, then the drain will occur and
3131 * block each close attempt, rather than merely the last close.
3132 *
3133 * Since it's possible for an fd that refers to a character
3134 * device to have an intermediate close followed by an open to
3135 * cause a different file to correspond to that descriptor,
3136 * unless there was a cautionary reference taken on the fileproc,
3137 * this is an inherently unsafe function. This happens in the
3138 * case where multiple fd's in a process refer to the same
3139 * character device (e.g. stdin/out/err pointing to a tty, etc.).
3140 *
3141 * Use of this function is discouraged.
3142 */
91447636
A
3143int
3144file_drop(int fd)
3145{
3146 struct fileproc *fp;
2d21ac55
A
3147 proc_t p = current_proc();
3148 int needwakeup = 0;
91447636 3149
2d21ac55 3150 proc_fdlock_spin(p);
91447636
A
3151 if (fd < 0 || fd >= p->p_fd->fd_nfiles ||
3152 (fp = p->p_fd->fd_ofiles[fd]) == NULL ||
3153 ((p->p_fd->fd_ofileflags[fd] & UF_RESERVED) &&
3154 !(p->p_fd->fd_ofileflags[fd] & UF_CLOSING))) {
3155 proc_fdunlock(p);
1c79356b 3156 return (EBADF);
91447636
A
3157 }
3158 fp->f_iocount --;
3159
3160 if (p->p_fpdrainwait && fp->f_iocount == 0) {
3161 p->p_fpdrainwait = 0;
2d21ac55 3162 needwakeup = 1;
91447636
A
3163 }
3164 proc_fdunlock(p);
1c79356b 3165
2d21ac55
A
3166 if (needwakeup)
3167 wakeup(&p->p_fpdrainwait);
3168 return(0);
1c79356b
A
3169}
3170
2d21ac55
A
3171
3172/*
3173 * falloc
3174 *
3175 * Description: Allocate an entry in the per process open file table and
3176 * return the corresponding fileproc and fd.
3177 *
3178 * Parameters: p The process in whose open file
3179 * table the fd is to be allocated
3180 * resultfp Pointer to fileproc pointer
3181 * return area
3182 * resultfd Pointer to fd return area
3183 * ctx VFS context
3184 *
3185 * Returns: 0 Success
3186 * falloc:ENFILE Too many open files in system
3187 * falloc:EMFILE Too many open files in process
3188 * falloc:ENOMEM M_FILEPROC or M_FILEGLOB zone
3189 * exhausted
3190 *
3191 * Implicit returns:
3192 * *resultfd (modified) Returned fileproc pointer
3193 * *resultfd (modified) Returned fd
3194 *
3195 * Locks: This function takes and drops the proc_fdlock; if this lock
3196 * is alread held, use falloc_locked() instead.
3197 *
3198 * Notes: This function takes separate process and context arguments
3199 * solely to support kern_exec.c; otherwise, it would take
3200 * neither, and expect falloc_locked() to use the
3201 * vfs_context_current() routine internally.
3202 */
91447636 3203int
2d21ac55 3204falloc(proc_t p, struct fileproc **resultfp, int *resultfd, vfs_context_t ctx)
91447636
A
3205{
3206 int error;
3207
3208 proc_fdlock(p);
2d21ac55 3209 error = falloc_locked(p, resultfp, resultfd, ctx, 1);
91447636
A
3210 proc_fdunlock(p);
3211
3212 return(error);
3213}
2d21ac55
A
3214
3215
1c79356b 3216/*
2d21ac55
A
3217 * falloc_locked
3218 *
1c79356b
A
3219 * Create a new open file structure and allocate
3220 * a file decriptor for the process that refers to it.
2d21ac55
A
3221 *
3222 * Returns: 0 Success
3223 *
3224 * Description: Allocate an entry in the per process open file table and
3225 * return the corresponding fileproc and fd.
3226 *
3227 * Parameters: p The process in whose open file
3228 * table the fd is to be allocated
3229 * resultfp Pointer to fileproc pointer
3230 * return area
3231 * resultfd Pointer to fd return area
3232 * ctx VFS context
3233 * locked Flag to indicate whether the
3234 * caller holds proc_fdlock
3235 *
3236 * Returns: 0 Success
3237 * ENFILE Too many open files in system
3238 * fdalloc:EMFILE Too many open files in process
3239 * ENOMEM M_FILEPROC or M_FILEGLOB zone
3240 * exhausted
3241 * fdalloc:ENOMEM
3242 *
3243 * Implicit returns:
3244 * *resultfd (modified) Returned fileproc pointer
3245 * *resultfd (modified) Returned fd
3246 *
3247 * Locks: If the parameter 'locked' is zero, this function takes and
3248 * drops the proc_fdlock; if non-zero, the caller must hold the
3249 * lock.
3250 *
3251 * Notes: If you intend to use a non-zero 'locked' parameter, use the
3252 * utility function falloc() instead.
3253 *
3254 * This function takes separate process and context arguments
3255 * solely to support kern_exec.c; otherwise, it would take
3256 * neither, and use the vfs_context_current() routine internally.
1c79356b
A
3257 */
3258int
2d21ac55
A
3259falloc_locked(proc_t p, struct fileproc **resultfp, int *resultfd,
3260 vfs_context_t ctx, int locked)
1c79356b 3261{
91447636
A
3262 struct fileproc *fp, *fq;
3263 struct fileglob *fg;
3264 int error, nfd;
3265
3266 if (!locked)
3267 proc_fdlock(p);
3268 if ( (error = fdalloc(p, 0, &nfd)) ) {
3269 if (!locked)
3270 proc_fdunlock(p);
1c79356b 3271 return (error);
91447636 3272 }
1c79356b 3273 if (nfiles >= maxfiles) {
91447636
A
3274 if (!locked)
3275 proc_fdunlock(p);
1c79356b
A
3276 tablefull("file");
3277 return (ENFILE);
3278 }
2d21ac55
A
3279#if CONFIG_MACF
3280 error = mac_file_check_create(proc_ucred(p));
3281 if (error) {
3282 if (!locked)
3283 proc_fdunlock(p);
3284 return (error);
3285 }
3286#endif
3287
1c79356b
A
3288 /*
3289 * Allocate a new file descriptor.
3290 * If the process has file descriptor zero open, add to the list
3291 * of open files at that point, otherwise put it at the front of
3292 * the list of open files.
3293 */
91447636
A
3294 proc_fdunlock(p);
3295
3296 MALLOC_ZONE(fp, struct fileproc *, sizeof(struct fileproc), M_FILEPROC, M_WAITOK);
2d21ac55
A
3297 if (fp == NULL) {
3298 if (locked)
3299 proc_fdlock(p);
3300 return (ENOMEM);
3301 }
91447636 3302 MALLOC_ZONE(fg, struct fileglob *, sizeof(struct fileglob), M_FILEGLOB, M_WAITOK);
2d21ac55
A
3303 if (fg == NULL) {
3304 FREE_ZONE(fp, sizeof(*fp), M_FILEPROC);
3305 if (locked)
3306 proc_fdlock(p);
3307 return (ENOMEM);
3308 }
91447636
A
3309 bzero(fp, sizeof(struct fileproc));
3310 bzero(fg, sizeof(struct fileglob));
3311 lck_mtx_init(&fg->fg_lock, file_lck_grp, file_lck_attr);
3312
3313 fp->f_iocount = 1;
3314 fg->fg_count = 1;
3315 fp->f_fglob = fg;
2d21ac55
A
3316#if CONFIG_MACF
3317 mac_file_label_init(fg);
3318#endif
3319
3320 kauth_cred_ref(ctx->vc_ucred);
91447636
A
3321
3322 proc_fdlock(p);
3323
2d21ac55 3324 fp->f_cred = ctx->vc_ucred;
91447636 3325
2d21ac55
A
3326#if CONFIG_MACF
3327 mac_file_label_associate(fp->f_cred, fg);
3328#endif
3329
3330 lck_mtx_lock_spin(file_flist_lock);
91447636 3331
1c79356b 3332 nfiles++;
91447636
A
3333
3334 if ( (fq = p->p_fd->fd_ofiles[0]) ) {
3335 LIST_INSERT_AFTER(fq->f_fglob, fg, f_list);
3336 } else {
3337 LIST_INSERT_HEAD(&filehead, fg, f_list);
3338 }
3339 lck_mtx_unlock(file_flist_lock);
3340
3341 p->p_fd->fd_ofiles[nfd] = fp;
3342
3343 if (!locked)
3344 proc_fdunlock(p);
3345
1c79356b
A
3346 if (resultfp)
3347 *resultfp = fp;
3348 if (resultfd)
91447636
A
3349 *resultfd = nfd;
3350
1c79356b
A
3351 return (0);
3352}
3353
2d21ac55 3354
1c79356b 3355/*
2d21ac55
A
3356 * fg_free
3357 *
3358 * Description: Free a file structure; drop the global open file count, and
3359 * drop the credential reference, if the fileglob has one, and
3360 * destroy the instance mutex before freeing
3361 *
3362 * Parameters: fg Pointer to fileglob to be
3363 * freed
3364 *
3365 * Returns: void
1c79356b
A
3366 */
3367void
2d21ac55 3368fg_free(struct fileglob *fg)
1c79356b 3369{
2d21ac55 3370 lck_mtx_lock_spin(file_flist_lock);
91447636
A
3371 LIST_REMOVE(fg, f_list);
3372 nfiles--;
3373 lck_mtx_unlock(file_flist_lock);
1c79356b 3374
0c530ab8
A
3375 if (IS_VALID_CRED(fg->fg_cred)) {
3376 kauth_cred_unref(&fg->fg_cred);
1c79356b 3377 }
91447636 3378 lck_mtx_destroy(&fg->fg_lock, file_lck_grp);
fa4905b1 3379
2d21ac55
A
3380#if CONFIG_MACF
3381 mac_file_label_destroy(fg);
3382#endif
91447636 3383 FREE_ZONE(fg, sizeof *fg, M_FILEGLOB);
1c79356b
A
3384}
3385
2d21ac55
A
3386
3387/*
3388 * fdexec
3389 *
3390 * Description: Perform close-on-exec processing for all files in a process
3391 * that are either marked as close-on-exec, or which were in the
3392 * process of being opened at the time of the execve
3393 *
3394 * Parameters: p Pointer to process calling
3395 * execve
3396 *
3397 * Returns: void
3398 *
3399 * Locks: This function internally takes and drops proc_fdlock()
3400 *
3401 * Notes: This function drops and retakes the kernel funnel; this is
3402 * inherently unsafe, since another thread may have the
3403 * proc_fdlock.
3404 *
3405 * XXX: We should likely reverse the lock and funnel drop/acquire
3406 * order to avoid the small race window; it's also possible that
3407 * if the program doing the exec has an outstanding listen socket
3408 * and a network connection is completed asyncrhonously that we
3409 * will end up with a "ghost" socket reference in the new process.
3410 *
3411 * This needs reworking to make it safe to remove the funnel from
3412 * the execve and posix_spawn system calls.
3413 */
1c79356b 3414void
2d21ac55 3415fdexec(proc_t p)
1c79356b 3416{
91447636
A
3417 struct filedesc *fdp = p->p_fd;
3418 int i = fdp->fd_lastfile;
6601e61a 3419 struct fileproc *fp;
91447636 3420
91447636 3421 proc_fdlock(p);
1c79356b 3422 while (i >= 0) {
55e303ae 3423
2d21ac55
A
3424 fp = fdp->fd_ofiles[i];
3425 if (
3426 ((fdp->fd_ofileflags[i] & (UF_RESERVED|UF_EXCLOSE)) == UF_EXCLOSE)
3427#if CONFIG_MACF
3428 || (fp && mac_file_check_inherit(proc_ucred(p), fp->f_fglob))
3429#endif
3430 ) {
3431 if (i < fdp->fd_knlistsize)
3432 knote_fdclose(p, i);
6601e61a 3433 procfdtbl_clearfd(p, i);
1c79356b
A
3434 if (i == fdp->fd_lastfile && i > 0)
3435 fdp->fd_lastfile--;
6601e61a
A
3436 if (i < fdp->fd_freefile)
3437 fdp->fd_freefile = i;
91447636 3438 closef_locked(fp, fp->f_fglob, p);
2d21ac55 3439 FREE_ZONE(fp, sizeof(*fp), M_FILEPROC);
1c79356b 3440 }
6601e61a 3441 i--;
1c79356b 3442 }
91447636 3443 proc_fdunlock(p);
1c79356b
A
3444}
3445
2d21ac55 3446
1c79356b 3447/*
2d21ac55
A
3448 * fdcopy
3449 *
3450 * Description: Copy a filedesc structure. This is normally used as part of
3451 * forkproc() when forking a new process, to copy the per process
3452 * open file table over to the new process.
3453 *
3454 * Parameters: p Process whose open file table
3455 * is to be copied (parent)
3456 * uth_cdir Per thread current working
3457 * cirectory, or NULL
3458 *
3459 * Returns: NULL Copy failed
3460 * !NULL Pointer to new struct filedesc
3461 *
3462 * Locks: This function internally takes and drops proc_fdlock()
3463 *
3464 * Notes: Files are copied directly, ignoring the new resource limits
3465 * for the process that's being copied into. Since the descriptor
3466 * references are just additional references, this does not count
3467 * against the number of open files on the system.
3468 *
3469 * The struct filedesc includes the current working directory,
3470 * and the current root directory, if the process is chroot'ed.
3471 *
3472 * If the exec was called by a thread using a per thread current
3473 * working directory, we inherit the working directory from the
3474 * thread making the call, rather than from the process.
3475 *
3476 * In the case of a failure to obtain a reference, for most cases,
3477 * the file entry will be silently droppped. There's an exception
3478 * for the case of a chroot dir, since a failure to to obtain a
3479 * reference there would constitute an "escape" from the chroot
3480 * environment, which must not be allowed. In that case, we will
3481 * deny the execve() operation, rather than allowing the escape.
1c79356b
A
3482 */
3483struct filedesc *
2d21ac55 3484fdcopy(proc_t p, vnode_t uth_cdir)
1c79356b 3485{
91447636
A
3486 struct filedesc *newfdp, *fdp = p->p_fd;
3487 int i;
3488 struct fileproc *ofp, *fp;
3489 vnode_t v_dir;
1c79356b
A
3490
3491 MALLOC_ZONE(newfdp, struct filedesc *,
6601e61a 3492 sizeof(*newfdp), M_FILEDESC, M_WAITOK);
91447636
A
3493 if (newfdp == NULL)
3494 return(NULL);
3495
3496 proc_fdlock(p);
3497
3498 /*
3499 * the FD_CHROOT flag will be inherited via this copy
3500 */
6601e61a 3501 (void) memcpy(newfdp, fdp, sizeof(*newfdp));
91447636
A
3502
3503 /*
2d21ac55
A
3504 * If we are running with per-thread current working directories,
3505 * inherit the new current working directory from the current thread
3506 * instead, before we take our references.
3507 */
3508 if (uth_cdir != NULLVP)
3509 newfdp->fd_cdir = uth_cdir;
3510
3511 /*
3512 * For both fd_cdir and fd_rdir make sure we get
91447636
A
3513 * a valid reference... if we can't, than set
3514 * set the pointer(s) to NULL in the child... this
3515 * will keep us from using a non-referenced vp
3516 * and allows us to do the vnode_rele only on
3517 * a properly referenced vp
3518 */
3519 if ( (v_dir = newfdp->fd_cdir) ) {
3520 if (vnode_getwithref(v_dir) == 0) {
3521 if ( (vnode_ref(v_dir)) )
3522 newfdp->fd_cdir = NULL;
3523 vnode_put(v_dir);
3524 } else
3525 newfdp->fd_cdir = NULL;
3526 }
3527 if (newfdp->fd_cdir == NULL && fdp->fd_cdir) {
3528 /*
3529 * we couldn't get a new reference on
3530 * the current working directory being
3531 * inherited... we might as well drop
3532 * our reference from the parent also
3533 * since the vnode has gone DEAD making
3534 * it useless... by dropping it we'll
3535 * be that much closer to recyling it
3536 */
3537 vnode_rele(fdp->fd_cdir);
3538 fdp->fd_cdir = NULL;
3539 }
3540
3541 if ( (v_dir = newfdp->fd_rdir) ) {
3542 if (vnode_getwithref(v_dir) == 0) {
3543 if ( (vnode_ref(v_dir)) )
3544 newfdp->fd_rdir = NULL;
3545 vnode_put(v_dir);
2d21ac55 3546 } else {
91447636 3547 newfdp->fd_rdir = NULL;
2d21ac55 3548 }
91447636 3549 }
2d21ac55 3550 /* Coming from a chroot environment and unable to get a reference... */
91447636
A
3551 if (newfdp->fd_rdir == NULL && fdp->fd_rdir) {
3552 /*
2d21ac55
A
3553 * We couldn't get a new reference on
3554 * the chroot directory being
3555 * inherited... this is fatal, since
3556 * otherwise it would constitute an
3557 * escape from a chroot environment by
3558 * the new process.
91447636 3559 */
2d21ac55
A
3560 if (newfdp->fd_cdir)
3561 vnode_rele(newfdp->fd_cdir);
3562 FREE_ZONE(newfdp, sizeof *newfdp, M_FILEDESC);
3563 return(NULL);
91447636 3564 }
1c79356b
A
3565 newfdp->fd_refcnt = 1;
3566
3567 /*
3568 * If the number of open files fits in the internal arrays
3569 * of the open file structure, use them, otherwise allocate
3570 * additional memory for the number of descriptors currently
3571 * in use.
3572 */
3573 if (newfdp->fd_lastfile < NDFILE)
3574 i = NDFILE;
3575 else {
3576 /*
3577 * Compute the smallest multiple of NDEXTENT needed
3578 * for the file descriptors currently in use,
3579 * allowing the table to shrink.
3580 */
3581 i = newfdp->fd_nfiles;
3582 while (i > 2 * NDEXTENT && i > newfdp->fd_lastfile * 2)
3583 i /= 2;
3584 }
91447636
A
3585 proc_fdunlock(p);
3586
3587 MALLOC_ZONE(newfdp->fd_ofiles, struct fileproc **,
1c79356b 3588 i * OFILESIZE, M_OFILETABL, M_WAITOK);
91447636
A
3589 if (newfdp->fd_ofiles == NULL) {
3590 if (newfdp->fd_cdir)
3591 vnode_rele(newfdp->fd_cdir);
3592 if (newfdp->fd_rdir)
3593 vnode_rele(newfdp->fd_rdir);
3594
2d21ac55 3595 FREE_ZONE(newfdp, sizeof(*newfdp), M_FILEDESC);
91447636
A
3596 return(NULL);
3597 }
6601e61a 3598 (void) memset(newfdp->fd_ofiles, 0, i * OFILESIZE);
91447636
A
3599 proc_fdlock(p);
3600
1c79356b
A
3601 newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];
3602 newfdp->fd_nfiles = i;
91447636 3603
1c79356b 3604 if (fdp->fd_nfiles > 0) {
91447636
A
3605 struct fileproc **fpp;
3606 char *flags;
1c79356b
A
3607
3608 (void) memcpy(newfdp->fd_ofiles, fdp->fd_ofiles,
2d21ac55 3609 (newfdp->fd_lastfile + 1) * sizeof(*fdp->fd_ofiles));
1c79356b 3610 (void) memcpy(newfdp->fd_ofileflags, fdp->fd_ofileflags,
2d21ac55 3611 (newfdp->fd_lastfile + 1) * sizeof(*fdp->fd_ofileflags));
1c79356b 3612
55e303ae
A
3613 /*
3614 * kq descriptors cannot be copied.
3615 */
3616 if (newfdp->fd_knlistsize != -1) {
3617 fpp = &newfdp->fd_ofiles[newfdp->fd_lastfile];
3618 for (i = newfdp->fd_lastfile; i >= 0; i--, fpp--) {
3619 if (*fpp != NULL && (*fpp)->f_type == DTYPE_KQUEUE) {
3620 *fpp = NULL;
3621 if (i < newfdp->fd_freefile)
3622 newfdp->fd_freefile = i;
3623 }
3624 if (*fpp == NULL && i == newfdp->fd_lastfile && i > 0)
3625 newfdp->fd_lastfile--;
3626 }
3627 newfdp->fd_knlist = NULL;
3628 newfdp->fd_knlistsize = -1;
3629 newfdp->fd_knhash = NULL;
3630 newfdp->fd_knhashmask = 0;
3631 }
1c79356b
A
3632 fpp = newfdp->fd_ofiles;
3633 flags = newfdp->fd_ofileflags;
91447636 3634
6601e61a 3635 for (i = newfdp->fd_lastfile + 1; --i >= 0; fpp++, flags++)
91447636
A
3636 if ((ofp = *fpp) != NULL && !(*flags & UF_RESERVED)) {
3637 MALLOC_ZONE(fp, struct fileproc *, sizeof(struct fileproc), M_FILEPROC, M_WAITOK);
2d21ac55
A
3638 if (fp == NULL) {
3639 /*
3640 * XXX no room to copy, unable to
3641 * XXX safely unwind state at present
3642 */
3643 *fpp = NULL;
3644 } else {
3645 bzero(fp, sizeof(struct fileproc));
3646 fp->f_flags = ofp->f_flags;
3647 //fp->f_iocount = ofp->f_iocount;
3648 fp->f_iocount = 0;
3649 fp->f_fglob = ofp->f_fglob;
3650 (void)fg_ref(fp);
3651 *fpp = fp;
3652 }
1c79356b 3653 } else {
6601e61a
A
3654 if (i < newfdp->fd_freefile)
3655 newfdp->fd_freefile = i;
1c79356b
A
3656 *fpp = NULL;
3657 *flags = 0;
3658 }
6601e61a 3659 }
1c79356b 3660
91447636 3661 proc_fdunlock(p);
1c79356b
A
3662 return (newfdp);
3663}
3664
2d21ac55 3665
1c79356b 3666/*
2d21ac55
A
3667 * fdfree
3668 *
3669 * Description: Release a filedesc (per process open file table) structure;
3670 * this is done on process exit(), or from forkproc_free() if
3671 * the fork fails for some reason subsequent to a successful
3672 * call to fdcopy()
3673 *
3674 * Parameters: p Pointer to process going away
3675 *
3676 * Returns: void
3677 *
3678 * Locks: This function internally takes and drops proc_fdlock()
1c79356b
A
3679 */
3680void
2d21ac55 3681fdfree(proc_t p)
1c79356b 3682{
fa4905b1 3683 struct filedesc *fdp;
91447636 3684 struct fileproc *fp;
fa4905b1 3685 int i;
91447636
A
3686
3687 proc_fdlock(p);
1c79356b 3688
55e303ae 3689 /* Certain daemons might not have file descriptors */
91447636 3690 fdp = p->p_fd;
55e303ae 3691
91447636
A
3692 if ((fdp == NULL) || (--fdp->fd_refcnt > 0)) {
3693 proc_fdunlock(p);
1c79356b 3694 return;
91447636
A
3695 }
3696 if (fdp->fd_refcnt == 0xffff)
3697 panic("fdfree: bad fd_refcnt");
55e303ae
A
3698
3699 /* Last reference: the structure can't change out from under us */
91447636
A
3700
3701 if (fdp->fd_nfiles > 0 && fdp->fd_ofiles) {
3702 for (i = fdp->fd_lastfile; i >= 0; i--) {
55e303ae 3703 if ((fp = fdp->fd_ofiles[i]) != NULL) {
91447636
A
3704
3705 if (fdp->fd_ofileflags[i] & UF_RESERVED)
2d21ac55 3706 panic("fdfree: found fp with UF_RESERVED\n");
91447636
A
3707
3708 /* closef drops the iocount ... */
3709 if ((fp->f_flags & FP_INCHRREAD) != 0)
3710 fp->f_iocount++;
6601e61a 3711 procfdtbl_reservefd(p, i);
91447636 3712
55e303ae
A
3713 if (i < fdp->fd_knlistsize)
3714 knote_fdclose(p, i);
91447636
A
3715 if (fp->f_flags & FP_WAITEVENT)
3716 (void)waitevent_close(p, fp);
3717 (void) closef_locked(fp, fp->f_fglob, p);
2d21ac55 3718 FREE_ZONE(fp, sizeof(*fp), M_FILEPROC);
55e303ae 3719 }
91447636
A
3720 }
3721 FREE_ZONE(fdp->fd_ofiles, fdp->fd_nfiles * OFILESIZE, M_OFILETABL);
3722 fdp->fd_ofiles = NULL;
3723 fdp->fd_nfiles = 0;
3724 }
55e303ae 3725
91447636
A
3726 proc_fdunlock(p);
3727
3728 if (fdp->fd_cdir)
3729 vnode_rele(fdp->fd_cdir);
3730 if (fdp->fd_rdir)
3731 vnode_rele(fdp->fd_rdir);
55e303ae 3732
2d21ac55 3733 proc_fdlock_spin(p);
91447636
A
3734 p->p_fd = NULL;
3735 proc_fdunlock(p);
55e303ae
A
3736
3737 if (fdp->fd_knlist)
3738 FREE(fdp->fd_knlist, M_KQUEUE);
3739 if (fdp->fd_knhash)
3740 FREE(fdp->fd_knhash, M_KQUEUE);
3741
2d21ac55 3742 FREE_ZONE(fdp, sizeof(*fdp), M_FILEDESC);
1c79356b
A
3743}
3744
2d21ac55
A
3745
3746/*
3747 * closef_finish
3748 *
3749 * Description: Called on last open instance for a fileglob for a file being
3750 * closed.
3751 *
3752 * Parameters: fp Pointer to fileproc for fd
3753 * fg Pointer to fileglob for fd
3754 * p Pointer to proc structure
3755 *
3756 * Returns: 0 Success
3757 * <fo_close>:??? Anything returnable by a per-fileops
3758 * close function
3759 *
3760 * Note: fp can only be non-NULL if p is also non-NULL. If p is NULL,
3761 * then fg must eith be locked (FHASLOCK) or must not have a
3762 * type of DTYPE_VNODE.
3763 *
3764 * On return, the fg is freed.
3765 *
3766 * This function may block draining output to a character
3767 * device on last close of that device.
3768 */
9bccf70c 3769static int
2d21ac55 3770closef_finish(struct fileproc *fp, struct fileglob *fg, proc_t p, vfs_context_t ctx)
9bccf70c 3771{
9bccf70c
A
3772 int error;
3773
91447636 3774
2d21ac55 3775 /* fg_ops completed initialization? */
91447636 3776 if (fg->fg_ops)
2d21ac55 3777 error = fo_close(fg, ctx);
9bccf70c
A
3778 else
3779 error = 0;
91447636 3780
2d21ac55 3781 /* if fp is non-NULL, drain it out */
91447636 3782 if (((fp != (struct fileproc *)0) && ((fp->f_flags & FP_INCHRREAD) != 0))) {
2d21ac55 3783 proc_fdlock_spin(p);
91447636
A
3784 if ( ((fp->f_flags & FP_INCHRREAD) != 0) ) {
3785 fileproc_drain(p, fp);
3786 }
3787 proc_fdunlock(p);
3788 }
3789 fg_free(fg);
3790
9bccf70c
A
3791 return (error);
3792}
3793
1c79356b 3794/*
2d21ac55
A
3795 * closef_locked
3796 *
3797 * Description: Internal form of closef; called with proc_fdlock held
3798 *
3799 * Parameters: fp Pointer to fileproc for fd
3800 * fg Pointer to fileglob for fd
3801 * p Pointer to proc structure
3802 *
3803 * Returns: 0 Success
3804 * closef_finish:??? Anything returnable by a per-fileops
3805 * close function
3806 *
3807 * Note: Decrements reference count on file structure; if this was the
3808 * last reference, then closef_finish() is called
3809 *
3810 * p and fp are allowed to be NULL when closing a file that was
3811 * being passed in a message (but only if we are called when this
3812 * is NOT the last reference).
1c79356b
A
3813 */
3814int
2d21ac55 3815closef_locked(struct fileproc *fp, struct fileglob *fg, proc_t p)
1c79356b
A
3816{
3817 struct vnode *vp;
3818 struct flock lf;
91447636 3819 struct vfs_context context;
1c79356b
A
3820 int error;
3821
91447636 3822 if (fg == NULL) {
1c79356b 3823 return (0);
91447636 3824 }
2d21ac55
A
3825
3826 /* Set up context with cred stashed in fg */
3827 if (p == current_proc())
3828 context.vc_thread = current_thread();
3829 else
3830 context.vc_thread = NULL;
3831 context.vc_ucred = fg->fg_cred;
3832
1c79356b
A
3833 /*
3834 * POSIX record locking dictates that any close releases ALL
3835 * locks owned by this process. This is handled by setting
3836 * a flag in the unlock to free ONLY locks obeying POSIX
3837 * semantics, and not to free BSD-style file locks.
3838 * If the descriptor was in a message, POSIX-style locks
3839 * aren't passed with the descriptor.
3840 */
b36670ce 3841 if (p && (p->p_ladvflag & P_LADVLOCK) && fg->fg_type == DTYPE_VNODE) {
91447636
A
3842 proc_fdunlock(p);
3843
1c79356b
A
3844 lf.l_whence = SEEK_SET;
3845 lf.l_start = 0;
3846 lf.l_len = 0;
3847 lf.l_type = F_UNLCK;
91447636
A
3848 vp = (struct vnode *)fg->fg_data;
3849
3850 if ( (error = vnode_getwithref(vp)) == 0 ) {
91447636 3851 (void) VNOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX, &context);
91447636
A
3852 (void)vnode_put(vp);
3853 }
3854 proc_fdlock(p);
1c79356b 3855 }
2d21ac55 3856 lck_mtx_lock_spin(&fg->fg_lock);
91447636
A
3857 fg->fg_count--;
3858
3859 if (fg->fg_count > 0) {
3860 lck_mtx_unlock(&fg->fg_lock);
1c79356b 3861 return (0);
91447636 3862 }
2d21ac55 3863#if DIAGNOSTIC
91447636 3864 if (fg->fg_count != 0)
2d21ac55
A
3865 panic("fg %p: being freed with bad fg_count (%d)", fg, fg->fg_count);
3866#endif
91447636
A
3867
3868 if (fp && (fp->f_flags & FP_WRITTEN))
3869 fg->fg_flag |= FWASWRITTEN;
3870
3871 fg->fg_lflags |= FG_TERM;
3872 lck_mtx_unlock(&fg->fg_lock);
3873
3874 proc_fdunlock(p);
2d21ac55 3875 error = closef_finish(fp, fg, p, &context);
91447636
A
3876 proc_fdlock(p);
3877
3878 return(error);
3879}
3880
3881
2d21ac55 3882/* sleep address to permit wakeup of select by fileproc_drain() */
91447636 3883extern int selwait;
2d21ac55
A
3884
3885
3886/*
3887 * fileproc_drain
3888 *
3889 * Description: Drain out pending I/O operations
3890 *
3891 * Parameters: p Process closing this file
3892 * fp fileproc struct for the open
3893 * instance on the file
3894 *
3895 * Returns: void
3896 *
3897 * Locks: Assumes the caller holds the proc_fdlock
3898 *
3899 * Notes: For character devices, this occurs on the last close of the
3900 * device; for all other file descriptos, this occurs on each
3901 * close to prevent fd's from being closed out from under
3902 * operations currently in progress and blocked
3903 *
3904 * See Also: file_vnode(), file_socket(), file_drop(), and the cautions
3905 * regarding their use and interaction with this function.
3906 */
91447636 3907void
2d21ac55 3908fileproc_drain(proc_t p, struct fileproc * fp)
91447636 3909{
2d21ac55
A
3910 struct vfs_context context;
3911
3912 context.vc_thread = proc_thread(p); /* XXX */
3913 context.vc_ucred = fp->f_fglob->fg_cred;
3914
91447636
A
3915 fp->f_iocount-- ; /* (the one the close holds) */
3916
3917 while (fp->f_iocount) {
2d21ac55
A
3918
3919 lck_mtx_convert_spin(&p->p_fdmlock);
3920
cf7d32b8
A
3921 if (fp->f_fglob->fg_ops->fo_drain) {
3922 (*fp->f_fglob->fg_ops->fo_drain)(fp, &context);
3923 }
91447636
A
3924 if (((fp->f_flags & FP_INSELECT)== FP_INSELECT)) {
3925 wait_queue_wakeup_all((wait_queue_t)fp->f_waddr, &selwait, THREAD_INTERRUPTED);
cf7d32b8 3926 }
91447636
A
3927 p->p_fpdrainwait = 1;
3928
2d21ac55 3929 msleep(&p->p_fpdrainwait, &p->p_fdmlock, PRIBIO, "fpdrain", NULL);
91447636 3930
91447636
A
3931 }
3932}
3933
2d21ac55
A
3934
3935/*
3936 * fp_free
3937 *
3938 * Description: Release the fd and free the fileproc associated with the fd
3939 * in the per process open file table of the specified process;
3940 * these values must correspond.
3941 *
3942 * Parameters: p Process containing fd
3943 * fd fd to be released
3944 * fp fileproc to be freed
3945 *
3946 * Returns: 0 Success
3947 *
3948 * Notes: XXX function should be void - no one interprets the returns
3949 * XXX code
3950 */
91447636 3951int
2d21ac55 3952fp_free(proc_t p, int fd, struct fileproc * fp)
91447636 3953{
2d21ac55 3954 proc_fdlock_spin(p);
91447636
A
3955 fdrelse(p, fd);
3956 proc_fdunlock(p);
3957
3958 fg_free(fp->f_fglob);
2d21ac55
A
3959 FREE_ZONE(fp, sizeof(*fp), M_FILEPROC);
3960 return(0);
1c79356b
A
3961}
3962
91447636 3963
1c79356b 3964/*
2d21ac55
A
3965 * flock
3966 *
3967 * Description: Apply an advisory lock on a file descriptor.
3968 *
3969 * Parameters: p Process making request
3970 * uap->fd fd on which the lock is to be
3971 * attempted
3972 * uap->how (Un)Lock bits, including type
3973 * retval Pointer to the call return area
3974 *
3975 * Returns: 0 Success
3976 * fp_getfvp:EBADF Bad file descriptor
3977 * fp_getfvp:ENOTSUP fd does not refer to a vnode
3978 * vnode_getwithref:???
3979 * VNOP_ADVLOCK:???
1c79356b 3980 *
2d21ac55
A
3981 * Implicit returns:
3982 * *retval (modified) Size of dtable
3983 *
3984 * Notes: Just attempt to get a record lock of the requested type on
3985 * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
1c79356b 3986 */
1c79356b 3987int
2d21ac55 3988flock(proc_t p, struct flock_args *uap, __unused register_t *retval)
1c79356b
A
3989{
3990 int fd = uap->fd;
3991 int how = uap->how;
91447636 3992 struct fileproc *fp;
1c79356b
A
3993 struct vnode *vp;
3994 struct flock lf;
2d21ac55 3995 vfs_context_t ctx = vfs_context_current();
91447636 3996 int error=0;
1c79356b 3997
55e303ae 3998 AUDIT_ARG(fd, uap->fd);
91447636
A
3999 if ( (error = fp_getfvp(p, fd, &fp, &vp)) ) {
4000 return(error);
4001 }
4002 if ( (error = vnode_getwithref(vp)) ) {
4003 goto out1;
4004 }
55e303ae 4005 AUDIT_ARG(vnpath, vp, ARG_VNODE1);
91447636 4006
1c79356b
A
4007 lf.l_whence = SEEK_SET;
4008 lf.l_start = 0;
4009 lf.l_len = 0;
4010 if (how & LOCK_UN) {
4011 lf.l_type = F_UNLCK;
4012 fp->f_flag &= ~FHASLOCK;
2d21ac55 4013 error = VNOP_ADVLOCK(vp, (caddr_t)fp->f_fglob, F_UNLCK, &lf, F_FLOCK, ctx);
91447636 4014 goto out;
1c79356b
A
4015 }
4016 if (how & LOCK_EX)
4017 lf.l_type = F_WRLCK;
4018 else if (how & LOCK_SH)
4019 lf.l_type = F_RDLCK;
91447636
A
4020 else {
4021 error = EBADF;
4022 goto out;
4023 }
2d21ac55
A
4024#if CONFIG_MACF
4025 error = mac_file_check_lock(proc_ucred(p), fp->f_fglob, F_SETLK, &lf);
4026 if (error)
4027 goto out;
4028#endif
1c79356b 4029 fp->f_flag |= FHASLOCK;
91447636 4030 if (how & LOCK_NB) {
2d21ac55 4031 error = VNOP_ADVLOCK(vp, (caddr_t)fp->f_fglob, F_SETLK, &lf, F_FLOCK, ctx);
91447636
A
4032 goto out;
4033 }
2d21ac55 4034 error = VNOP_ADVLOCK(vp, (caddr_t)fp->f_fglob, F_SETLK, &lf, F_FLOCK|F_WAIT, ctx);
91447636
A
4035out:
4036 (void)vnode_put(vp);
4037out1:
4038 fp_drop(p, fd, fp, 0);
4039 return(error);
4040
1c79356b
A
4041}
4042
4043/*
2d21ac55 4044 * dupfdopen
1c79356b 4045 *
2d21ac55
A
4046 * Description: Duplicate the specified descriptor to a free descriptor;
4047 * this is the second half of fdopen(), above.
4048 *
4049 * Parameters: fdp filedesc pointer to fill in
4050 * indx fd to dup to
4051 * dfd fd to dup from
4052 * mode mode to set on new fd
4053 * error command code
4054 *
4055 * Returns: 0 Success
4056 * EBADF Source fd is bad
4057 * EACCES Requested mode not allowed
4058 * !0 'error', if not ENODEV or
4059 * ENXIO
4060 *
4061 * Notes: XXX This is not thread safe; see fdopen() above
1c79356b
A
4062 */
4063int
2d21ac55 4064dupfdopen(struct filedesc *fdp, int indx, int dfd, int mode, int error)
1c79356b 4065{
91447636
A
4066 struct fileproc *wfp;
4067 struct fileproc *fp;
2d21ac55
A
4068#if CONFIG_MACF
4069 int myerror;
4070#endif
4071 proc_t p = current_proc();
1c79356b
A
4072
4073 /*
4074 * If the to-be-dup'd fd number is greater than the allowed number
4075 * of file descriptors, or the fd to be dup'd has already been
4076 * closed, reject. Note, check for new == old is necessary as
4077 * falloc could allocate an already closed to-be-dup'd descriptor
4078 * as the new descriptor.
4079 */
91447636
A
4080 proc_fdlock(p);
4081
1c79356b 4082 fp = fdp->fd_ofiles[indx];
91447636 4083 if (dfd < 0 || dfd >= fdp->fd_nfiles ||
1c79356b 4084 (wfp = fdp->fd_ofiles[dfd]) == NULL || wfp == fp ||
91447636 4085 (fdp->fd_ofileflags[dfd] & UF_RESERVED)) {
1c79356b 4086
91447636
A
4087 proc_fdunlock(p);
4088 return (EBADF);
4089 }
2d21ac55
A
4090#if CONFIG_MACF
4091 myerror = mac_file_check_dup(proc_ucred(p), wfp->f_fglob, dfd);
4092 if (myerror) {
4093 proc_fdunlock(p);
4094 return (myerror);
4095 }
4096#endif
1c79356b
A
4097 /*
4098 * There are two cases of interest here.
4099 *
4100 * For ENODEV simply dup (dfd) to file descriptor
4101 * (indx) and return.
4102 *
4103 * For ENXIO steal away the file structure from (dfd) and
4104 * store it in (indx). (dfd) is effectively closed by
4105 * this operation.
4106 *
4107 * Any other error code is just returned.
4108 */
4109 switch (error) {
4110 case ENODEV:
4111 /*
4112 * Check that the mode the file is being opened for is a
4113 * subset of the mode of the existing descriptor.
4114 */
91447636
A
4115 if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag) {
4116 proc_fdunlock(p);
1c79356b 4117 return (EACCES);
91447636 4118 }
1c79356b 4119 if (indx > fdp->fd_lastfile)
91447636
A
4120 fdp->fd_lastfile = indx;
4121 (void)fg_ref(wfp);
4122
4123 if (fp->f_fglob)
4124 fg_free(fp->f_fglob);
4125 fp->f_fglob = wfp->f_fglob;
4126
1c79356b 4127 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
91447636
A
4128
4129 proc_fdunlock(p);
1c79356b
A
4130 return (0);
4131
1c79356b 4132 default:
91447636 4133 proc_fdunlock(p);
1c79356b
A
4134 return (error);
4135 }
4136 /* NOTREACHED */
4137}
4138
2d21ac55
A
4139
4140/*
4141 * fg_ref
4142 *
4143 * Description: Add a reference to a fileglob by fileproc
4144 *
4145 * Parameters: fp fileproc containing fileglob
4146 * pointer
4147 *
4148 * Returns: void
4149 *
4150 * Notes: XXX Should use OSAddAtomic?
4151 */
91447636
A
4152void
4153fg_ref(struct fileproc * fp)
1c79356b 4154{
91447636
A
4155 struct fileglob *fg;
4156
4157 fg = fp->f_fglob;
4158
2d21ac55
A
4159 lck_mtx_lock_spin(&fg->fg_lock);
4160
4161#if DIAGNOSTIC
4162 if ((fp->f_flags & ~((unsigned int)FP_VALID_FLAGS)) != 0)
4163 panic("fg_ref: invalid bits on fp%x\n", (unsigned int)fp);
4164
4165 if (fg->fg_count == 0)
4166 panic("fg_ref: adding fgcount to zeroed fg :fp %x, fg%x\n ", (unsigned int)fp, (unsigned int)fg);
4167#endif
91447636
A
4168 fg->fg_count++;
4169 lck_mtx_unlock(&fg->fg_lock);
1c79356b
A
4170}
4171
2d21ac55
A
4172
4173/*
4174 * fg_drop
4175 *
4176 * Description: Remove a reference to a fileglob by fileproc
4177 *
4178 * Parameters: fp fileproc containing fileglob
4179 * pointer
4180 *
4181 * Returns: void
4182 *
4183 * Notes: XXX Should use OSAddAtomic?
4184 */
91447636
A
4185void
4186fg_drop(struct fileproc * fp)
1c79356b 4187{
91447636
A
4188 struct fileglob *fg;
4189
4190 fg = fp->f_fglob;
2d21ac55 4191 lck_mtx_lock_spin(&fg->fg_lock);
91447636
A
4192 fg->fg_count--;
4193 lck_mtx_unlock(&fg->fg_lock);
1c79356b
A
4194}
4195
9bccf70c 4196
2d21ac55
A
4197/*
4198 * fg_insertuipc
4199 *
4200 * Description: Insert fileglob onto message queue
4201 *
4202 * Parameters: fg Fileglob pointer to insert
4203 *
4204 * Returns: void
4205 *
4206 * Locks: Takes and drops fg_lock, potentially many times
4207 */
91447636
A
4208void
4209fg_insertuipc(struct fileglob * fg)
9bccf70c 4210{
2d21ac55 4211 int insertque = 0;
9bccf70c 4212
2d21ac55 4213 lck_mtx_lock_spin(&fg->fg_lock);
91447636
A
4214
4215 while (fg->fg_lflags & FG_RMMSGQ) {
2d21ac55
A
4216 lck_mtx_convert_spin(&fg->fg_lock);
4217
91447636 4218 fg->fg_lflags |= FG_WRMMSGQ;
2d21ac55 4219 msleep(&fg->fg_lflags, &fg->fg_lock, 0, "fg_insertuipc", NULL);
91447636 4220 }
9bccf70c 4221
91447636
A
4222 fg->fg_count++;
4223 fg->fg_msgcount++;
4224 if (fg->fg_msgcount == 1) {
4225 fg->fg_lflags |= FG_INSMSGQ;
4226 insertque=1;
9bccf70c 4227 }
91447636
A
4228 lck_mtx_unlock(&fg->fg_lock);
4229
4230 if (insertque) {
2d21ac55 4231 lck_mtx_lock_spin(uipc_lock);
6601e61a 4232 unp_gc_wait();
91447636
A
4233 LIST_INSERT_HEAD(&fmsghead, fg, f_msglist);
4234 lck_mtx_unlock(uipc_lock);
4235 lck_mtx_lock(&fg->fg_lock);
4236 fg->fg_lflags &= ~FG_INSMSGQ;
4237 if (fg->fg_lflags & FG_WINSMSGQ) {
4238 fg->fg_lflags &= ~FG_WINSMSGQ;
4239 wakeup(&fg->fg_lflags);
4240 }
4241 lck_mtx_unlock(&fg->fg_lock);
4242 }
4243
4244}
9bccf70c 4245
2d21ac55
A
4246
4247/*
4248 * fg_removeuipc
4249 *
4250 * Description: Remove fileglob from message queue
4251 *
4252 * Parameters: fg Fileglob pointer to remove
4253 *
4254 * Returns: void
4255 *
4256 * Locks: Takes and drops fg_lock, potentially many times
4257 */
91447636
A
4258void
4259fg_removeuipc(struct fileglob * fg)
4260{
2d21ac55 4261 int removeque = 0;
91447636 4262
2d21ac55 4263 lck_mtx_lock_spin(&fg->fg_lock);
91447636 4264 while (fg->fg_lflags & FG_INSMSGQ) {
2d21ac55
A
4265 lck_mtx_convert_spin(&fg->fg_lock);
4266
91447636 4267 fg->fg_lflags |= FG_WINSMSGQ;
2d21ac55 4268 msleep(&fg->fg_lflags, &fg->fg_lock, 0, "fg_removeuipc", NULL);
91447636
A
4269 }
4270 fg->fg_msgcount--;
4271 if (fg->fg_msgcount == 0) {
4272 fg->fg_lflags |= FG_RMMSGQ;
4273 removeque=1;
9bccf70c 4274 }
91447636
A
4275 lck_mtx_unlock(&fg->fg_lock);
4276
4277 if (removeque) {
2d21ac55 4278 lck_mtx_lock_spin(uipc_lock);
6601e61a 4279 unp_gc_wait();
91447636
A
4280 LIST_REMOVE(fg, f_msglist);
4281 lck_mtx_unlock(uipc_lock);
4282 lck_mtx_lock(&fg->fg_lock);
4283 fg->fg_lflags &= ~FG_RMMSGQ;
4284 if (fg->fg_lflags & FG_WRMMSGQ) {
4285 fg->fg_lflags &= ~FG_WRMMSGQ;
4286 wakeup(&fg->fg_lflags);
4287 }
4288 lck_mtx_unlock(&fg->fg_lock);
4289 }
4290}
4291
4292
2d21ac55
A
4293/*
4294 * fo_read
4295 *
4296 * Description: Generic fileops read indirected through the fileops pointer
4297 * in the fileproc structure
4298 *
4299 * Parameters: fp fileproc structure pointer
4300 * uio user I/O structure pointer
4301 * flags FOF_ flags
4302 * ctx VFS context for operation
4303 *
4304 * Returns: 0 Success
4305 * !0 Errno from read
4306 */
91447636 4307int
2d21ac55 4308fo_read(struct fileproc *fp, struct uio *uio, int flags, vfs_context_t ctx)
91447636 4309{
2d21ac55 4310 return ((*fp->f_ops->fo_read)(fp, uio, flags, ctx));
91447636
A
4311}
4312
2d21ac55
A
4313
4314/*
4315 * fo_write
4316 *
4317 * Description: Generic fileops write indirected through the fileops pointer
4318 * in the fileproc structure
4319 *
4320 * Parameters: fp fileproc structure pointer
4321 * uio user I/O structure pointer
4322 * flags FOF_ flags
4323 * ctx VFS context for operation
4324 *
4325 * Returns: 0 Success
4326 * !0 Errno from write
4327 */
91447636 4328int
2d21ac55 4329fo_write(struct fileproc *fp, struct uio *uio, int flags, vfs_context_t ctx)
91447636 4330{
2d21ac55 4331 return((*fp->f_ops->fo_write)(fp, uio, flags, ctx));
91447636
A
4332}
4333
2d21ac55
A
4334
4335/*
4336 * fo_ioctl
4337 *
4338 * Description: Generic fileops ioctl indirected through the fileops pointer
4339 * in the fileproc structure
4340 *
4341 * Parameters: fp fileproc structure pointer
4342 * com ioctl command
4343 * data pointer to internalized copy
4344 * of user space ioctl command
4345 * parameter data in kernel space
4346 * ctx VFS context for operation
4347 *
4348 * Returns: 0 Success
4349 * !0 Errno from ioctl
4350 *
4351 * Locks: The caller is assumed to have held the proc_fdlock; this
4352 * function releases and reacquires this lock. If the caller
4353 * accesses data protected by this lock prior to calling this
4354 * function, it will need to revalidate/reacquire any cached
4355 * protected data obtained prior to the call.
4356 */
91447636 4357int
2d21ac55 4358fo_ioctl(struct fileproc *fp, u_long com, caddr_t data, vfs_context_t ctx)
91447636 4359{
2d21ac55 4360 int error;
91447636 4361
2d21ac55
A
4362 proc_fdunlock(vfs_context_proc(ctx));
4363 error = (*fp->f_ops->fo_ioctl)(fp, com, data, ctx);
4364 proc_fdlock(vfs_context_proc(ctx));
91447636
A
4365 return(error);
4366}
4367
2d21ac55
A
4368
4369/*
4370 * fo_select
4371 *
4372 * Description: Generic fileops select indirected through the fileops pointer
4373 * in the fileproc structure
4374 *
4375 * Parameters: fp fileproc structure pointer
4376 * which select which
4377 * wql pointer to wait queue list
4378 * ctx VFS context for operation
4379 *
4380 * Returns: 0 Success
4381 * !0 Errno from select
4382 */
91447636 4383int
2d21ac55 4384fo_select(struct fileproc *fp, int which, void *wql, vfs_context_t ctx)
91447636 4385{
2d21ac55 4386 return((*fp->f_ops->fo_select)(fp, which, wql, ctx));
91447636
A
4387}
4388
2d21ac55
A
4389
4390/*
4391 * fo_close
4392 *
4393 * Description: Generic fileops close indirected through the fileops pointer
4394 * in the fileproc structure
4395 *
4396 * Parameters: fp fileproc structure pointer for
4397 * file to close
4398 * ctx VFS context for operation
4399 *
4400 * Returns: 0 Success
4401 * !0 Errno from close
4402 */
91447636 4403int
2d21ac55 4404fo_close(struct fileglob *fg, vfs_context_t ctx)
91447636 4405{
2d21ac55 4406 return((*fg->fg_ops->fo_close)(fg, ctx));
9bccf70c
A
4407}
4408
2d21ac55
A
4409
4410/*
4411 * fo_kqfilter
4412 *
4413 * Description: Generic fileops kqueue filter indirected through the fileops
4414 * pointer in the fileproc structure
4415 *
4416 * Parameters: fp fileproc structure pointer
4417 * kn pointer to knote to filter on
4418 * ctx VFS context for operation
4419 *
4420 * Returns: 0 Success
4421 * !0 Errno from kqueue filter
4422 */
1c79356b 4423int
2d21ac55 4424fo_kqfilter(struct fileproc *fp, struct knote *kn, vfs_context_t ctx)
1c79356b 4425{
2d21ac55 4426 return ((*fp->f_ops->fo_kqfilter)(fp, kn, ctx));
1c79356b 4427}