1 /* $OpenBSD: kern_descrip.c,v 1.207 2022/12/05 23:18:37 deraadt Exp $ */ 2 /* $NetBSD: kern_descrip.c,v 1.42 1996/03/30 22:24:38 christos Exp $ */ 3 4 /* 5 * Copyright (c) 1982, 1986, 1989, 1991, 1993 6 * The Regents of the University of California. All rights reserved. 7 * (c) UNIX System Laboratories, Inc. 8 * All or some portions of this file are derived from material licensed 9 * to the University of California by American Telephone and Telegraph 10 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 11 * the permission of UNIX System Laboratories, Inc. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * @(#)kern_descrip.c 8.6 (Berkeley) 4/19/94 38 */ 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/filedesc.h> 43 #include <sys/vnode.h> 44 #include <sys/proc.h> 45 #include <sys/file.h> 46 #include <sys/socket.h> 47 #include <sys/stat.h> 48 #include <sys/ioctl.h> 49 #include <sys/fcntl.h> 50 #include <sys/lock.h> 51 #include <sys/malloc.h> 52 #include <sys/ucred.h> 53 #include <sys/unistd.h> 54 #include <sys/resourcevar.h> 55 #include <sys/mount.h> 56 #include <sys/syscallargs.h> 57 #include <sys/event.h> 58 #include <sys/pool.h> 59 #include <sys/ktrace.h> 60 #include <sys/pledge.h> 61 62 /* 63 * Descriptor management. 64 * 65 * We need to block interrupts as long as `fhdlk' is being taken 66 * with and without the KERNEL_LOCK(). 67 */ 68 struct mutex fhdlk = MUTEX_INITIALIZER(IPL_MPFLOOR); 69 struct filelist filehead; /* head of list of open files */ 70 int numfiles; /* actual number of open files */ 71 72 static __inline void fd_used(struct filedesc *, int); 73 static __inline void fd_unused(struct filedesc *, int); 74 static __inline int find_next_zero(u_int *, int, u_int); 75 static __inline int fd_inuse(struct filedesc *, int); 76 int finishdup(struct proc *, struct file *, int, int, register_t *, int); 77 int find_last_set(struct filedesc *, int); 78 int dodup3(struct proc *, int, int, int, register_t *); 79 80 #define DUPF_CLOEXEC 0x01 81 #define DUPF_DUP2 0x02 82 83 struct pool file_pool; 84 struct pool fdesc_pool; 85 86 void 87 filedesc_init(void) 88 { 89 pool_init(&file_pool, sizeof(struct file), 0, IPL_MPFLOOR, 90 PR_WAITOK, "filepl", NULL); 91 pool_init(&fdesc_pool, sizeof(struct filedesc0), 0, IPL_NONE, 92 PR_WAITOK, "fdescpl", NULL); 93 LIST_INIT(&filehead); 94 } 95 96 static __inline int 97 find_next_zero (u_int *bitmap, int want, u_int bits) 98 { 99 int i, off, maxoff; 100 u_int sub; 101 102 if (want > bits) 103 return -1; 104 105 off = want >> NDENTRYSHIFT; 106 i = want & NDENTRYMASK; 107 if (i) { 108 sub = bitmap[off] | ((u_int)~0 >> (NDENTRIES - i)); 109 if (sub != ~0) 110 goto found; 111 off++; 112 } 113 114 maxoff = NDLOSLOTS(bits); 115 while (off < maxoff) { 116 if ((sub = bitmap[off]) != ~0) 117 goto found; 118 off++; 119 } 120 121 return -1; 122 123 found: 124 return (off << NDENTRYSHIFT) + ffs(~sub) - 1; 125 } 126 127 int 128 find_last_set(struct filedesc *fd, int last) 129 { 130 int off, i; 131 u_int *bitmap = fd->fd_lomap; 132 133 off = (last - 1) >> NDENTRYSHIFT; 134 135 while (off >= 0 && !bitmap[off]) 136 off--; 137 if (off < 0) 138 return 0; 139 140 i = ((off + 1) << NDENTRYSHIFT) - 1; 141 if (i >= last) 142 i = last - 1; 143 144 while (i > 0 && !fd_inuse(fd, i)) 145 i--; 146 return i; 147 } 148 149 static __inline int 150 fd_inuse(struct filedesc *fdp, int fd) 151 { 152 u_int off = fd >> NDENTRYSHIFT; 153 154 if (fdp->fd_lomap[off] & (1U << (fd & NDENTRYMASK))) 155 return 1; 156 157 return 0; 158 } 159 160 static __inline void 161 fd_used(struct filedesc *fdp, int fd) 162 { 163 u_int off = fd >> NDENTRYSHIFT; 164 165 fdp->fd_lomap[off] |= 1U << (fd & NDENTRYMASK); 166 if (fdp->fd_lomap[off] == ~0) 167 fdp->fd_himap[off >> NDENTRYSHIFT] |= 1U << (off & NDENTRYMASK); 168 169 if (fd > fdp->fd_lastfile) 170 fdp->fd_lastfile = fd; 171 fdp->fd_openfd++; 172 } 173 174 static __inline void 175 fd_unused(struct filedesc *fdp, int fd) 176 { 177 u_int off = fd >> NDENTRYSHIFT; 178 179 if (fd < fdp->fd_freefile) 180 fdp->fd_freefile = fd; 181 182 if (fdp->fd_lomap[off] == ~0) 183 fdp->fd_himap[off >> NDENTRYSHIFT] &= ~(1U << (off & NDENTRYMASK)); 184 fdp->fd_lomap[off] &= ~(1U << (fd & NDENTRYMASK)); 185 186 #ifdef DIAGNOSTIC 187 if (fd > fdp->fd_lastfile) 188 panic("fd_unused: fd_lastfile inconsistent"); 189 #endif 190 if (fd == fdp->fd_lastfile) 191 fdp->fd_lastfile = find_last_set(fdp, fd); 192 fdp->fd_openfd--; 193 } 194 195 struct file * 196 fd_iterfile(struct file *fp, struct proc *p) 197 { 198 struct file *nfp; 199 unsigned int count; 200 201 mtx_enter(&fhdlk); 202 if (fp == NULL) 203 nfp = LIST_FIRST(&filehead); 204 else 205 nfp = LIST_NEXT(fp, f_list); 206 207 /* don't refcount when f_count == 0 to avoid race in fdrop() */ 208 while (nfp != NULL) { 209 count = nfp->f_count; 210 if (count == 0) { 211 nfp = LIST_NEXT(nfp, f_list); 212 continue; 213 } 214 if (atomic_cas_uint(&nfp->f_count, count, count + 1) == count) 215 break; 216 } 217 mtx_leave(&fhdlk); 218 219 if (fp != NULL) 220 FRELE(fp, p); 221 222 return nfp; 223 } 224 225 struct file * 226 fd_getfile(struct filedesc *fdp, int fd) 227 { 228 struct file *fp; 229 230 vfs_stall_barrier(); 231 232 if ((u_int)fd >= fdp->fd_nfiles) 233 return (NULL); 234 235 mtx_enter(&fdp->fd_fplock); 236 fp = fdp->fd_ofiles[fd]; 237 if (fp != NULL) 238 atomic_inc_int(&fp->f_count); 239 mtx_leave(&fdp->fd_fplock); 240 241 return (fp); 242 } 243 244 struct file * 245 fd_getfile_mode(struct filedesc *fdp, int fd, int mode) 246 { 247 struct file *fp; 248 249 KASSERT(mode != 0); 250 251 fp = fd_getfile(fdp, fd); 252 if (fp == NULL) 253 return (NULL); 254 255 if ((fp->f_flag & mode) == 0) { 256 FRELE(fp, curproc); 257 return (NULL); 258 } 259 260 return (fp); 261 } 262 263 int 264 fd_checkclosed(struct filedesc *fdp, int fd, struct file *fp) 265 { 266 int closed; 267 268 mtx_enter(&fdp->fd_fplock); 269 KASSERT(fd < fdp->fd_nfiles); 270 closed = (fdp->fd_ofiles[fd] != fp); 271 mtx_leave(&fdp->fd_fplock); 272 return (closed); 273 } 274 275 /* 276 * System calls on descriptors. 277 */ 278 279 /* 280 * Duplicate a file descriptor. 281 */ 282 int 283 sys_dup(struct proc *p, void *v, register_t *retval) 284 { 285 struct sys_dup_args /* { 286 syscallarg(int) fd; 287 } */ *uap = v; 288 struct filedesc *fdp = p->p_fd; 289 int old = SCARG(uap, fd); 290 struct file *fp; 291 int new; 292 int error; 293 294 restart: 295 if ((fp = fd_getfile(fdp, old)) == NULL) 296 return (EBADF); 297 fdplock(fdp); 298 if ((error = fdalloc(p, 0, &new)) != 0) { 299 if (error == ENOSPC) { 300 fdexpand(p); 301 fdpunlock(fdp); 302 FRELE(fp, p); 303 goto restart; 304 } 305 fdpunlock(fdp); 306 FRELE(fp, p); 307 return (error); 308 } 309 /* No need for FRELE(), finishdup() uses current ref. */ 310 return (finishdup(p, fp, old, new, retval, 0)); 311 } 312 313 /* 314 * Duplicate a file descriptor to a particular value. 315 */ 316 int 317 sys_dup2(struct proc *p, void *v, register_t *retval) 318 { 319 struct sys_dup2_args /* { 320 syscallarg(int) from; 321 syscallarg(int) to; 322 } */ *uap = v; 323 324 return (dodup3(p, SCARG(uap, from), SCARG(uap, to), 0, retval)); 325 } 326 327 int 328 sys_dup3(struct proc *p, void *v, register_t *retval) 329 { 330 struct sys_dup3_args /* { 331 syscallarg(int) from; 332 syscallarg(int) to; 333 syscallarg(int) flags; 334 } */ *uap = v; 335 336 if (SCARG(uap, from) == SCARG(uap, to)) 337 return (EINVAL); 338 if (SCARG(uap, flags) & ~O_CLOEXEC) 339 return (EINVAL); 340 return (dodup3(p, SCARG(uap, from), SCARG(uap, to), 341 SCARG(uap, flags), retval)); 342 } 343 344 int 345 dodup3(struct proc *p, int old, int new, int flags, register_t *retval) 346 { 347 struct filedesc *fdp = p->p_fd; 348 struct file *fp; 349 int dupflags, error, i; 350 351 restart: 352 if ((fp = fd_getfile(fdp, old)) == NULL) 353 return (EBADF); 354 if (old == new) { 355 /* 356 * NOTE! This doesn't clear the close-on-exec flag. This might 357 * or might not be the intended behavior from the start, but 358 * this is what everyone else does. 359 */ 360 *retval = new; 361 FRELE(fp, p); 362 return (0); 363 } 364 if ((u_int)new >= lim_cur(RLIMIT_NOFILE) || 365 (u_int)new >= maxfiles) { 366 FRELE(fp, p); 367 return (EBADF); 368 } 369 fdplock(fdp); 370 if (new >= fdp->fd_nfiles) { 371 if ((error = fdalloc(p, new, &i)) != 0) { 372 if (error == ENOSPC) { 373 fdexpand(p); 374 fdpunlock(fdp); 375 FRELE(fp, p); 376 goto restart; 377 } 378 fdpunlock(fdp); 379 FRELE(fp, p); 380 return (error); 381 } 382 if (new != i) 383 panic("dup2: fdalloc"); 384 fd_unused(fdp, new); 385 } 386 387 dupflags = DUPF_DUP2; 388 if (flags & O_CLOEXEC) 389 dupflags |= DUPF_CLOEXEC; 390 391 /* No need for FRELE(), finishdup() uses current ref. */ 392 return (finishdup(p, fp, old, new, retval, dupflags)); 393 } 394 395 /* 396 * The file control system call. 397 */ 398 int 399 sys_fcntl(struct proc *p, void *v, register_t *retval) 400 { 401 struct sys_fcntl_args /* { 402 syscallarg(int) fd; 403 syscallarg(int) cmd; 404 syscallarg(void *) arg; 405 } */ *uap = v; 406 int fd = SCARG(uap, fd); 407 struct filedesc *fdp = p->p_fd; 408 struct file *fp; 409 struct vnode *vp; 410 int i, prev, tmp, newmin, flg = F_POSIX; 411 struct flock fl; 412 int error = 0; 413 414 error = pledge_fcntl(p, SCARG(uap, cmd)); 415 if (error) 416 return (error); 417 418 restart: 419 if ((fp = fd_getfile(fdp, fd)) == NULL) 420 return (EBADF); 421 switch (SCARG(uap, cmd)) { 422 423 case F_DUPFD: 424 case F_DUPFD_CLOEXEC: 425 newmin = (long)SCARG(uap, arg); 426 if ((u_int)newmin >= lim_cur(RLIMIT_NOFILE) || 427 (u_int)newmin >= maxfiles) { 428 error = EINVAL; 429 break; 430 } 431 fdplock(fdp); 432 if ((error = fdalloc(p, newmin, &i)) != 0) { 433 if (error == ENOSPC) { 434 fdexpand(p); 435 fdpunlock(fdp); 436 FRELE(fp, p); 437 goto restart; 438 } 439 fdpunlock(fdp); 440 FRELE(fp, p); 441 } else { 442 int dupflags = 0; 443 444 if (SCARG(uap, cmd) == F_DUPFD_CLOEXEC) 445 dupflags |= DUPF_CLOEXEC; 446 447 /* No need for FRELE(), finishdup() uses current ref. */ 448 error = finishdup(p, fp, fd, i, retval, dupflags); 449 } 450 return (error); 451 452 case F_GETFD: 453 fdplock(fdp); 454 *retval = fdp->fd_ofileflags[fd] & UF_EXCLOSE ? 1 : 0; 455 fdpunlock(fdp); 456 break; 457 458 case F_SETFD: 459 fdplock(fdp); 460 if ((long)SCARG(uap, arg) & 1) 461 fdp->fd_ofileflags[fd] |= UF_EXCLOSE; 462 else 463 fdp->fd_ofileflags[fd] &= ~UF_EXCLOSE; 464 fdpunlock(fdp); 465 break; 466 467 case F_GETFL: 468 *retval = OFLAGS(fp->f_flag); 469 break; 470 471 case F_ISATTY: 472 vp = fp->f_data; 473 if (fp->f_type == DTYPE_VNODE && (vp->v_flag & VISTTY)) 474 *retval = 1; 475 else { 476 *retval = 0; 477 error = ENOTTY; 478 } 479 break; 480 481 case F_SETFL: 482 do { 483 tmp = prev = fp->f_flag; 484 tmp &= ~FCNTLFLAGS; 485 tmp |= FFLAGS((long)SCARG(uap, arg)) & FCNTLFLAGS; 486 } while (atomic_cas_uint(&fp->f_flag, prev, tmp) != prev); 487 tmp = fp->f_flag & FNONBLOCK; 488 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p); 489 if (error) 490 break; 491 tmp = fp->f_flag & FASYNC; 492 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p); 493 if (!error) 494 break; 495 atomic_clearbits_int(&fp->f_flag, FNONBLOCK); 496 tmp = 0; 497 (void) (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p); 498 break; 499 500 case F_GETOWN: 501 tmp = 0; 502 error = (*fp->f_ops->fo_ioctl) 503 (fp, FIOGETOWN, (caddr_t)&tmp, p); 504 *retval = tmp; 505 break; 506 507 case F_SETOWN: 508 tmp = (long)SCARG(uap, arg); 509 error = ((*fp->f_ops->fo_ioctl) 510 (fp, FIOSETOWN, (caddr_t)&tmp, p)); 511 break; 512 513 case F_SETLKW: 514 flg |= F_WAIT; 515 /* FALLTHROUGH */ 516 517 case F_SETLK: 518 error = pledge_flock(p); 519 if (error != 0) 520 break; 521 522 if (fp->f_type != DTYPE_VNODE) { 523 error = EINVAL; 524 break; 525 } 526 vp = fp->f_data; 527 /* Copy in the lock structure */ 528 error = copyin((caddr_t)SCARG(uap, arg), (caddr_t)&fl, 529 sizeof (fl)); 530 if (error) 531 break; 532 #ifdef KTRACE 533 if (KTRPOINT(p, KTR_STRUCT)) 534 ktrflock(p, &fl); 535 #endif 536 if (fl.l_whence == SEEK_CUR) { 537 off_t offset = foffset(fp); 538 539 if (fl.l_start == 0 && fl.l_len < 0) { 540 /* lockf(3) compliance hack */ 541 fl.l_len = -fl.l_len; 542 fl.l_start = offset - fl.l_len; 543 } else 544 fl.l_start += offset; 545 } 546 switch (fl.l_type) { 547 548 case F_RDLCK: 549 if ((fp->f_flag & FREAD) == 0) { 550 error = EBADF; 551 goto out; 552 } 553 atomic_setbits_int(&fdp->fd_flags, FD_ADVLOCK); 554 error = VOP_ADVLOCK(vp, fdp, F_SETLK, &fl, flg); 555 break; 556 557 case F_WRLCK: 558 if ((fp->f_flag & FWRITE) == 0) { 559 error = EBADF; 560 goto out; 561 } 562 atomic_setbits_int(&fdp->fd_flags, FD_ADVLOCK); 563 error = VOP_ADVLOCK(vp, fdp, F_SETLK, &fl, flg); 564 break; 565 566 case F_UNLCK: 567 error = VOP_ADVLOCK(vp, fdp, F_UNLCK, &fl, F_POSIX); 568 goto out; 569 570 default: 571 error = EINVAL; 572 goto out; 573 } 574 575 if (fd_checkclosed(fdp, fd, fp)) { 576 /* 577 * We have lost the race with close() or dup2(); 578 * unlock, pretend that we've won the race and that 579 * lock had been removed by close() 580 */ 581 fl.l_whence = SEEK_SET; 582 fl.l_start = 0; 583 fl.l_len = 0; 584 VOP_ADVLOCK(vp, fdp, F_UNLCK, &fl, F_POSIX); 585 fl.l_type = F_UNLCK; 586 } 587 goto out; 588 589 590 case F_GETLK: 591 error = pledge_flock(p); 592 if (error != 0) 593 break; 594 595 if (fp->f_type != DTYPE_VNODE) { 596 error = EINVAL; 597 break; 598 } 599 vp = fp->f_data; 600 /* Copy in the lock structure */ 601 error = copyin((caddr_t)SCARG(uap, arg), (caddr_t)&fl, 602 sizeof (fl)); 603 if (error) 604 break; 605 if (fl.l_whence == SEEK_CUR) { 606 off_t offset = foffset(fp); 607 608 if (fl.l_start == 0 && fl.l_len < 0) { 609 /* lockf(3) compliance hack */ 610 fl.l_len = -fl.l_len; 611 fl.l_start = offset - fl.l_len; 612 } else 613 fl.l_start += offset; 614 } 615 if (fl.l_type != F_RDLCK && 616 fl.l_type != F_WRLCK && 617 fl.l_type != F_UNLCK && 618 fl.l_type != 0) { 619 error = EINVAL; 620 break; 621 } 622 error = VOP_ADVLOCK(vp, fdp, F_GETLK, &fl, F_POSIX); 623 if (error) 624 break; 625 #ifdef KTRACE 626 if (KTRPOINT(p, KTR_STRUCT)) 627 ktrflock(p, &fl); 628 #endif 629 error = (copyout((caddr_t)&fl, (caddr_t)SCARG(uap, arg), 630 sizeof (fl))); 631 break; 632 633 default: 634 error = EINVAL; 635 break; 636 } 637 out: 638 FRELE(fp, p); 639 return (error); 640 } 641 642 /* 643 * Common code for dup, dup2, and fcntl(F_DUPFD). 644 */ 645 int 646 finishdup(struct proc *p, struct file *fp, int old, int new, 647 register_t *retval, int dupflags) 648 { 649 struct file *oldfp; 650 struct filedesc *fdp = p->p_fd; 651 int error; 652 653 fdpassertlocked(fdp); 654 KASSERT(fp->f_iflags & FIF_INSERTED); 655 656 if (fp->f_count >= FDUP_MAX_COUNT) { 657 error = EDEADLK; 658 goto fail; 659 } 660 661 oldfp = fd_getfile(fdp, new); 662 if ((dupflags & DUPF_DUP2) && oldfp == NULL) { 663 if (fd_inuse(fdp, new)) { 664 error = EBUSY; 665 goto fail; 666 } 667 fd_used(fdp, new); 668 } 669 670 /* 671 * Use `fd_fplock' to synchronize with fd_getfile() so that 672 * the function no longer creates a new reference to the old file. 673 */ 674 mtx_enter(&fdp->fd_fplock); 675 fdp->fd_ofiles[new] = fp; 676 mtx_leave(&fdp->fd_fplock); 677 678 fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] & ~UF_EXCLOSE; 679 if (dupflags & DUPF_CLOEXEC) 680 fdp->fd_ofileflags[new] |= UF_EXCLOSE; 681 *retval = new; 682 683 if (oldfp != NULL) { 684 knote_fdclose(p, new); 685 fdpunlock(fdp); 686 closef(oldfp, p); 687 } else { 688 fdpunlock(fdp); 689 } 690 691 return (0); 692 693 fail: 694 fdpunlock(fdp); 695 FRELE(fp, p); 696 return (error); 697 } 698 699 void 700 fdinsert(struct filedesc *fdp, int fd, int flags, struct file *fp) 701 { 702 struct file *fq; 703 704 fdpassertlocked(fdp); 705 706 mtx_enter(&fhdlk); 707 if ((fp->f_iflags & FIF_INSERTED) == 0) { 708 atomic_setbits_int(&fp->f_iflags, FIF_INSERTED); 709 if ((fq = fdp->fd_ofiles[0]) != NULL) { 710 LIST_INSERT_AFTER(fq, fp, f_list); 711 } else { 712 LIST_INSERT_HEAD(&filehead, fp, f_list); 713 } 714 } 715 mtx_leave(&fhdlk); 716 717 mtx_enter(&fdp->fd_fplock); 718 KASSERT(fdp->fd_ofiles[fd] == NULL); 719 fdp->fd_ofiles[fd] = fp; 720 mtx_leave(&fdp->fd_fplock); 721 722 fdp->fd_ofileflags[fd] |= (flags & UF_EXCLOSE); 723 } 724 725 void 726 fdremove(struct filedesc *fdp, int fd) 727 { 728 fdpassertlocked(fdp); 729 730 /* 731 * Use `fd_fplock' to synchronize with fd_getfile() so that 732 * the function no longer creates a new reference to the file. 733 */ 734 mtx_enter(&fdp->fd_fplock); 735 fdp->fd_ofiles[fd] = NULL; 736 mtx_leave(&fdp->fd_fplock); 737 738 fdp->fd_ofileflags[fd] = 0; 739 740 fd_unused(fdp, fd); 741 } 742 743 int 744 fdrelease(struct proc *p, int fd) 745 { 746 struct filedesc *fdp = p->p_fd; 747 struct file *fp; 748 749 fdpassertlocked(fdp); 750 751 fp = fd_getfile(fdp, fd); 752 if (fp == NULL) { 753 fdpunlock(fdp); 754 return (EBADF); 755 } 756 fdremove(fdp, fd); 757 knote_fdclose(p, fd); 758 fdpunlock(fdp); 759 return (closef(fp, p)); 760 } 761 762 /* 763 * Close a file descriptor. 764 */ 765 int 766 sys_close(struct proc *p, void *v, register_t *retval) 767 { 768 struct sys_close_args /* { 769 syscallarg(int) fd; 770 } */ *uap = v; 771 int fd = SCARG(uap, fd), error; 772 struct filedesc *fdp = p->p_fd; 773 774 fdplock(fdp); 775 /* fdrelease unlocks fdp. */ 776 error = fdrelease(p, fd); 777 778 return (error); 779 } 780 781 /* 782 * Return status information about a file descriptor. 783 */ 784 int 785 sys_fstat(struct proc *p, void *v, register_t *retval) 786 { 787 struct sys_fstat_args /* { 788 syscallarg(int) fd; 789 syscallarg(struct stat *) sb; 790 } */ *uap = v; 791 int fd = SCARG(uap, fd); 792 struct filedesc *fdp = p->p_fd; 793 struct file *fp; 794 struct stat ub; 795 int error; 796 797 if ((fp = fd_getfile(fdp, fd)) == NULL) 798 return (EBADF); 799 error = (*fp->f_ops->fo_stat)(fp, &ub, p); 800 FRELE(fp, p); 801 if (error == 0) { 802 /* 803 * Don't let non-root see generation numbers 804 * (for NFS security) 805 */ 806 if (suser(p)) 807 ub.st_gen = 0; 808 error = copyout((caddr_t)&ub, (caddr_t)SCARG(uap, sb), 809 sizeof (ub)); 810 } 811 #ifdef KTRACE 812 if (error == 0 && KTRPOINT(p, KTR_STRUCT)) 813 ktrstat(p, &ub); 814 #endif 815 return (error); 816 } 817 818 /* 819 * Return pathconf information about a file descriptor. 820 */ 821 int 822 sys_fpathconf(struct proc *p, void *v, register_t *retval) 823 { 824 struct sys_fpathconf_args /* { 825 syscallarg(int) fd; 826 syscallarg(int) name; 827 } */ *uap = v; 828 int fd = SCARG(uap, fd); 829 struct filedesc *fdp = p->p_fd; 830 struct file *fp; 831 struct vnode *vp; 832 int error; 833 834 if ((fp = fd_getfile(fdp, fd)) == NULL) 835 return (EBADF); 836 switch (fp->f_type) { 837 case DTYPE_PIPE: 838 case DTYPE_SOCKET: 839 if (SCARG(uap, name) != _PC_PIPE_BUF) { 840 error = EINVAL; 841 break; 842 } 843 *retval = PIPE_BUF; 844 error = 0; 845 break; 846 847 case DTYPE_VNODE: 848 vp = fp->f_data; 849 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 850 error = VOP_PATHCONF(vp, SCARG(uap, name), retval); 851 VOP_UNLOCK(vp); 852 break; 853 854 default: 855 error = EOPNOTSUPP; 856 break; 857 } 858 FRELE(fp, p); 859 return (error); 860 } 861 862 /* 863 * Allocate a file descriptor for the process. 864 */ 865 int 866 fdalloc(struct proc *p, int want, int *result) 867 { 868 struct filedesc *fdp = p->p_fd; 869 int lim, last, i; 870 u_int new, off; 871 872 fdpassertlocked(fdp); 873 874 /* 875 * Search for a free descriptor starting at the higher 876 * of want or fd_freefile. If that fails, consider 877 * expanding the ofile array. 878 */ 879 restart: 880 lim = min((int)lim_cur(RLIMIT_NOFILE), maxfiles); 881 last = min(fdp->fd_nfiles, lim); 882 if ((i = want) < fdp->fd_freefile) 883 i = fdp->fd_freefile; 884 off = i >> NDENTRYSHIFT; 885 new = find_next_zero(fdp->fd_himap, off, 886 (last + NDENTRIES - 1) >> NDENTRYSHIFT); 887 if (new != -1) { 888 i = find_next_zero(&fdp->fd_lomap[new], 889 new > off ? 0 : i & NDENTRYMASK, 890 NDENTRIES); 891 if (i == -1) { 892 /* 893 * Free file descriptor in this block was 894 * below want, try again with higher want. 895 */ 896 want = (new + 1) << NDENTRYSHIFT; 897 goto restart; 898 } 899 i += (new << NDENTRYSHIFT); 900 if (i < last) { 901 fd_used(fdp, i); 902 if (want <= fdp->fd_freefile) 903 fdp->fd_freefile = i; 904 *result = i; 905 fdp->fd_ofileflags[i] = 0; 906 if (ISSET(p->p_p->ps_flags, PS_PLEDGE)) 907 fdp->fd_ofileflags[i] |= UF_PLEDGED; 908 return (0); 909 } 910 } 911 if (fdp->fd_nfiles >= lim) 912 return (EMFILE); 913 914 return (ENOSPC); 915 } 916 917 void 918 fdexpand(struct proc *p) 919 { 920 struct filedesc *fdp = p->p_fd; 921 int nfiles, oldnfiles; 922 size_t copylen; 923 struct file **newofile, **oldofile; 924 char *newofileflags; 925 u_int *newhimap, *newlomap; 926 927 fdpassertlocked(fdp); 928 929 oldnfiles = fdp->fd_nfiles; 930 oldofile = fdp->fd_ofiles; 931 932 /* 933 * No space in current array. 934 */ 935 if (fdp->fd_nfiles < NDEXTENT) 936 nfiles = NDEXTENT; 937 else 938 nfiles = 2 * fdp->fd_nfiles; 939 940 newofile = mallocarray(nfiles, OFILESIZE, M_FILEDESC, M_WAITOK); 941 /* 942 * Allocate all required chunks before calling free(9) to make 943 * sure that ``fd_ofiles'' stays valid if we go to sleep. 944 */ 945 if (NDHISLOTS(nfiles) > NDHISLOTS(fdp->fd_nfiles)) { 946 newhimap = mallocarray(NDHISLOTS(nfiles), sizeof(u_int), 947 M_FILEDESC, M_WAITOK); 948 newlomap = mallocarray(NDLOSLOTS(nfiles), sizeof(u_int), 949 M_FILEDESC, M_WAITOK); 950 } 951 newofileflags = (char *) &newofile[nfiles]; 952 953 /* 954 * Copy the existing ofile and ofileflags arrays 955 * and zero the new portion of each array. 956 */ 957 copylen = sizeof(struct file *) * fdp->fd_nfiles; 958 memcpy(newofile, fdp->fd_ofiles, copylen); 959 memset((char *)newofile + copylen, 0, 960 nfiles * sizeof(struct file *) - copylen); 961 copylen = sizeof(char) * fdp->fd_nfiles; 962 memcpy(newofileflags, fdp->fd_ofileflags, copylen); 963 memset(newofileflags + copylen, 0, nfiles * sizeof(char) - copylen); 964 965 if (NDHISLOTS(nfiles) > NDHISLOTS(fdp->fd_nfiles)) { 966 copylen = NDHISLOTS(fdp->fd_nfiles) * sizeof(u_int); 967 memcpy(newhimap, fdp->fd_himap, copylen); 968 memset((char *)newhimap + copylen, 0, 969 NDHISLOTS(nfiles) * sizeof(u_int) - copylen); 970 971 copylen = NDLOSLOTS(fdp->fd_nfiles) * sizeof(u_int); 972 memcpy(newlomap, fdp->fd_lomap, copylen); 973 memset((char *)newlomap + copylen, 0, 974 NDLOSLOTS(nfiles) * sizeof(u_int) - copylen); 975 976 if (NDHISLOTS(fdp->fd_nfiles) > NDHISLOTS(NDFILE)) { 977 free(fdp->fd_himap, M_FILEDESC, 978 NDHISLOTS(fdp->fd_nfiles) * sizeof(u_int)); 979 free(fdp->fd_lomap, M_FILEDESC, 980 NDLOSLOTS(fdp->fd_nfiles) * sizeof(u_int)); 981 } 982 fdp->fd_himap = newhimap; 983 fdp->fd_lomap = newlomap; 984 } 985 986 mtx_enter(&fdp->fd_fplock); 987 fdp->fd_ofiles = newofile; 988 mtx_leave(&fdp->fd_fplock); 989 990 fdp->fd_ofileflags = newofileflags; 991 fdp->fd_nfiles = nfiles; 992 993 if (oldnfiles > NDFILE) 994 free(oldofile, M_FILEDESC, oldnfiles * OFILESIZE); 995 } 996 997 /* 998 * Create a new open file structure and allocate 999 * a file descriptor for the process that refers to it. 1000 */ 1001 int 1002 falloc(struct proc *p, struct file **resultfp, int *resultfd) 1003 { 1004 struct file *fp; 1005 int error, i; 1006 1007 KASSERT(resultfp != NULL); 1008 KASSERT(resultfd != NULL); 1009 1010 fdpassertlocked(p->p_fd); 1011 restart: 1012 if ((error = fdalloc(p, 0, &i)) != 0) { 1013 if (error == ENOSPC) { 1014 fdexpand(p); 1015 goto restart; 1016 } 1017 return (error); 1018 } 1019 1020 fp = fnew(p); 1021 if (fp == NULL) { 1022 fd_unused(p->p_fd, i); 1023 return (ENFILE); 1024 } 1025 1026 FREF(fp); 1027 *resultfp = fp; 1028 *resultfd = i; 1029 1030 return (0); 1031 } 1032 1033 struct file * 1034 fnew(struct proc *p) 1035 { 1036 struct file *fp; 1037 int nfiles; 1038 1039 nfiles = atomic_inc_int_nv(&numfiles); 1040 if (nfiles > maxfiles) { 1041 atomic_dec_int(&numfiles); 1042 tablefull("file"); 1043 return (NULL); 1044 } 1045 1046 fp = pool_get(&file_pool, PR_WAITOK|PR_ZERO); 1047 /* 1048 * We need to block interrupts as long as `f_mtx' is being taken 1049 * with and without the KERNEL_LOCK(). 1050 */ 1051 mtx_init(&fp->f_mtx, IPL_MPFLOOR); 1052 fp->f_count = 1; 1053 fp->f_cred = p->p_ucred; 1054 crhold(fp->f_cred); 1055 1056 return (fp); 1057 } 1058 1059 /* 1060 * Build a new filedesc structure. 1061 */ 1062 struct filedesc * 1063 fdinit(void) 1064 { 1065 struct filedesc0 *newfdp; 1066 1067 newfdp = pool_get(&fdesc_pool, PR_WAITOK|PR_ZERO); 1068 rw_init(&newfdp->fd_fd.fd_lock, "fdlock"); 1069 mtx_init(&newfdp->fd_fd.fd_fplock, IPL_MPFLOOR); 1070 LIST_INIT(&newfdp->fd_fd.fd_kqlist); 1071 1072 /* Create the file descriptor table. */ 1073 newfdp->fd_fd.fd_refcnt = 1; 1074 newfdp->fd_fd.fd_cmask = S_IWGRP|S_IWOTH; 1075 newfdp->fd_fd.fd_ofiles = newfdp->fd_dfiles; 1076 newfdp->fd_fd.fd_ofileflags = newfdp->fd_dfileflags; 1077 newfdp->fd_fd.fd_nfiles = NDFILE; 1078 newfdp->fd_fd.fd_himap = newfdp->fd_dhimap; 1079 newfdp->fd_fd.fd_lomap = newfdp->fd_dlomap; 1080 1081 newfdp->fd_fd.fd_freefile = 0; 1082 newfdp->fd_fd.fd_lastfile = 0; 1083 1084 return (&newfdp->fd_fd); 1085 } 1086 1087 /* 1088 * Share a filedesc structure. 1089 */ 1090 struct filedesc * 1091 fdshare(struct process *pr) 1092 { 1093 pr->ps_fd->fd_refcnt++; 1094 return (pr->ps_fd); 1095 } 1096 1097 /* 1098 * Copy a filedesc structure. 1099 */ 1100 struct filedesc * 1101 fdcopy(struct process *pr) 1102 { 1103 struct filedesc *newfdp, *fdp = pr->ps_fd; 1104 int i; 1105 1106 newfdp = fdinit(); 1107 1108 fdplock(fdp); 1109 if (fdp->fd_cdir) { 1110 vref(fdp->fd_cdir); 1111 newfdp->fd_cdir = fdp->fd_cdir; 1112 } 1113 if (fdp->fd_rdir) { 1114 vref(fdp->fd_rdir); 1115 newfdp->fd_rdir = fdp->fd_rdir; 1116 } 1117 1118 /* 1119 * If the number of open files fits in the internal arrays 1120 * of the open file structure, use them, otherwise allocate 1121 * additional memory for the number of descriptors currently 1122 * in use. 1123 */ 1124 if (fdp->fd_lastfile >= NDFILE) { 1125 /* 1126 * Compute the smallest multiple of NDEXTENT needed 1127 * for the file descriptors currently in use, 1128 * allowing the table to shrink. 1129 */ 1130 i = fdp->fd_nfiles; 1131 while (i >= 2 * NDEXTENT && i > fdp->fd_lastfile * 2) 1132 i /= 2; 1133 newfdp->fd_ofiles = mallocarray(i, OFILESIZE, M_FILEDESC, 1134 M_WAITOK | M_ZERO); 1135 newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i]; 1136 newfdp->fd_nfiles = i; 1137 } 1138 if (NDHISLOTS(newfdp->fd_nfiles) > NDHISLOTS(NDFILE)) { 1139 newfdp->fd_himap = mallocarray(NDHISLOTS(newfdp->fd_nfiles), 1140 sizeof(u_int), M_FILEDESC, M_WAITOK | M_ZERO); 1141 newfdp->fd_lomap = mallocarray(NDLOSLOTS(newfdp->fd_nfiles), 1142 sizeof(u_int), M_FILEDESC, M_WAITOK | M_ZERO); 1143 } 1144 newfdp->fd_freefile = fdp->fd_freefile; 1145 newfdp->fd_flags = fdp->fd_flags; 1146 newfdp->fd_cmask = fdp->fd_cmask; 1147 1148 for (i = 0; i <= fdp->fd_lastfile; i++) { 1149 struct file *fp = fdp->fd_ofiles[i]; 1150 1151 if (fp != NULL) { 1152 /* 1153 * XXX Gruesome hack. If count gets too high, fail 1154 * to copy an fd, since fdcopy()'s callers do not 1155 * permit it to indicate failure yet. 1156 * Meanwhile, kqueue files have to be 1157 * tied to the process that opened them to enforce 1158 * their internal consistency, so close them here. 1159 */ 1160 if (fp->f_count >= FDUP_MAX_COUNT || 1161 fp->f_type == DTYPE_KQUEUE) { 1162 if (i < newfdp->fd_freefile) 1163 newfdp->fd_freefile = i; 1164 continue; 1165 } 1166 1167 FREF(fp); 1168 newfdp->fd_ofiles[i] = fp; 1169 newfdp->fd_ofileflags[i] = fdp->fd_ofileflags[i]; 1170 fd_used(newfdp, i); 1171 } 1172 } 1173 fdpunlock(fdp); 1174 1175 return (newfdp); 1176 } 1177 1178 /* 1179 * Release a filedesc structure. 1180 */ 1181 void 1182 fdfree(struct proc *p) 1183 { 1184 struct filedesc *fdp = p->p_fd; 1185 struct file *fp; 1186 int fd; 1187 1188 if (--fdp->fd_refcnt > 0) 1189 return; 1190 for (fd = 0; fd <= fdp->fd_lastfile; fd++) { 1191 fp = fdp->fd_ofiles[fd]; 1192 if (fp != NULL) { 1193 fdp->fd_ofiles[fd] = NULL; 1194 knote_fdclose(p, fd); 1195 /* closef() expects a refcount of 2 */ 1196 FREF(fp); 1197 (void) closef(fp, p); 1198 } 1199 } 1200 p->p_fd = NULL; 1201 if (fdp->fd_nfiles > NDFILE) 1202 free(fdp->fd_ofiles, M_FILEDESC, fdp->fd_nfiles * OFILESIZE); 1203 if (NDHISLOTS(fdp->fd_nfiles) > NDHISLOTS(NDFILE)) { 1204 free(fdp->fd_himap, M_FILEDESC, 1205 NDHISLOTS(fdp->fd_nfiles) * sizeof(u_int)); 1206 free(fdp->fd_lomap, M_FILEDESC, 1207 NDLOSLOTS(fdp->fd_nfiles) * sizeof(u_int)); 1208 } 1209 if (fdp->fd_cdir) 1210 vrele(fdp->fd_cdir); 1211 if (fdp->fd_rdir) 1212 vrele(fdp->fd_rdir); 1213 pool_put(&fdesc_pool, fdp); 1214 } 1215 1216 /* 1217 * Internal form of close. 1218 * Decrement reference count on file structure. 1219 * Note: p may be NULL when closing a file 1220 * that was being passed in a message. 1221 * 1222 * The fp must have its usecount bumped and will be FRELEd here. 1223 */ 1224 int 1225 closef(struct file *fp, struct proc *p) 1226 { 1227 struct filedesc *fdp; 1228 1229 if (fp == NULL) 1230 return (0); 1231 1232 KASSERTMSG(fp->f_count >= 2, "count (%u) < 2", fp->f_count); 1233 1234 atomic_dec_int(&fp->f_count); 1235 1236 /* 1237 * POSIX record locking dictates that any close releases ALL 1238 * locks owned by this process. This is handled by setting 1239 * a flag in the unlock to free ONLY locks obeying POSIX 1240 * semantics, and not to free BSD-style file locks. 1241 * If the descriptor was in a message, POSIX-style locks 1242 * aren't passed with the descriptor. 1243 */ 1244 1245 if (p && ((fdp = p->p_fd) != NULL) && 1246 (fdp->fd_flags & FD_ADVLOCK) && 1247 fp->f_type == DTYPE_VNODE) { 1248 struct vnode *vp = fp->f_data; 1249 struct flock lf; 1250 1251 lf.l_whence = SEEK_SET; 1252 lf.l_start = 0; 1253 lf.l_len = 0; 1254 lf.l_type = F_UNLCK; 1255 (void) VOP_ADVLOCK(vp, fdp, F_UNLCK, &lf, F_POSIX); 1256 } 1257 1258 return (FRELE(fp, p)); 1259 } 1260 1261 int 1262 fdrop(struct file *fp, struct proc *p) 1263 { 1264 int error; 1265 1266 KASSERTMSG(fp->f_count == 0, "count (%u) != 0", fp->f_count); 1267 1268 mtx_enter(&fhdlk); 1269 if (fp->f_iflags & FIF_INSERTED) 1270 LIST_REMOVE(fp, f_list); 1271 mtx_leave(&fhdlk); 1272 1273 if (fp->f_ops) 1274 error = (*fp->f_ops->fo_close)(fp, p); 1275 else 1276 error = 0; 1277 1278 crfree(fp->f_cred); 1279 atomic_dec_int(&numfiles); 1280 pool_put(&file_pool, fp); 1281 1282 return (error); 1283 } 1284 1285 /* 1286 * Apply an advisory lock on a file descriptor. 1287 * 1288 * Just attempt to get a record lock of the requested type on 1289 * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0). 1290 */ 1291 int 1292 sys_flock(struct proc *p, void *v, register_t *retval) 1293 { 1294 struct sys_flock_args /* { 1295 syscallarg(int) fd; 1296 syscallarg(int) how; 1297 } */ *uap = v; 1298 int fd = SCARG(uap, fd); 1299 int how = SCARG(uap, how); 1300 struct filedesc *fdp = p->p_fd; 1301 struct file *fp; 1302 struct vnode *vp; 1303 struct flock lf; 1304 int error; 1305 1306 if ((fp = fd_getfile(fdp, fd)) == NULL) 1307 return (EBADF); 1308 if (fp->f_type != DTYPE_VNODE) { 1309 error = EOPNOTSUPP; 1310 goto out; 1311 } 1312 vp = fp->f_data; 1313 lf.l_whence = SEEK_SET; 1314 lf.l_start = 0; 1315 lf.l_len = 0; 1316 if (how & LOCK_UN) { 1317 lf.l_type = F_UNLCK; 1318 atomic_clearbits_int(&fp->f_iflags, FIF_HASLOCK); 1319 error = VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK); 1320 goto out; 1321 } 1322 if (how & LOCK_EX) 1323 lf.l_type = F_WRLCK; 1324 else if (how & LOCK_SH) 1325 lf.l_type = F_RDLCK; 1326 else { 1327 error = EINVAL; 1328 goto out; 1329 } 1330 atomic_setbits_int(&fp->f_iflags, FIF_HASLOCK); 1331 if (how & LOCK_NB) 1332 error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK); 1333 else 1334 error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK|F_WAIT); 1335 out: 1336 FRELE(fp, p); 1337 return (error); 1338 } 1339 1340 /* 1341 * File Descriptor pseudo-device driver (/dev/fd/). 1342 * 1343 * Opening minor device N dup()s the file (if any) connected to file 1344 * descriptor N belonging to the calling process. Note that this driver 1345 * consists of only the ``open()'' routine, because all subsequent 1346 * references to this file will be direct to the other driver. 1347 */ 1348 int 1349 filedescopen(dev_t dev, int mode, int type, struct proc *p) 1350 { 1351 1352 /* 1353 * XXX Kludge: set curproc->p_dupfd to contain the value of the 1354 * the file descriptor being sought for duplication. The error 1355 * return ensures that the vnode for this device will be released 1356 * by vn_open. Open will detect this special error and take the 1357 * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN 1358 * will simply report the error. 1359 */ 1360 p->p_dupfd = minor(dev); 1361 return (ENODEV); 1362 } 1363 1364 /* 1365 * Duplicate the specified descriptor to a free descriptor. 1366 */ 1367 int 1368 dupfdopen(struct proc *p, int indx, int mode) 1369 { 1370 struct filedesc *fdp = p->p_fd; 1371 int dupfd = p->p_dupfd; 1372 struct file *wfp; 1373 1374 fdpassertlocked(fdp); 1375 1376 /* 1377 * Assume that the filename was user-specified; applications do 1378 * not tend to open /dev/fd/# when they can just call dup() 1379 */ 1380 if ((p->p_p->ps_flags & (PS_SUGIDEXEC | PS_SUGID))) { 1381 if (p->p_descfd == 255) 1382 return (EPERM); 1383 if (p->p_descfd != dupfd) 1384 return (EPERM); 1385 } 1386 1387 /* 1388 * If the to-be-dup'd fd number is greater than the allowed number 1389 * of file descriptors, or the fd to be dup'd has already been 1390 * closed, reject. Note, there is no need to check for new == old 1391 * because fd_getfile will return NULL if the file at indx is 1392 * newly created by falloc. 1393 */ 1394 if ((wfp = fd_getfile(fdp, dupfd)) == NULL) 1395 return (EBADF); 1396 1397 /* 1398 * Check that the mode the file is being opened for is a 1399 * subset of the mode of the existing descriptor. 1400 */ 1401 if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag) { 1402 FRELE(wfp, p); 1403 return (EACCES); 1404 } 1405 if (wfp->f_count >= FDUP_MAX_COUNT) { 1406 FRELE(wfp, p); 1407 return (EDEADLK); 1408 } 1409 1410 KASSERT(wfp->f_iflags & FIF_INSERTED); 1411 1412 mtx_enter(&fdp->fd_fplock); 1413 KASSERT(fdp->fd_ofiles[indx] == NULL); 1414 fdp->fd_ofiles[indx] = wfp; 1415 mtx_leave(&fdp->fd_fplock); 1416 1417 fdp->fd_ofileflags[indx] = (fdp->fd_ofileflags[indx] & UF_EXCLOSE) | 1418 (fdp->fd_ofileflags[dupfd] & ~UF_EXCLOSE); 1419 1420 return (0); 1421 } 1422 1423 /* 1424 * Close any files on exec? 1425 */ 1426 void 1427 fdcloseexec(struct proc *p) 1428 { 1429 struct filedesc *fdp = p->p_fd; 1430 int fd; 1431 1432 fdplock(fdp); 1433 for (fd = 0; fd <= fdp->fd_lastfile; fd++) { 1434 fdp->fd_ofileflags[fd] &= ~UF_PLEDGED; 1435 if (fdp->fd_ofileflags[fd] & UF_EXCLOSE) { 1436 /* fdrelease() unlocks fdp. */ 1437 (void) fdrelease(p, fd); 1438 fdplock(fdp); 1439 } 1440 } 1441 fdpunlock(fdp); 1442 } 1443 1444 int 1445 sys_closefrom(struct proc *p, void *v, register_t *retval) 1446 { 1447 struct sys_closefrom_args *uap = v; 1448 struct filedesc *fdp = p->p_fd; 1449 u_int startfd, i; 1450 1451 startfd = SCARG(uap, fd); 1452 fdplock(fdp); 1453 1454 if (startfd > fdp->fd_lastfile) { 1455 fdpunlock(fdp); 1456 return (EBADF); 1457 } 1458 1459 for (i = startfd; i <= fdp->fd_lastfile; i++) { 1460 /* fdrelease() unlocks fdp. */ 1461 fdrelease(p, i); 1462 fdplock(fdp); 1463 } 1464 1465 fdpunlock(fdp); 1466 return (0); 1467 } 1468 1469 int 1470 sys_getdtablecount(struct proc *p, void *v, register_t *retval) 1471 { 1472 *retval = p->p_fd->fd_openfd; 1473 return (0); 1474 } 1475