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