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