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