1 /* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94 39 * $FreeBSD: src/sys/kern/vfs_syscalls.c,v 1.151.2.18 2003/04/04 20:35:58 tegge Exp $ 40 * $DragonFly: src/sys/kern/vfs_syscalls.c,v 1.74 2005/10/09 18:07:55 corecode Exp $ 41 */ 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/buf.h> 46 #include <sys/conf.h> 47 #include <sys/sysent.h> 48 #include <sys/malloc.h> 49 #include <sys/mount.h> 50 #include <sys/mountctl.h> 51 #include <sys/sysproto.h> 52 #include <sys/filedesc.h> 53 #include <sys/kernel.h> 54 #include <sys/fcntl.h> 55 #include <sys/file.h> 56 #include <sys/linker.h> 57 #include <sys/stat.h> 58 #include <sys/unistd.h> 59 #include <sys/vnode.h> 60 #include <sys/proc.h> 61 #include <sys/namei.h> 62 #include <sys/nlookup.h> 63 #include <sys/dirent.h> 64 #include <sys/extattr.h> 65 #include <sys/kern_syscall.h> 66 67 #include <machine/limits.h> 68 #include <vfs/union/union.h> 69 #include <sys/sysctl.h> 70 #include <vm/vm.h> 71 #include <vm/vm_object.h> 72 #include <vm/vm_zone.h> 73 #include <vm/vm_page.h> 74 75 #include <sys/file2.h> 76 77 static int checkvp_chdir (struct vnode *vn, struct thread *td); 78 static void checkdirs (struct vnode *olddp, struct namecache *ncp); 79 static int chroot_refuse_vdir_fds (struct filedesc *fdp); 80 static int chroot_visible_mnt(struct mount *mp, struct proc *p); 81 static int getutimes (const struct timeval *, struct timespec *); 82 static int setfown (struct vnode *, uid_t, gid_t); 83 static int setfmode (struct vnode *, int); 84 static int setfflags (struct vnode *, int); 85 static int setutimes (struct vnode *, const struct timespec *, int); 86 static int usermount = 0; /* if 1, non-root can mount fs. */ 87 88 int (*union_dircheckp) (struct thread *, struct vnode **, struct file *); 89 90 SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0, ""); 91 92 /* 93 * Virtual File System System Calls 94 */ 95 96 /* 97 * Mount a file system. 98 */ 99 /* 100 * mount_args(char *type, char *path, int flags, caddr_t data) 101 */ 102 /* ARGSUSED */ 103 int 104 mount(struct mount_args *uap) 105 { 106 struct thread *td = curthread; 107 struct proc *p = td->td_proc; 108 struct vnode *vp; 109 struct namecache *ncp; 110 struct mount *mp; 111 struct vfsconf *vfsp; 112 int error, flag = 0, flag2 = 0; 113 struct vattr va; 114 struct nlookupdata nd; 115 char fstypename[MFSNAMELEN]; 116 struct nlcomponent nlc; 117 118 KKASSERT(p); 119 if (p->p_ucred->cr_prison != NULL) 120 return (EPERM); 121 if (usermount == 0 && (error = suser(td))) 122 return (error); 123 /* 124 * Do not allow NFS export by non-root users. 125 */ 126 if (uap->flags & MNT_EXPORTED) { 127 error = suser(td); 128 if (error) 129 return (error); 130 } 131 /* 132 * Silently enforce MNT_NOSUID and MNT_NODEV for non-root users 133 */ 134 if (suser(td)) 135 uap->flags |= MNT_NOSUID | MNT_NODEV; 136 137 /* 138 * Lookup the requested path and extract the ncp and vnode. 139 */ 140 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 141 if (error == 0) { 142 if ((error = nlookup(&nd)) == 0) { 143 if (nd.nl_ncp->nc_vp == NULL) 144 error = ENOENT; 145 } 146 } 147 if (error) { 148 nlookup_done(&nd); 149 return (error); 150 } 151 152 /* 153 * Extract the locked+refd ncp and cleanup the nd structure 154 */ 155 ncp = nd.nl_ncp; 156 nd.nl_ncp = NULL; 157 nlookup_done(&nd); 158 159 /* 160 * now we have the locked ref'd ncp and unreferenced vnode. 161 */ 162 vp = ncp->nc_vp; 163 if ((error = vget(vp, LK_EXCLUSIVE, td)) != 0) { 164 cache_put(ncp); 165 return (error); 166 } 167 cache_unlock(ncp); 168 169 /* 170 * Now we have an unlocked ref'd ncp and a locked ref'd vp 171 */ 172 if (uap->flags & MNT_UPDATE) { 173 if ((vp->v_flag & VROOT) == 0) { 174 cache_drop(ncp); 175 vput(vp); 176 return (EINVAL); 177 } 178 mp = vp->v_mount; 179 flag = mp->mnt_flag; 180 flag2 = mp->mnt_kern_flag; 181 /* 182 * We only allow the filesystem to be reloaded if it 183 * is currently mounted read-only. 184 */ 185 if ((uap->flags & MNT_RELOAD) && 186 ((mp->mnt_flag & MNT_RDONLY) == 0)) { 187 cache_drop(ncp); 188 vput(vp); 189 return (EOPNOTSUPP); /* Needs translation */ 190 } 191 /* 192 * Only root, or the user that did the original mount is 193 * permitted to update it. 194 */ 195 if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid && 196 (error = suser(td))) { 197 cache_drop(ncp); 198 vput(vp); 199 return (error); 200 } 201 if (vfs_busy(mp, LK_NOWAIT, td)) { 202 cache_drop(ncp); 203 vput(vp); 204 return (EBUSY); 205 } 206 if ((vp->v_flag & VMOUNT) != 0 || 207 vp->v_mountedhere != NULL) { 208 cache_drop(ncp); 209 vfs_unbusy(mp, td); 210 vput(vp); 211 return (EBUSY); 212 } 213 vp->v_flag |= VMOUNT; 214 mp->mnt_flag |= 215 uap->flags & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE); 216 VOP_UNLOCK(vp, 0, td); 217 goto update; 218 } 219 /* 220 * If the user is not root, ensure that they own the directory 221 * onto which we are attempting to mount. 222 */ 223 if ((error = VOP_GETATTR(vp, &va, td)) || 224 (va.va_uid != p->p_ucred->cr_uid && 225 (error = suser(td)))) { 226 cache_drop(ncp); 227 vput(vp); 228 return (error); 229 } 230 if ((error = vinvalbuf(vp, V_SAVE, td, 0, 0)) != 0) { 231 cache_drop(ncp); 232 vput(vp); 233 return (error); 234 } 235 if (vp->v_type != VDIR) { 236 cache_drop(ncp); 237 vput(vp); 238 return (ENOTDIR); 239 } 240 if ((error = copyinstr(uap->type, fstypename, MFSNAMELEN, NULL)) != 0) { 241 cache_drop(ncp); 242 vput(vp); 243 return (error); 244 } 245 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) { 246 if (!strcmp(vfsp->vfc_name, fstypename)) 247 break; 248 } 249 if (vfsp == NULL) { 250 linker_file_t lf; 251 252 /* Only load modules for root (very important!) */ 253 if ((error = suser(td)) != 0) { 254 cache_drop(ncp); 255 vput(vp); 256 return error; 257 } 258 error = linker_load_file(fstypename, &lf); 259 if (error || lf == NULL) { 260 cache_drop(ncp); 261 vput(vp); 262 if (lf == NULL) 263 error = ENODEV; 264 return error; 265 } 266 lf->userrefs++; 267 /* lookup again, see if the VFS was loaded */ 268 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) { 269 if (!strcmp(vfsp->vfc_name, fstypename)) 270 break; 271 } 272 if (vfsp == NULL) { 273 lf->userrefs--; 274 linker_file_unload(lf); 275 cache_drop(ncp); 276 vput(vp); 277 return (ENODEV); 278 } 279 } 280 if ((vp->v_flag & VMOUNT) != 0 || 281 vp->v_mountedhere != NULL) { 282 cache_drop(ncp); 283 vput(vp); 284 return (EBUSY); 285 } 286 vp->v_flag |= VMOUNT; 287 288 /* 289 * Allocate and initialize the filesystem. 290 */ 291 mp = malloc(sizeof(struct mount), M_MOUNT, M_ZERO|M_WAITOK); 292 TAILQ_INIT(&mp->mnt_nvnodelist); 293 TAILQ_INIT(&mp->mnt_reservedvnlist); 294 TAILQ_INIT(&mp->mnt_jlist); 295 mp->mnt_nvnodelistsize = 0; 296 lockinit(&mp->mnt_lock, 0, "vfslock", 0, LK_NOPAUSE); 297 vfs_busy(mp, LK_NOWAIT, td); 298 mp->mnt_op = vfsp->vfc_vfsops; 299 mp->mnt_vfc = vfsp; 300 vfsp->vfc_refcount++; 301 mp->mnt_stat.f_type = vfsp->vfc_typenum; 302 mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK; 303 strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN); 304 mp->mnt_vnodecovered = vp; 305 mp->mnt_stat.f_owner = p->p_ucred->cr_uid; 306 mp->mnt_iosize_max = DFLTPHYS; 307 VOP_UNLOCK(vp, 0, td); 308 update: 309 /* 310 * Set the mount level flags. 311 */ 312 if (uap->flags & MNT_RDONLY) 313 mp->mnt_flag |= MNT_RDONLY; 314 else if (mp->mnt_flag & MNT_RDONLY) 315 mp->mnt_kern_flag |= MNTK_WANTRDWR; 316 mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV | 317 MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_NOATIME | 318 MNT_NOSYMFOLLOW | MNT_IGNORE | 319 MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR); 320 mp->mnt_flag |= uap->flags & (MNT_NOSUID | MNT_NOEXEC | 321 MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_FORCE | 322 MNT_NOSYMFOLLOW | MNT_IGNORE | 323 MNT_NOATIME | MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR); 324 /* 325 * Mount the filesystem. 326 * XXX The final recipients of VFS_MOUNT just overwrite the ndp they 327 * get. 328 */ 329 error = VFS_MOUNT(mp, uap->path, uap->data, td); 330 if (mp->mnt_flag & MNT_UPDATE) { 331 if (mp->mnt_kern_flag & MNTK_WANTRDWR) 332 mp->mnt_flag &= ~MNT_RDONLY; 333 mp->mnt_flag &=~ (MNT_UPDATE | MNT_RELOAD | MNT_FORCE); 334 mp->mnt_kern_flag &=~ MNTK_WANTRDWR; 335 if (error) { 336 mp->mnt_flag = flag; 337 mp->mnt_kern_flag = flag2; 338 } 339 vfs_unbusy(mp, td); 340 vp->v_flag &= ~VMOUNT; 341 vrele(vp); 342 cache_drop(ncp); 343 return (error); 344 } 345 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 346 /* 347 * Put the new filesystem on the mount list after root. The mount 348 * point gets its own mnt_ncp which is a special ncp linking the 349 * vnode-under to the root of the new mount. The lookup code 350 * detects the mount point going forward and detects the special 351 * mnt_ncp via NCP_MOUNTPT going backwards. 352 * 353 * It is not necessary to invalidate or purge the vnode underneath 354 * because elements under the mount will be given their own glue 355 * namecache record. 356 */ 357 if (!error) { 358 nlc.nlc_nameptr = ""; 359 nlc.nlc_namelen = 0; 360 mp->mnt_ncp = cache_nlookup(ncp, &nlc); 361 cache_setunresolved(mp->mnt_ncp); 362 mp->mnt_ncp->nc_flag |= NCF_MOUNTPT; 363 mp->mnt_ncp->nc_mount = mp; 364 cache_drop(ncp); 365 /* XXX get the root of the fs and cache_setvp(mnt_ncp...) */ 366 vp->v_flag &= ~VMOUNT; 367 vp->v_mountedhere = mp; 368 mountlist_insert(mp, MNTINS_LAST); 369 checkdirs(vp, mp->mnt_ncp); 370 cache_unlock(mp->mnt_ncp); /* leave ref intact */ 371 VOP_UNLOCK(vp, 0, td); 372 error = vfs_allocate_syncvnode(mp); 373 vfs_unbusy(mp, td); 374 if ((error = VFS_START(mp, 0, td)) != 0) 375 vrele(vp); 376 } else { 377 vfs_rm_vnodeops(&mp->mnt_vn_coherency_ops); 378 vfs_rm_vnodeops(&mp->mnt_vn_journal_ops); 379 vfs_rm_vnodeops(&mp->mnt_vn_norm_ops); 380 vfs_rm_vnodeops(&mp->mnt_vn_spec_ops); 381 vfs_rm_vnodeops(&mp->mnt_vn_fifo_ops); 382 vp->v_flag &= ~VMOUNT; 383 mp->mnt_vfc->vfc_refcount--; 384 vfs_unbusy(mp, td); 385 free(mp, M_MOUNT); 386 cache_drop(ncp); 387 vput(vp); 388 } 389 return (error); 390 } 391 392 /* 393 * Scan all active processes to see if any of them have a current 394 * or root directory onto which the new filesystem has just been 395 * mounted. If so, replace them with the new mount point. 396 * 397 * The passed ncp is ref'd and locked (from the mount code) and 398 * must be associated with the vnode representing the root of the 399 * mount point. 400 */ 401 static void 402 checkdirs(struct vnode *olddp, struct namecache *ncp) 403 { 404 struct filedesc *fdp; 405 struct vnode *newdp; 406 struct mount *mp; 407 struct proc *p; 408 409 if (olddp->v_usecount == 1) 410 return; 411 mp = olddp->v_mountedhere; 412 if (VFS_ROOT(mp, &newdp)) 413 panic("mount: lost mount"); 414 cache_setvp(ncp, newdp); 415 416 if (rootvnode == olddp) { 417 vref(newdp); 418 vfs_cache_setroot(newdp, cache_hold(ncp)); 419 } 420 421 FOREACH_PROC_IN_SYSTEM(p) { 422 fdp = p->p_fd; 423 if (fdp->fd_cdir == olddp) { 424 vrele(fdp->fd_cdir); 425 vref(newdp); 426 fdp->fd_cdir = newdp; 427 cache_drop(fdp->fd_ncdir); 428 fdp->fd_ncdir = cache_hold(ncp); 429 } 430 if (fdp->fd_rdir == olddp) { 431 vrele(fdp->fd_rdir); 432 vref(newdp); 433 fdp->fd_rdir = newdp; 434 cache_drop(fdp->fd_nrdir); 435 fdp->fd_nrdir = cache_hold(ncp); 436 } 437 } 438 vput(newdp); 439 } 440 441 /* 442 * Unmount a file system. 443 * 444 * Note: unmount takes a path to the vnode mounted on as argument, 445 * not special file (as before). 446 */ 447 /* 448 * umount_args(char *path, int flags) 449 */ 450 /* ARGSUSED */ 451 int 452 unmount(struct unmount_args *uap) 453 { 454 struct thread *td = curthread; 455 struct proc *p = td->td_proc; 456 struct vnode *vp; 457 struct mount *mp; 458 int error; 459 struct nlookupdata nd; 460 461 KKASSERT(p); 462 if (p->p_ucred->cr_prison != NULL) 463 return (EPERM); 464 if (usermount == 0 && (error = suser(td))) 465 return (error); 466 467 vp = NULL; 468 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 469 if (error == 0) 470 error = nlookup(&nd); 471 if (error == 0) 472 error = cache_vget(nd.nl_ncp, nd.nl_cred, LK_EXCLUSIVE, &vp); 473 nlookup_done(&nd); 474 if (error) 475 return (error); 476 477 mp = vp->v_mount; 478 479 /* 480 * Only root, or the user that did the original mount is 481 * permitted to unmount this filesystem. 482 */ 483 if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) && 484 (error = suser(td))) { 485 vput(vp); 486 return (error); 487 } 488 489 /* 490 * Don't allow unmounting the root file system. 491 */ 492 if (mp->mnt_flag & MNT_ROOTFS) { 493 vput(vp); 494 return (EINVAL); 495 } 496 497 /* 498 * Must be the root of the filesystem 499 */ 500 if ((vp->v_flag & VROOT) == 0) { 501 vput(vp); 502 return (EINVAL); 503 } 504 vput(vp); 505 return (dounmount(mp, uap->flags, td)); 506 } 507 508 /* 509 * Do the actual file system unmount. 510 */ 511 static int 512 dounmount_interlock(struct mount *mp) 513 { 514 if (mp->mnt_kern_flag & MNTK_UNMOUNT) 515 return (EBUSY); 516 mp->mnt_kern_flag |= MNTK_UNMOUNT; 517 return(0); 518 } 519 520 int 521 dounmount(struct mount *mp, int flags, struct thread *td) 522 { 523 struct vnode *coveredvp; 524 int error; 525 int async_flag; 526 527 /* 528 * Exclusive access for unmounting purposes 529 */ 530 if ((error = mountlist_interlock(dounmount_interlock, mp)) != 0) 531 return (error); 532 533 /* 534 * Allow filesystems to detect that a forced unmount is in progress. 535 */ 536 if (flags & MNT_FORCE) 537 mp->mnt_kern_flag |= MNTK_UNMOUNTF; 538 error = lockmgr(&mp->mnt_lock, LK_DRAIN | 539 ((flags & MNT_FORCE) ? 0 : LK_NOWAIT), NULL, td); 540 if (error) { 541 mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF); 542 if (mp->mnt_kern_flag & MNTK_MWAIT) 543 wakeup(mp); 544 return (error); 545 } 546 547 if (mp->mnt_flag & MNT_EXPUBLIC) 548 vfs_setpublicfs(NULL, NULL, NULL); 549 550 vfs_msync(mp, MNT_WAIT); 551 async_flag = mp->mnt_flag & MNT_ASYNC; 552 mp->mnt_flag &=~ MNT_ASYNC; 553 cache_purgevfs(mp); /* remove cache entries for this file sys */ 554 if (mp->mnt_syncer != NULL) 555 vrele(mp->mnt_syncer); 556 if (((mp->mnt_flag & MNT_RDONLY) || 557 (error = VFS_SYNC(mp, MNT_WAIT, td)) == 0) || 558 (flags & MNT_FORCE)) 559 error = VFS_UNMOUNT(mp, flags, td); 560 if (error) { 561 if (mp->mnt_syncer == NULL) 562 vfs_allocate_syncvnode(mp); 563 mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF); 564 mp->mnt_flag |= async_flag; 565 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_REENABLE, NULL, td); 566 if (mp->mnt_kern_flag & MNTK_MWAIT) 567 wakeup(mp); 568 return (error); 569 } 570 /* 571 * Clean up any journals still associated with the mount after 572 * filesystem activity has ceased. 573 */ 574 journal_remove_all_journals(mp, 575 ((flags & MNT_FORCE) ? MC_JOURNAL_STOP_IMM : 0)); 576 577 mountlist_remove(mp); 578 579 /* 580 * Remove any installed vnode ops here so the individual VFSs don't 581 * have to. 582 */ 583 vfs_rm_vnodeops(&mp->mnt_vn_coherency_ops); 584 vfs_rm_vnodeops(&mp->mnt_vn_journal_ops); 585 vfs_rm_vnodeops(&mp->mnt_vn_norm_ops); 586 vfs_rm_vnodeops(&mp->mnt_vn_spec_ops); 587 vfs_rm_vnodeops(&mp->mnt_vn_fifo_ops); 588 589 if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) { 590 coveredvp->v_mountedhere = NULL; 591 vrele(coveredvp); 592 cache_drop(mp->mnt_ncp); 593 mp->mnt_ncp = NULL; 594 } 595 mp->mnt_vfc->vfc_refcount--; 596 if (!TAILQ_EMPTY(&mp->mnt_nvnodelist)) 597 panic("unmount: dangling vnode"); 598 lockmgr(&mp->mnt_lock, LK_RELEASE, NULL, td); 599 if (mp->mnt_kern_flag & MNTK_MWAIT) 600 wakeup(mp); 601 free(mp, M_MOUNT); 602 return (0); 603 } 604 605 /* 606 * Sync each mounted filesystem. 607 */ 608 609 #ifdef DEBUG 610 static int syncprt = 0; 611 SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, ""); 612 #endif /* DEBUG */ 613 614 static int sync_callback(struct mount *mp, void *data); 615 616 /* ARGSUSED */ 617 int 618 sync(struct sync_args *uap) 619 { 620 mountlist_scan(sync_callback, NULL, MNTSCAN_FORWARD); 621 #ifdef DEBUG 622 /* 623 * print out buffer pool stat information on each sync() call. 624 */ 625 if (syncprt) 626 vfs_bufstats(); 627 #endif /* DEBUG */ 628 return (0); 629 } 630 631 static 632 int 633 sync_callback(struct mount *mp, void *data __unused) 634 { 635 int asyncflag; 636 637 if ((mp->mnt_flag & MNT_RDONLY) == 0) { 638 asyncflag = mp->mnt_flag & MNT_ASYNC; 639 mp->mnt_flag &= ~MNT_ASYNC; 640 vfs_msync(mp, MNT_NOWAIT); 641 VFS_SYNC(mp, MNT_NOWAIT, curthread); 642 mp->mnt_flag |= asyncflag; 643 } 644 return(0); 645 } 646 647 /* XXX PRISON: could be per prison flag */ 648 static int prison_quotas; 649 #if 0 650 SYSCTL_INT(_kern_prison, OID_AUTO, quotas, CTLFLAG_RW, &prison_quotas, 0, ""); 651 #endif 652 653 /* 654 * quotactl_args(char *path, int fcmd, int uid, caddr_t arg) 655 * 656 * Change filesystem quotas. 657 */ 658 /* ARGSUSED */ 659 int 660 quotactl(struct quotactl_args *uap) 661 { 662 struct nlookupdata nd; 663 struct thread *td; 664 struct proc *p; 665 struct mount *mp; 666 int error; 667 668 td = curthread; 669 p = td->td_proc; 670 if (p->p_ucred->cr_prison && !prison_quotas) 671 return (EPERM); 672 673 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 674 if (error == 0) 675 error = nlookup(&nd); 676 if (error == 0) { 677 mp = nd.nl_ncp->nc_mount; 678 error = VFS_QUOTACTL(mp, uap->cmd, uap->uid, 679 uap->arg, nd.nl_td); 680 } 681 nlookup_done(&nd); 682 return (error); 683 } 684 685 /* 686 * mountctl(char *path, int op, int fd, const void *ctl, int ctllen, 687 * void *buf, int buflen) 688 * 689 * This function operates on a mount point and executes the specified 690 * operation using the specified control data, and possibly returns data. 691 * 692 * The actual number of bytes stored in the result buffer is returned, 0 693 * if none, otherwise an error is returned. 694 */ 695 /* ARGSUSED */ 696 int 697 mountctl(struct mountctl_args *uap) 698 { 699 struct thread *td = curthread; 700 struct proc *p = td->td_proc; 701 struct filedesc *fdp = p->p_fd; 702 struct file *fp; 703 void *ctl = NULL; 704 void *buf = NULL; 705 char *path = NULL; 706 int error; 707 708 /* 709 * Sanity and permissions checks. We must be root. 710 */ 711 KKASSERT(p); 712 if (p->p_ucred->cr_prison != NULL) 713 return (EPERM); 714 if ((error = suser(td)) != 0) 715 return (error); 716 717 /* 718 * Argument length checks 719 */ 720 if (uap->ctllen < 0 || uap->ctllen > 1024) 721 return (EINVAL); 722 if (uap->buflen < 0 || uap->buflen > 16 * 1024) 723 return (EINVAL); 724 if (uap->path == NULL) 725 return (EINVAL); 726 727 /* 728 * Allocate the necessary buffers and copyin data 729 */ 730 path = zalloc(namei_zone); 731 error = copyinstr(uap->path, path, MAXPATHLEN, NULL); 732 if (error) 733 goto done; 734 735 if (uap->ctllen) { 736 ctl = malloc(uap->ctllen + 1, M_TEMP, M_WAITOK|M_ZERO); 737 error = copyin(uap->ctl, ctl, uap->ctllen); 738 if (error) 739 goto done; 740 } 741 if (uap->buflen) 742 buf = malloc(uap->buflen + 1, M_TEMP, M_WAITOK|M_ZERO); 743 744 /* 745 * Validate the descriptor 746 */ 747 if (uap->fd == -1) { 748 fp = NULL; 749 } else if ((u_int)uap->fd >= fdp->fd_nfiles || 750 (fp = fdp->fd_files[uap->fd].fp) == NULL) { 751 error = EBADF; 752 goto done; 753 } 754 if (fp) 755 fhold(fp); 756 757 /* 758 * Execute the internal kernel function and clean up. 759 */ 760 error = kern_mountctl(path, uap->op, fp, ctl, uap->ctllen, buf, uap->buflen, &uap->sysmsg_result); 761 if (fp) 762 fdrop(fp, td); 763 if (error == 0 && uap->sysmsg_result > 0) 764 error = copyout(buf, uap->buf, uap->sysmsg_result); 765 done: 766 if (path) 767 zfree(namei_zone, path); 768 if (ctl) 769 free(ctl, M_TEMP); 770 if (buf) 771 free(buf, M_TEMP); 772 return (error); 773 } 774 775 /* 776 * Execute a mount control operation by resolving the path to a mount point 777 * and calling vop_mountctl(). 778 */ 779 int 780 kern_mountctl(const char *path, int op, struct file *fp, 781 const void *ctl, int ctllen, 782 void *buf, int buflen, int *res) 783 { 784 struct vnode *vp; 785 struct mount *mp; 786 struct nlookupdata nd; 787 int error; 788 789 *res = 0; 790 vp = NULL; 791 error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW); 792 if (error == 0) 793 error = nlookup(&nd); 794 if (error == 0) 795 error = cache_vget(nd.nl_ncp, nd.nl_cred, LK_EXCLUSIVE, &vp); 796 nlookup_done(&nd); 797 if (error) 798 return (error); 799 800 mp = vp->v_mount; 801 802 /* 803 * Must be the root of the filesystem 804 */ 805 if ((vp->v_flag & VROOT) == 0) { 806 vput(vp); 807 return (EINVAL); 808 } 809 error = vop_mountctl(mp->mnt_vn_use_ops, op, fp, ctl, ctllen, 810 buf, buflen, res); 811 vput(vp); 812 return (error); 813 } 814 815 int 816 kern_statfs(struct nlookupdata *nd, struct statfs *buf) 817 { 818 struct thread *td = curthread; 819 struct proc *p = td->td_proc; 820 struct mount *mp; 821 struct statfs *sp; 822 char *fullpath, *freepath; 823 int error; 824 825 if ((error = nlookup(nd)) != 0) 826 return (error); 827 mp = nd->nl_ncp->nc_mount; 828 sp = &mp->mnt_stat; 829 if ((error = VFS_STATFS(mp, sp, td)) != 0) 830 return (error); 831 832 error = cache_fullpath(p, mp->mnt_ncp, &fullpath, &freepath); 833 if (error) 834 return(error); 835 bzero(sp->f_mntonname, sizeof(sp->f_mntonname)); 836 strlcpy(sp->f_mntonname, fullpath, sizeof(sp->f_mntonname)); 837 free(freepath, M_TEMP); 838 839 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 840 bcopy(sp, buf, sizeof(*buf)); 841 /* Only root should have access to the fsid's. */ 842 if (suser(td)) 843 buf->f_fsid.val[0] = buf->f_fsid.val[1] = 0; 844 return (0); 845 } 846 847 /* 848 * statfs_args(char *path, struct statfs *buf) 849 * 850 * Get filesystem statistics. 851 */ 852 int 853 statfs(struct statfs_args *uap) 854 { 855 struct nlookupdata nd; 856 struct statfs buf; 857 int error; 858 859 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 860 if (error == 0) 861 error = kern_statfs(&nd, &buf); 862 nlookup_done(&nd); 863 if (error == 0) 864 error = copyout(&buf, uap->buf, sizeof(*uap->buf)); 865 return (error); 866 } 867 868 int 869 kern_fstatfs(int fd, struct statfs *buf) 870 { 871 struct thread *td = curthread; 872 struct proc *p = td->td_proc; 873 struct file *fp; 874 struct mount *mp; 875 struct statfs *sp; 876 char *fullpath, *freepath; 877 int error; 878 879 KKASSERT(p); 880 error = getvnode(p->p_fd, fd, &fp); 881 if (error) 882 return (error); 883 mp = ((struct vnode *)fp->f_data)->v_mount; 884 if (mp == NULL) 885 return (EBADF); 886 sp = &mp->mnt_stat; 887 error = VFS_STATFS(mp, sp, td); 888 if (error) 889 return (error); 890 891 error = cache_fullpath(p, mp->mnt_ncp, &fullpath, &freepath); 892 if (error) 893 return(error); 894 bzero(sp->f_mntonname, sizeof(sp->f_mntonname)); 895 strlcpy(sp->f_mntonname, fullpath, sizeof(sp->f_mntonname)); 896 free(freepath, M_TEMP); 897 898 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 899 bcopy(sp, buf, sizeof(*buf)); 900 901 /* Only root should have access to the fsid's. */ 902 if (suser(td)) 903 buf->f_fsid.val[0] = buf->f_fsid.val[1] = 0; 904 return (0); 905 } 906 907 /* 908 * fstatfs_args(int fd, struct statfs *buf) 909 * 910 * Get filesystem statistics. 911 */ 912 int 913 fstatfs(struct fstatfs_args *uap) 914 { 915 struct statfs buf; 916 int error; 917 918 error = kern_fstatfs(uap->fd, &buf); 919 920 if (error == 0) 921 error = copyout(&buf, uap->buf, sizeof(*uap->buf)); 922 return (error); 923 } 924 925 /* 926 * getfsstat_args(struct statfs *buf, long bufsize, int flags) 927 * 928 * Get statistics on all filesystems. 929 */ 930 931 struct getfsstat_info { 932 struct statfs *sfsp; 933 long count; 934 long maxcount; 935 int error; 936 int flags; 937 int is_chrooted; 938 struct thread *td; 939 struct proc *p; 940 }; 941 942 static int getfsstat_callback(struct mount *, void *); 943 944 /* ARGSUSED */ 945 int 946 getfsstat(struct getfsstat_args *uap) 947 { 948 struct thread *td = curthread; 949 struct proc *p = td->td_proc; 950 struct getfsstat_info info; 951 952 bzero(&info, sizeof(info)); 953 if (p != NULL && (p->p_fd->fd_nrdir->nc_flag & NCF_ROOT) == 0) 954 info.is_chrooted = 1; 955 else 956 info.is_chrooted = 0; 957 958 info.maxcount = uap->bufsize / sizeof(struct statfs); 959 info.sfsp = uap->buf; 960 info.count = 0; 961 info.flags = uap->flags; 962 info.td = td; 963 info.p = p; 964 965 mountlist_scan(getfsstat_callback, &info, MNTSCAN_FORWARD); 966 if (info.sfsp && info.count > info.maxcount) 967 uap->sysmsg_result = info.maxcount; 968 else 969 uap->sysmsg_result = info.count; 970 return (info.error); 971 } 972 973 static int 974 getfsstat_callback(struct mount *mp, void *data) 975 { 976 struct getfsstat_info *info = data; 977 struct statfs *sp; 978 char *freepath; 979 char *fullpath; 980 int error; 981 982 if (info->sfsp && info->count < info->maxcount) { 983 if (info->is_chrooted && !chroot_visible_mnt(mp, info->p)) 984 return(0); 985 sp = &mp->mnt_stat; 986 987 /* 988 * If MNT_NOWAIT or MNT_LAZY is specified, do not 989 * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY 990 * overrides MNT_WAIT. 991 */ 992 if (((info->flags & (MNT_LAZY|MNT_NOWAIT)) == 0 || 993 (info->flags & MNT_WAIT)) && 994 (error = VFS_STATFS(mp, sp, info->td))) { 995 return(0); 996 } 997 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 998 999 error = cache_fullpath(info->p, mp->mnt_ncp, 1000 &fullpath, &freepath); 1001 if (error) { 1002 info->error = error; 1003 return(-1); 1004 } 1005 bzero(sp->f_mntonname, sizeof(sp->f_mntonname)); 1006 strlcpy(sp->f_mntonname, fullpath, sizeof(sp->f_mntonname)); 1007 free(freepath, M_TEMP); 1008 1009 error = copyout(sp, info->sfsp, sizeof(*sp)); 1010 if (error) { 1011 info->error = error; 1012 return (-1); 1013 } 1014 ++info->sfsp; 1015 } 1016 info->count++; 1017 return(0); 1018 } 1019 1020 /* 1021 * fchdir_args(int fd) 1022 * 1023 * Change current working directory to a given file descriptor. 1024 */ 1025 /* ARGSUSED */ 1026 int 1027 fchdir(struct fchdir_args *uap) 1028 { 1029 struct thread *td = curthread; 1030 struct proc *p = td->td_proc; 1031 struct filedesc *fdp = p->p_fd; 1032 struct vnode *vp, *ovp; 1033 struct mount *mp; 1034 struct file *fp; 1035 struct namecache *ncp, *oncp; 1036 struct namecache *nct; 1037 int error; 1038 1039 if ((error = getvnode(fdp, uap->fd, &fp)) != 0) 1040 return (error); 1041 vp = (struct vnode *)fp->f_data; 1042 vref(vp); 1043 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 1044 if (vp->v_type != VDIR || fp->f_ncp == NULL) 1045 error = ENOTDIR; 1046 else 1047 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, td); 1048 if (error) { 1049 vput(vp); 1050 return (error); 1051 } 1052 ncp = cache_hold(fp->f_ncp); 1053 while (!error && (mp = vp->v_mountedhere) != NULL) { 1054 error = nlookup_mp(mp, &nct); 1055 if (error == 0) { 1056 cache_unlock(nct); /* leave ref intact */ 1057 vput(vp); 1058 vp = nct->nc_vp; 1059 error = vget(vp, LK_SHARED, td); 1060 KKASSERT(error == 0); 1061 cache_drop(ncp); 1062 ncp = nct; 1063 } 1064 } 1065 if (error == 0) { 1066 ovp = fdp->fd_cdir; 1067 oncp = fdp->fd_ncdir; 1068 VOP_UNLOCK(vp, 0, td); /* leave ref intact */ 1069 fdp->fd_cdir = vp; 1070 fdp->fd_ncdir = ncp; 1071 cache_drop(oncp); 1072 vrele(ovp); 1073 } else { 1074 cache_drop(ncp); 1075 vput(vp); 1076 } 1077 return (error); 1078 } 1079 1080 int 1081 kern_chdir(struct nlookupdata *nd) 1082 { 1083 struct thread *td = curthread; 1084 struct proc *p = td->td_proc; 1085 struct filedesc *fdp = p->p_fd; 1086 struct vnode *vp, *ovp; 1087 struct namecache *oncp; 1088 int error; 1089 1090 if ((error = nlookup(nd)) != 0) 1091 return (error); 1092 if ((vp = nd->nl_ncp->nc_vp) == NULL) 1093 return (ENOENT); 1094 if ((error = vget(vp, LK_SHARED, td)) != 0) 1095 return (error); 1096 1097 error = checkvp_chdir(vp, td); 1098 VOP_UNLOCK(vp, 0, td); 1099 if (error == 0) { 1100 ovp = fdp->fd_cdir; 1101 oncp = fdp->fd_ncdir; 1102 cache_unlock(nd->nl_ncp); /* leave reference intact */ 1103 fdp->fd_ncdir = nd->nl_ncp; 1104 fdp->fd_cdir = vp; 1105 cache_drop(oncp); 1106 vrele(ovp); 1107 nd->nl_ncp = NULL; 1108 } else { 1109 vrele(vp); 1110 } 1111 return (error); 1112 } 1113 1114 /* 1115 * chdir_args(char *path) 1116 * 1117 * Change current working directory (``.''). 1118 */ 1119 int 1120 chdir(struct chdir_args *uap) 1121 { 1122 struct nlookupdata nd; 1123 int error; 1124 1125 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 1126 if (error == 0) 1127 error = kern_chdir(&nd); 1128 nlookup_done(&nd); 1129 return (error); 1130 } 1131 1132 /* 1133 * Helper function for raised chroot(2) security function: Refuse if 1134 * any filedescriptors are open directories. 1135 */ 1136 static int 1137 chroot_refuse_vdir_fds(fdp) 1138 struct filedesc *fdp; 1139 { 1140 struct vnode *vp; 1141 struct file *fp; 1142 int error; 1143 int fd; 1144 1145 for (fd = 0; fd < fdp->fd_nfiles ; fd++) { 1146 error = getvnode(fdp, fd, &fp); 1147 if (error) 1148 continue; 1149 vp = (struct vnode *)fp->f_data; 1150 if (vp->v_type != VDIR) 1151 continue; 1152 return(EPERM); 1153 } 1154 return (0); 1155 } 1156 1157 /* 1158 * This sysctl determines if we will allow a process to chroot(2) if it 1159 * has a directory open: 1160 * 0: disallowed for all processes. 1161 * 1: allowed for processes that were not already chroot(2)'ed. 1162 * 2: allowed for all processes. 1163 */ 1164 1165 static int chroot_allow_open_directories = 1; 1166 1167 SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW, 1168 &chroot_allow_open_directories, 0, ""); 1169 1170 /* 1171 * chroot to the specified namecache entry. We obtain the vp from the 1172 * namecache data. The passed ncp must be locked and referenced and will 1173 * remain locked and referenced on return. 1174 */ 1175 int 1176 kern_chroot(struct namecache *ncp) 1177 { 1178 struct thread *td = curthread; 1179 struct proc *p = td->td_proc; 1180 struct filedesc *fdp = p->p_fd; 1181 struct vnode *vp; 1182 int error; 1183 1184 /* 1185 * Only root can chroot 1186 */ 1187 if ((error = suser_cred(p->p_ucred, PRISON_ROOT)) != 0) 1188 return (error); 1189 1190 /* 1191 * Disallow open directory descriptors (fchdir() breakouts). 1192 */ 1193 if (chroot_allow_open_directories == 0 || 1194 (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) { 1195 if ((error = chroot_refuse_vdir_fds(fdp)) != 0) 1196 return (error); 1197 } 1198 if ((vp = ncp->nc_vp) == NULL) 1199 return (ENOENT); 1200 1201 if ((error = vget(vp, LK_SHARED, td)) != 0) 1202 return (error); 1203 1204 /* 1205 * Check the validity of vp as a directory to change to and 1206 * associate it with rdir/jdir. 1207 */ 1208 error = checkvp_chdir(vp, td); 1209 VOP_UNLOCK(vp, 0, td); /* leave reference intact */ 1210 if (error == 0) { 1211 vrele(fdp->fd_rdir); 1212 fdp->fd_rdir = vp; /* reference inherited by fd_rdir */ 1213 cache_drop(fdp->fd_nrdir); 1214 fdp->fd_nrdir = cache_hold(ncp); 1215 if (fdp->fd_jdir == NULL) { 1216 fdp->fd_jdir = vp; 1217 vref(fdp->fd_jdir); 1218 fdp->fd_njdir = cache_hold(ncp); 1219 } 1220 } else { 1221 vrele(vp); 1222 } 1223 return (error); 1224 } 1225 1226 /* 1227 * chroot_args(char *path) 1228 * 1229 * Change notion of root (``/'') directory. 1230 */ 1231 /* ARGSUSED */ 1232 int 1233 chroot(struct chroot_args *uap) 1234 { 1235 struct thread *td = curthread; 1236 struct nlookupdata nd; 1237 int error; 1238 1239 KKASSERT(td->td_proc); 1240 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 1241 if (error) { 1242 nlookup_done(&nd); 1243 return(error); 1244 } 1245 error = nlookup(&nd); 1246 if (error == 0) 1247 error = kern_chroot(nd.nl_ncp); 1248 nlookup_done(&nd); 1249 return(error); 1250 } 1251 1252 /* 1253 * Common routine for chroot and chdir. Given a locked, referenced vnode, 1254 * determine whether it is legal to chdir to the vnode. The vnode's state 1255 * is not changed by this call. 1256 */ 1257 int 1258 checkvp_chdir(struct vnode *vp, struct thread *td) 1259 { 1260 int error; 1261 1262 if (vp->v_type != VDIR) 1263 error = ENOTDIR; 1264 else 1265 error = VOP_ACCESS(vp, VEXEC, td->td_proc->p_ucred, td); 1266 return (error); 1267 } 1268 1269 int 1270 kern_open(struct nlookupdata *nd, int oflags, int mode, int *res) 1271 { 1272 struct thread *td = curthread; 1273 struct proc *p = td->td_proc; 1274 struct lwp *lp = td->td_lwp; 1275 struct filedesc *fdp = p->p_fd; 1276 int cmode, flags; 1277 struct file *nfp; 1278 struct file *fp; 1279 struct vnode *vp; 1280 int type, indx, error; 1281 struct flock lf; 1282 1283 if ((oflags & O_ACCMODE) == O_ACCMODE) 1284 return (EINVAL); 1285 flags = FFLAGS(oflags); 1286 error = falloc(p, &nfp, NULL); 1287 if (error) 1288 return (error); 1289 fp = nfp; 1290 cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; 1291 1292 /* 1293 * XXX p_dupfd is a real mess. It allows a device to return a 1294 * file descriptor to be duplicated rather then doing the open 1295 * itself. 1296 */ 1297 lp->lwp_dupfd = -1; 1298 1299 /* 1300 * Call vn_open() to do the lookup and assign the vnode to the 1301 * file pointer. vn_open() does not change the ref count on fp 1302 * and the vnode, on success, will be inherited by the file pointer 1303 * and unlocked. 1304 */ 1305 nd->nl_flags |= NLC_LOCKVP; 1306 error = vn_open(nd, fp, flags, cmode); 1307 nlookup_done(nd); 1308 if (error) { 1309 /* 1310 * handle special fdopen() case. bleh. dupfdopen() is 1311 * responsible for dropping the old contents of ofiles[indx] 1312 * if it succeeds. 1313 * 1314 * Note that if fsetfd() succeeds it will add a ref to fp 1315 * which represents the fd_files[] assignment. We must still 1316 * drop our reference. 1317 */ 1318 if ((error == ENODEV || error == ENXIO) && lp->lwp_dupfd >= 0) { 1319 if (fsetfd(p, fp, &indx) == 0) { 1320 error = dupfdopen(fdp, indx, lp->lwp_dupfd, flags, error); 1321 if (error == 0) { 1322 *res = indx; 1323 fdrop(fp, td); /* our ref */ 1324 return (0); 1325 } 1326 if (fdp->fd_files[indx].fp == fp) { 1327 funsetfd(fdp, indx); 1328 fdrop(fp, td); /* fd_files[] ref */ 1329 } 1330 } 1331 } 1332 fdrop(fp, td); /* our ref */ 1333 if (error == ERESTART) 1334 error = EINTR; 1335 return (error); 1336 } 1337 1338 /* 1339 * ref the vnode for ourselves so it can't be ripped out from under 1340 * is. XXX need an ND flag to request that the vnode be returned 1341 * anyway. 1342 */ 1343 vp = (struct vnode *)fp->f_data; 1344 vref(vp); 1345 if ((error = fsetfd(p, fp, &indx)) != 0) { 1346 fdrop(fp, td); 1347 vrele(vp); 1348 return (error); 1349 } 1350 1351 /* 1352 * If no error occurs the vp will have been assigned to the file 1353 * pointer. 1354 */ 1355 lp->lwp_dupfd = 0; 1356 1357 /* 1358 * There should be 2 references on the file, one from the descriptor 1359 * table, and one for us. 1360 * 1361 * Handle the case where someone closed the file (via its file 1362 * descriptor) while we were blocked. The end result should look 1363 * like opening the file succeeded but it was immediately closed. 1364 */ 1365 if (fp->f_count == 1) { 1366 KASSERT(fdp->fd_files[indx].fp != fp, 1367 ("Open file descriptor lost all refs")); 1368 vrele(vp); 1369 fo_close(fp, td); 1370 fdrop(fp, td); 1371 *res = indx; 1372 return 0; 1373 } 1374 1375 if (flags & (O_EXLOCK | O_SHLOCK)) { 1376 lf.l_whence = SEEK_SET; 1377 lf.l_start = 0; 1378 lf.l_len = 0; 1379 if (flags & O_EXLOCK) 1380 lf.l_type = F_WRLCK; 1381 else 1382 lf.l_type = F_RDLCK; 1383 type = F_FLOCK; 1384 if ((flags & FNONBLOCK) == 0) 1385 type |= F_WAIT; 1386 1387 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) { 1388 /* 1389 * lock request failed. Normally close the descriptor 1390 * but handle the case where someone might have dup()d 1391 * it when we weren't looking. One reference is 1392 * owned by the descriptor array, the other by us. 1393 */ 1394 vrele(vp); 1395 if (fdp->fd_files[indx].fp == fp) { 1396 funsetfd(fdp, indx); 1397 fdrop(fp, td); 1398 } 1399 fdrop(fp, td); 1400 return (error); 1401 } 1402 fp->f_flag |= FHASLOCK; 1403 } 1404 /* assert that vn_open created a backing object if one is needed */ 1405 KASSERT(!vn_canvmio(vp) || VOP_GETVOBJECT(vp, NULL) == 0, 1406 ("open: vmio vnode has no backing object after vn_open")); 1407 1408 vrele(vp); 1409 1410 /* 1411 * release our private reference, leaving the one associated with the 1412 * descriptor table intact. 1413 */ 1414 fdrop(fp, td); 1415 *res = indx; 1416 return (0); 1417 } 1418 1419 /* 1420 * open_args(char *path, int flags, int mode) 1421 * 1422 * Check permissions, allocate an open file structure, 1423 * and call the device open routine if any. 1424 */ 1425 int 1426 open(struct open_args *uap) 1427 { 1428 struct nlookupdata nd; 1429 int error; 1430 1431 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 1432 if (error == 0) { 1433 error = kern_open(&nd, uap->flags, 1434 uap->mode, &uap->sysmsg_result); 1435 } 1436 nlookup_done(&nd); 1437 return (error); 1438 } 1439 1440 int 1441 kern_mknod(struct nlookupdata *nd, int mode, int dev) 1442 { 1443 struct namecache *ncp; 1444 struct thread *td = curthread; 1445 struct proc *p = td->td_proc; 1446 struct vnode *vp; 1447 struct vattr vattr; 1448 int error; 1449 int whiteout = 0; 1450 1451 KKASSERT(p); 1452 1453 switch (mode & S_IFMT) { 1454 case S_IFCHR: 1455 case S_IFBLK: 1456 error = suser(td); 1457 break; 1458 default: 1459 error = suser_cred(p->p_ucred, PRISON_ROOT); 1460 break; 1461 } 1462 if (error) 1463 return (error); 1464 1465 bwillwrite(); 1466 nd->nl_flags |= NLC_CREATE; 1467 if ((error = nlookup(nd)) != 0) 1468 return (error); 1469 ncp = nd->nl_ncp; 1470 if (ncp->nc_vp) 1471 return (EEXIST); 1472 1473 VATTR_NULL(&vattr); 1474 vattr.va_mode = (mode & ALLPERMS) &~ p->p_fd->fd_cmask; 1475 vattr.va_rdev = dev; 1476 whiteout = 0; 1477 1478 switch (mode & S_IFMT) { 1479 case S_IFMT: /* used by badsect to flag bad sectors */ 1480 vattr.va_type = VBAD; 1481 break; 1482 case S_IFCHR: 1483 vattr.va_type = VCHR; 1484 break; 1485 case S_IFBLK: 1486 vattr.va_type = VBLK; 1487 break; 1488 case S_IFWHT: 1489 whiteout = 1; 1490 break; 1491 default: 1492 error = EINVAL; 1493 break; 1494 } 1495 if (error == 0) { 1496 if (whiteout) { 1497 error = VOP_NWHITEOUT(ncp, nd->nl_cred, NAMEI_CREATE); 1498 } else { 1499 vp = NULL; 1500 error = VOP_NMKNOD(ncp, &vp, nd->nl_cred, &vattr); 1501 if (error == 0) 1502 vput(vp); 1503 } 1504 } 1505 return (error); 1506 } 1507 1508 /* 1509 * mknod_args(char *path, int mode, int dev) 1510 * 1511 * Create a special file. 1512 */ 1513 int 1514 mknod(struct mknod_args *uap) 1515 { 1516 struct nlookupdata nd; 1517 int error; 1518 1519 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0); 1520 if (error == 0) 1521 error = kern_mknod(&nd, uap->mode, uap->dev); 1522 nlookup_done(&nd); 1523 return (error); 1524 } 1525 1526 int 1527 kern_mkfifo(struct nlookupdata *nd, int mode) 1528 { 1529 struct namecache *ncp; 1530 struct thread *td = curthread; 1531 struct proc *p = td->td_proc; 1532 struct vattr vattr; 1533 struct vnode *vp; 1534 int error; 1535 1536 bwillwrite(); 1537 1538 nd->nl_flags |= NLC_CREATE; 1539 if ((error = nlookup(nd)) != 0) 1540 return (error); 1541 ncp = nd->nl_ncp; 1542 if (ncp->nc_vp) 1543 return (EEXIST); 1544 1545 VATTR_NULL(&vattr); 1546 vattr.va_type = VFIFO; 1547 vattr.va_mode = (mode & ALLPERMS) &~ p->p_fd->fd_cmask; 1548 vp = NULL; 1549 error = VOP_NMKNOD(ncp, &vp, nd->nl_cred, &vattr); 1550 if (error == 0) 1551 vput(vp); 1552 return (error); 1553 } 1554 1555 /* 1556 * mkfifo_args(char *path, int mode) 1557 * 1558 * Create a named pipe. 1559 */ 1560 int 1561 mkfifo(struct mkfifo_args *uap) 1562 { 1563 struct nlookupdata nd; 1564 int error; 1565 1566 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0); 1567 if (error == 0) 1568 error = kern_mkfifo(&nd, uap->mode); 1569 nlookup_done(&nd); 1570 return (error); 1571 } 1572 1573 static int hardlink_check_uid = 0; 1574 SYSCTL_INT(_kern, OID_AUTO, hardlink_check_uid, CTLFLAG_RW, 1575 &hardlink_check_uid, 0, 1576 "Unprivileged processes cannot create hard links to files owned by other " 1577 "users"); 1578 static int hardlink_check_gid = 0; 1579 SYSCTL_INT(_kern, OID_AUTO, hardlink_check_gid, CTLFLAG_RW, 1580 &hardlink_check_gid, 0, 1581 "Unprivileged processes cannot create hard links to files owned by other " 1582 "groups"); 1583 1584 static int 1585 can_hardlink(struct vnode *vp, struct thread *td, struct ucred *cred) 1586 { 1587 struct vattr va; 1588 int error; 1589 1590 /* 1591 * Shortcut if disabled 1592 */ 1593 if (hardlink_check_uid == 0 && hardlink_check_gid == 0) 1594 return (0); 1595 1596 /* 1597 * root cred can always hardlink 1598 */ 1599 if (suser_cred(cred, PRISON_ROOT) == 0) 1600 return (0); 1601 1602 /* 1603 * Otherwise only if the originating file is owned by the 1604 * same user or group. Note that any group is allowed if 1605 * the file is owned by the caller. 1606 */ 1607 error = VOP_GETATTR(vp, &va, td); 1608 if (error != 0) 1609 return (error); 1610 1611 if (hardlink_check_uid) { 1612 if (cred->cr_uid != va.va_uid) 1613 return (EPERM); 1614 } 1615 1616 if (hardlink_check_gid) { 1617 if (cred->cr_uid != va.va_uid && !groupmember(va.va_gid, cred)) 1618 return (EPERM); 1619 } 1620 1621 return (0); 1622 } 1623 1624 int 1625 kern_link(struct nlookupdata *nd, struct nlookupdata *linknd) 1626 { 1627 struct thread *td = curthread; 1628 struct vnode *vp; 1629 int error; 1630 1631 /* 1632 * Lookup the source and obtained a locked vnode. 1633 * 1634 * XXX relookup on vget failure / race ? 1635 */ 1636 bwillwrite(); 1637 if ((error = nlookup(nd)) != 0) 1638 return (error); 1639 vp = nd->nl_ncp->nc_vp; 1640 KKASSERT(vp != NULL); 1641 if (vp->v_type == VDIR) 1642 return (EPERM); /* POSIX */ 1643 if ((error = vget(vp, LK_EXCLUSIVE, td)) != 0) 1644 return (error); 1645 1646 /* 1647 * Unlock the source so we can lookup the target without deadlocking 1648 * (XXX vp is locked already, possible other deadlock?). The target 1649 * must not exist. 1650 */ 1651 KKASSERT(nd->nl_flags & NLC_NCPISLOCKED); 1652 nd->nl_flags &= ~NLC_NCPISLOCKED; 1653 cache_unlock(nd->nl_ncp); 1654 1655 linknd->nl_flags |= NLC_CREATE; 1656 if ((error = nlookup(linknd)) != 0) { 1657 vput(vp); 1658 return (error); 1659 } 1660 if (linknd->nl_ncp->nc_vp) { 1661 vput(vp); 1662 return (EEXIST); 1663 } 1664 1665 /* 1666 * Finally run the new API VOP. 1667 */ 1668 error = can_hardlink(vp, td, td->td_proc->p_ucred); 1669 if (error == 0) 1670 error = VOP_NLINK(linknd->nl_ncp, vp, linknd->nl_cred); 1671 vput(vp); 1672 return (error); 1673 } 1674 1675 /* 1676 * link_args(char *path, char *link) 1677 * 1678 * Make a hard file link. 1679 */ 1680 int 1681 link(struct link_args *uap) 1682 { 1683 struct nlookupdata nd, linknd; 1684 int error; 1685 1686 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 1687 if (error == 0) { 1688 error = nlookup_init(&linknd, uap->link, UIO_USERSPACE, 0); 1689 if (error == 0) 1690 error = kern_link(&nd, &linknd); 1691 nlookup_done(&linknd); 1692 } 1693 nlookup_done(&nd); 1694 return (error); 1695 } 1696 1697 int 1698 kern_symlink(struct nlookupdata *nd, char *path, int mode) 1699 { 1700 struct namecache *ncp; 1701 struct vattr vattr; 1702 struct vnode *vp; 1703 int error; 1704 1705 bwillwrite(); 1706 nd->nl_flags |= NLC_CREATE; 1707 if ((error = nlookup(nd)) != 0) 1708 return (error); 1709 ncp = nd->nl_ncp; 1710 if (ncp->nc_vp) 1711 return (EEXIST); 1712 1713 VATTR_NULL(&vattr); 1714 vattr.va_mode = mode; 1715 error = VOP_NSYMLINK(ncp, &vp, nd->nl_cred, &vattr, path); 1716 if (error == 0) 1717 vput(vp); 1718 return (error); 1719 } 1720 1721 /* 1722 * symlink(char *path, char *link) 1723 * 1724 * Make a symbolic link. 1725 */ 1726 int 1727 symlink(struct symlink_args *uap) 1728 { 1729 struct thread *td = curthread; 1730 struct nlookupdata nd; 1731 char *path; 1732 int error; 1733 int mode; 1734 1735 path = zalloc(namei_zone); 1736 error = copyinstr(uap->path, path, MAXPATHLEN, NULL); 1737 if (error == 0) { 1738 error = nlookup_init(&nd, uap->link, UIO_USERSPACE, 0); 1739 if (error == 0) { 1740 mode = ACCESSPERMS & ~td->td_proc->p_fd->fd_cmask; 1741 error = kern_symlink(&nd, path, mode); 1742 } 1743 nlookup_done(&nd); 1744 } 1745 zfree(namei_zone, path); 1746 return (error); 1747 } 1748 1749 /* 1750 * undelete_args(char *path) 1751 * 1752 * Delete a whiteout from the filesystem. 1753 */ 1754 /* ARGSUSED */ 1755 int 1756 undelete(struct undelete_args *uap) 1757 { 1758 struct nlookupdata nd; 1759 int error; 1760 1761 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0); 1762 bwillwrite(); 1763 nd.nl_flags |= NLC_DELETE; 1764 if (error == 0) 1765 error = nlookup(&nd); 1766 if (error == 0) 1767 error = VOP_NWHITEOUT(nd.nl_ncp, nd.nl_cred, NAMEI_DELETE); 1768 nlookup_done(&nd); 1769 return (error); 1770 } 1771 1772 int 1773 kern_unlink(struct nlookupdata *nd) 1774 { 1775 struct namecache *ncp; 1776 int error; 1777 1778 bwillwrite(); 1779 nd->nl_flags |= NLC_DELETE; 1780 if ((error = nlookup(nd)) != 0) 1781 return (error); 1782 ncp = nd->nl_ncp; 1783 error = VOP_NREMOVE(ncp, nd->nl_cred); 1784 return (error); 1785 } 1786 1787 /* 1788 * unlink_args(char *path) 1789 * 1790 * Delete a name from the filesystem. 1791 */ 1792 int 1793 unlink(struct unlink_args *uap) 1794 { 1795 struct nlookupdata nd; 1796 int error; 1797 1798 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0); 1799 if (error == 0) 1800 error = kern_unlink(&nd); 1801 nlookup_done(&nd); 1802 return (error); 1803 } 1804 1805 int 1806 kern_lseek(int fd, off_t offset, int whence, off_t *res) 1807 { 1808 struct thread *td = curthread; 1809 struct proc *p = td->td_proc; 1810 struct filedesc *fdp = p->p_fd; 1811 struct file *fp; 1812 struct vattr vattr; 1813 int error; 1814 1815 if ((u_int)fd >= fdp->fd_nfiles || 1816 (fp = fdp->fd_files[fd].fp) == NULL) 1817 return (EBADF); 1818 if (fp->f_type != DTYPE_VNODE) 1819 return (ESPIPE); 1820 switch (whence) { 1821 case L_INCR: 1822 fp->f_offset += offset; 1823 break; 1824 case L_XTND: 1825 error=VOP_GETATTR((struct vnode *)fp->f_data, &vattr, td); 1826 if (error) 1827 return (error); 1828 fp->f_offset = offset + vattr.va_size; 1829 break; 1830 case L_SET: 1831 fp->f_offset = offset; 1832 break; 1833 default: 1834 return (EINVAL); 1835 } 1836 *res = fp->f_offset; 1837 return (0); 1838 } 1839 1840 /* 1841 * lseek_args(int fd, int pad, off_t offset, int whence) 1842 * 1843 * Reposition read/write file offset. 1844 */ 1845 int 1846 lseek(struct lseek_args *uap) 1847 { 1848 int error; 1849 1850 error = kern_lseek(uap->fd, uap->offset, uap->whence, 1851 &uap->sysmsg_offset); 1852 1853 return (error); 1854 } 1855 1856 int 1857 kern_access(struct nlookupdata *nd, int aflags) 1858 { 1859 struct thread *td = curthread; 1860 struct vnode *vp; 1861 int error, flags; 1862 1863 if ((error = nlookup(nd)) != 0) 1864 return (error); 1865 retry: 1866 error = cache_vget(nd->nl_ncp, nd->nl_cred, LK_EXCLUSIVE, &vp); 1867 if (error) 1868 return (error); 1869 1870 /* Flags == 0 means only check for existence. */ 1871 if (aflags) { 1872 flags = 0; 1873 if (aflags & R_OK) 1874 flags |= VREAD; 1875 if (aflags & W_OK) 1876 flags |= VWRITE; 1877 if (aflags & X_OK) 1878 flags |= VEXEC; 1879 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) 1880 error = VOP_ACCESS(vp, flags, nd->nl_cred, td); 1881 1882 /* 1883 * If the file handle is stale we have to re-resolve the 1884 * entry. This is a hack at the moment. 1885 */ 1886 if (error == ESTALE) { 1887 cache_setunresolved(nd->nl_ncp); 1888 error = cache_resolve(nd->nl_ncp, nd->nl_cred); 1889 if (error == 0) { 1890 vput(vp); 1891 vp = NULL; 1892 goto retry; 1893 } 1894 } 1895 } 1896 vput(vp); 1897 return (error); 1898 } 1899 1900 /* 1901 * access_args(char *path, int flags) 1902 * 1903 * Check access permissions. 1904 */ 1905 int 1906 access(struct access_args *uap) 1907 { 1908 struct nlookupdata nd; 1909 int error; 1910 1911 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 1912 if (error == 0) 1913 error = kern_access(&nd, uap->flags); 1914 nlookup_done(&nd); 1915 return (error); 1916 } 1917 1918 int 1919 kern_stat(struct nlookupdata *nd, struct stat *st) 1920 { 1921 int error; 1922 struct vnode *vp; 1923 thread_t td; 1924 1925 if ((error = nlookup(nd)) != 0) 1926 return (error); 1927 again: 1928 if ((vp = nd->nl_ncp->nc_vp) == NULL) 1929 return (ENOENT); 1930 1931 td = curthread; 1932 if ((error = vget(vp, LK_SHARED, td)) != 0) 1933 return (error); 1934 error = vn_stat(vp, st, td); 1935 1936 /* 1937 * If the file handle is stale we have to re-resolve the entry. This 1938 * is a hack at the moment. 1939 */ 1940 if (error == ESTALE) { 1941 cache_setunresolved(nd->nl_ncp); 1942 error = cache_resolve(nd->nl_ncp, nd->nl_cred); 1943 if (error == 0) { 1944 vput(vp); 1945 goto again; 1946 } 1947 } 1948 vput(vp); 1949 return (error); 1950 } 1951 1952 /* 1953 * stat_args(char *path, struct stat *ub) 1954 * 1955 * Get file status; this version follows links. 1956 */ 1957 int 1958 stat(struct stat_args *uap) 1959 { 1960 struct nlookupdata nd; 1961 struct stat st; 1962 int error; 1963 1964 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 1965 if (error == 0) { 1966 error = kern_stat(&nd, &st); 1967 if (error == 0) 1968 error = copyout(&st, uap->ub, sizeof(*uap->ub)); 1969 } 1970 nlookup_done(&nd); 1971 return (error); 1972 } 1973 1974 /* 1975 * lstat_args(char *path, struct stat *ub) 1976 * 1977 * Get file status; this version does not follow links. 1978 */ 1979 int 1980 lstat(struct lstat_args *uap) 1981 { 1982 struct nlookupdata nd; 1983 struct stat st; 1984 int error; 1985 1986 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0); 1987 if (error == 0) { 1988 error = kern_stat(&nd, &st); 1989 if (error == 0) 1990 error = copyout(&st, uap->ub, sizeof(*uap->ub)); 1991 } 1992 nlookup_done(&nd); 1993 return (error); 1994 } 1995 1996 /* 1997 * pathconf_Args(char *path, int name) 1998 * 1999 * Get configurable pathname variables. 2000 */ 2001 /* ARGSUSED */ 2002 int 2003 pathconf(struct pathconf_args *uap) 2004 { 2005 struct nlookupdata nd; 2006 struct vnode *vp; 2007 int error; 2008 2009 vp = NULL; 2010 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 2011 if (error == 0) 2012 error = nlookup(&nd); 2013 if (error == 0) 2014 error = cache_vget(nd.nl_ncp, nd.nl_cred, LK_EXCLUSIVE, &vp); 2015 nlookup_done(&nd); 2016 if (error == 0) { 2017 error = VOP_PATHCONF(vp, uap->name, uap->sysmsg_fds); 2018 vput(vp); 2019 } 2020 return (error); 2021 } 2022 2023 /* 2024 * XXX: daver 2025 * kern_readlink isn't properly split yet. There is a copyin burried 2026 * in VOP_READLINK(). 2027 */ 2028 int 2029 kern_readlink(struct nlookupdata *nd, char *buf, int count, int *res) 2030 { 2031 struct thread *td = curthread; 2032 struct proc *p = td->td_proc; 2033 struct vnode *vp; 2034 struct iovec aiov; 2035 struct uio auio; 2036 int error; 2037 2038 if ((error = nlookup(nd)) != 0) 2039 return (error); 2040 error = cache_vget(nd->nl_ncp, nd->nl_cred, LK_EXCLUSIVE, &vp); 2041 if (error) 2042 return (error); 2043 if (vp->v_type != VLNK) { 2044 error = EINVAL; 2045 } else { 2046 aiov.iov_base = buf; 2047 aiov.iov_len = count; 2048 auio.uio_iov = &aiov; 2049 auio.uio_iovcnt = 1; 2050 auio.uio_offset = 0; 2051 auio.uio_rw = UIO_READ; 2052 auio.uio_segflg = UIO_USERSPACE; 2053 auio.uio_td = td; 2054 auio.uio_resid = count; 2055 error = VOP_READLINK(vp, &auio, p->p_ucred); 2056 } 2057 vput(vp); 2058 *res = count - auio.uio_resid; 2059 return (error); 2060 } 2061 2062 /* 2063 * readlink_args(char *path, char *buf, int count) 2064 * 2065 * Return target name of a symbolic link. 2066 */ 2067 int 2068 readlink(struct readlink_args *uap) 2069 { 2070 struct nlookupdata nd; 2071 int error; 2072 2073 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0); 2074 if (error == 0) { 2075 error = kern_readlink(&nd, uap->buf, uap->count, 2076 &uap->sysmsg_result); 2077 } 2078 nlookup_done(&nd); 2079 return (error); 2080 } 2081 2082 static int 2083 setfflags(struct vnode *vp, int flags) 2084 { 2085 struct thread *td = curthread; 2086 struct proc *p = td->td_proc; 2087 int error; 2088 struct vattr vattr; 2089 2090 /* 2091 * Prevent non-root users from setting flags on devices. When 2092 * a device is reused, users can retain ownership of the device 2093 * if they are allowed to set flags and programs assume that 2094 * chown can't fail when done as root. 2095 */ 2096 if ((vp->v_type == VCHR || vp->v_type == VBLK) && 2097 ((error = suser_cred(p->p_ucred, PRISON_ROOT)) != 0)) 2098 return (error); 2099 2100 /* 2101 * note: vget is required for any operation that might mod the vnode 2102 * so VINACTIVE is properly cleared. 2103 */ 2104 VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE); 2105 if ((error = vget(vp, LK_EXCLUSIVE, td)) == 0) { 2106 VATTR_NULL(&vattr); 2107 vattr.va_flags = flags; 2108 error = VOP_SETATTR(vp, &vattr, p->p_ucred, td); 2109 vput(vp); 2110 } 2111 return (error); 2112 } 2113 2114 /* 2115 * chflags(char *path, int flags) 2116 * 2117 * Change flags of a file given a path name. 2118 */ 2119 /* ARGSUSED */ 2120 int 2121 chflags(struct chflags_args *uap) 2122 { 2123 struct nlookupdata nd; 2124 struct vnode *vp; 2125 int error; 2126 2127 vp = NULL; 2128 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 2129 /* XXX Add NLC flag indicating modifying operation? */ 2130 if (error == 0) 2131 error = nlookup(&nd); 2132 if (error == 0) 2133 error = cache_vref(nd.nl_ncp, nd.nl_cred, &vp); 2134 nlookup_done(&nd); 2135 if (error == 0) { 2136 error = setfflags(vp, uap->flags); 2137 vrele(vp); 2138 } 2139 return (error); 2140 } 2141 2142 /* 2143 * fchflags_args(int fd, int flags) 2144 * 2145 * Change flags of a file given a file descriptor. 2146 */ 2147 /* ARGSUSED */ 2148 int 2149 fchflags(struct fchflags_args *uap) 2150 { 2151 struct thread *td = curthread; 2152 struct proc *p = td->td_proc; 2153 struct file *fp; 2154 int error; 2155 2156 if ((error = getvnode(p->p_fd, uap->fd, &fp)) != 0) 2157 return (error); 2158 return setfflags((struct vnode *) fp->f_data, uap->flags); 2159 } 2160 2161 static int 2162 setfmode(struct vnode *vp, int mode) 2163 { 2164 struct thread *td = curthread; 2165 struct proc *p = td->td_proc; 2166 int error; 2167 struct vattr vattr; 2168 2169 /* 2170 * note: vget is required for any operation that might mod the vnode 2171 * so VINACTIVE is properly cleared. 2172 */ 2173 VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE); 2174 if ((error = vget(vp, LK_EXCLUSIVE, td)) == 0) { 2175 VATTR_NULL(&vattr); 2176 vattr.va_mode = mode & ALLPERMS; 2177 error = VOP_SETATTR(vp, &vattr, p->p_ucred, td); 2178 vput(vp); 2179 } 2180 return error; 2181 } 2182 2183 int 2184 kern_chmod(struct nlookupdata *nd, int mode) 2185 { 2186 struct vnode *vp; 2187 int error; 2188 2189 /* XXX Add NLC flag indicating modifying operation? */ 2190 if ((error = nlookup(nd)) != 0) 2191 return (error); 2192 if ((error = cache_vref(nd->nl_ncp, nd->nl_cred, &vp)) != 0) 2193 return (error); 2194 error = setfmode(vp, mode); 2195 vrele(vp); 2196 return (error); 2197 } 2198 2199 /* 2200 * chmod_args(char *path, int mode) 2201 * 2202 * Change mode of a file given path name. 2203 */ 2204 /* ARGSUSED */ 2205 int 2206 chmod(struct chmod_args *uap) 2207 { 2208 struct nlookupdata nd; 2209 int error; 2210 2211 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 2212 if (error == 0) 2213 error = kern_chmod(&nd, uap->mode); 2214 nlookup_done(&nd); 2215 return (error); 2216 } 2217 2218 /* 2219 * lchmod_args(char *path, int mode) 2220 * 2221 * Change mode of a file given path name (don't follow links.) 2222 */ 2223 /* ARGSUSED */ 2224 int 2225 lchmod(struct lchmod_args *uap) 2226 { 2227 struct nlookupdata nd; 2228 int error; 2229 2230 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0); 2231 if (error == 0) 2232 error = kern_chmod(&nd, uap->mode); 2233 nlookup_done(&nd); 2234 return (error); 2235 } 2236 2237 /* 2238 * fchmod_args(int fd, int mode) 2239 * 2240 * Change mode of a file given a file descriptor. 2241 */ 2242 /* ARGSUSED */ 2243 int 2244 fchmod(struct fchmod_args *uap) 2245 { 2246 struct thread *td = curthread; 2247 struct proc *p = td->td_proc; 2248 struct file *fp; 2249 int error; 2250 2251 if ((error = getvnode(p->p_fd, uap->fd, &fp)) != 0) 2252 return (error); 2253 return setfmode((struct vnode *)fp->f_data, uap->mode); 2254 } 2255 2256 static int 2257 setfown(struct vnode *vp, uid_t uid, gid_t gid) 2258 { 2259 struct thread *td = curthread; 2260 struct proc *p = td->td_proc; 2261 int error; 2262 struct vattr vattr; 2263 2264 /* 2265 * note: vget is required for any operation that might mod the vnode 2266 * so VINACTIVE is properly cleared. 2267 */ 2268 VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE); 2269 if ((error = vget(vp, LK_EXCLUSIVE, td)) == 0) { 2270 VATTR_NULL(&vattr); 2271 vattr.va_uid = uid; 2272 vattr.va_gid = gid; 2273 error = VOP_SETATTR(vp, &vattr, p->p_ucred, td); 2274 vput(vp); 2275 } 2276 return error; 2277 } 2278 2279 int 2280 kern_chown(struct nlookupdata *nd, int uid, int gid) 2281 { 2282 struct vnode *vp; 2283 int error; 2284 2285 /* XXX Add NLC flag indicating modifying operation? */ 2286 if ((error = nlookup(nd)) != 0) 2287 return (error); 2288 if ((error = cache_vref(nd->nl_ncp, nd->nl_cred, &vp)) != 0) 2289 return (error); 2290 error = setfown(vp, uid, gid); 2291 vrele(vp); 2292 return (error); 2293 } 2294 2295 /* 2296 * chown(char *path, int uid, int gid) 2297 * 2298 * Set ownership given a path name. 2299 */ 2300 int 2301 chown(struct chown_args *uap) 2302 { 2303 struct nlookupdata nd; 2304 int error; 2305 2306 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 2307 if (error == 0) 2308 error = kern_chown(&nd, uap->uid, uap->gid); 2309 nlookup_done(&nd); 2310 return (error); 2311 } 2312 2313 /* 2314 * lchown_args(char *path, int uid, int gid) 2315 * 2316 * Set ownership given a path name, do not cross symlinks. 2317 */ 2318 int 2319 lchown(struct lchown_args *uap) 2320 { 2321 struct nlookupdata nd; 2322 int error; 2323 2324 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0); 2325 if (error == 0) 2326 error = kern_chown(&nd, uap->uid, uap->gid); 2327 nlookup_done(&nd); 2328 return (error); 2329 } 2330 2331 /* 2332 * fchown_args(int fd, int uid, int gid) 2333 * 2334 * Set ownership given a file descriptor. 2335 */ 2336 /* ARGSUSED */ 2337 int 2338 fchown(struct fchown_args *uap) 2339 { 2340 struct thread *td = curthread; 2341 struct proc *p = td->td_proc; 2342 struct file *fp; 2343 int error; 2344 2345 if ((error = getvnode(p->p_fd, uap->fd, &fp)) != 0) 2346 return (error); 2347 return setfown((struct vnode *)fp->f_data, 2348 uap->uid, uap->gid); 2349 } 2350 2351 static int 2352 getutimes(const struct timeval *tvp, struct timespec *tsp) 2353 { 2354 struct timeval tv[2]; 2355 2356 if (tvp == NULL) { 2357 microtime(&tv[0]); 2358 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]); 2359 tsp[1] = tsp[0]; 2360 } else { 2361 TIMEVAL_TO_TIMESPEC(&tvp[0], &tsp[0]); 2362 TIMEVAL_TO_TIMESPEC(&tvp[1], &tsp[1]); 2363 } 2364 return 0; 2365 } 2366 2367 static int 2368 setutimes(struct vnode *vp, const struct timespec *ts, int nullflag) 2369 { 2370 struct thread *td = curthread; 2371 struct proc *p = td->td_proc; 2372 int error; 2373 struct vattr vattr; 2374 2375 /* 2376 * note: vget is required for any operation that might mod the vnode 2377 * so VINACTIVE is properly cleared. 2378 */ 2379 VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE); 2380 if ((error = vget(vp, LK_EXCLUSIVE, td)) == 0) { 2381 VATTR_NULL(&vattr); 2382 vattr.va_atime = ts[0]; 2383 vattr.va_mtime = ts[1]; 2384 if (nullflag) 2385 vattr.va_vaflags |= VA_UTIMES_NULL; 2386 error = VOP_SETATTR(vp, &vattr, p->p_ucred, td); 2387 vput(vp); 2388 } 2389 return error; 2390 } 2391 2392 int 2393 kern_utimes(struct nlookupdata *nd, struct timeval *tptr) 2394 { 2395 struct timespec ts[2]; 2396 struct vnode *vp; 2397 int error; 2398 2399 if ((error = getutimes(tptr, ts)) != 0) 2400 return (error); 2401 /* XXX Add NLC flag indicating modifying operation? */ 2402 if ((error = nlookup(nd)) != 0) 2403 return (error); 2404 if ((error = cache_vref(nd->nl_ncp, nd->nl_cred, &vp)) != 0) 2405 return (error); 2406 error = setutimes(vp, ts, tptr == NULL); 2407 vrele(vp); 2408 return (error); 2409 } 2410 2411 /* 2412 * utimes_args(char *path, struct timeval *tptr) 2413 * 2414 * Set the access and modification times of a file. 2415 */ 2416 int 2417 utimes(struct utimes_args *uap) 2418 { 2419 struct timeval tv[2]; 2420 struct nlookupdata nd; 2421 int error; 2422 2423 if (uap->tptr) { 2424 error = copyin(uap->tptr, tv, sizeof(tv)); 2425 if (error) 2426 return (error); 2427 } 2428 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 2429 if (error == 0) 2430 error = kern_utimes(&nd, uap->tptr ? tv : NULL); 2431 nlookup_done(&nd); 2432 return (error); 2433 } 2434 2435 /* 2436 * lutimes_args(char *path, struct timeval *tptr) 2437 * 2438 * Set the access and modification times of a file. 2439 */ 2440 int 2441 lutimes(struct lutimes_args *uap) 2442 { 2443 struct timeval tv[2]; 2444 struct nlookupdata nd; 2445 int error; 2446 2447 if (uap->tptr) { 2448 error = copyin(uap->tptr, tv, sizeof(tv)); 2449 if (error) 2450 return (error); 2451 } 2452 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0); 2453 if (error == 0) 2454 error = kern_utimes(&nd, uap->tptr ? tv : NULL); 2455 nlookup_done(&nd); 2456 return (error); 2457 } 2458 2459 int 2460 kern_futimes(int fd, struct timeval *tptr) 2461 { 2462 struct thread *td = curthread; 2463 struct proc *p = td->td_proc; 2464 struct timespec ts[2]; 2465 struct file *fp; 2466 int error; 2467 2468 error = getutimes(tptr, ts); 2469 if (error) 2470 return (error); 2471 error = getvnode(p->p_fd, fd, &fp); 2472 if (error) 2473 return (error); 2474 error = setutimes((struct vnode *)fp->f_data, ts, tptr == NULL); 2475 return (error); 2476 } 2477 2478 /* 2479 * futimes_args(int fd, struct timeval *tptr) 2480 * 2481 * Set the access and modification times of a file. 2482 */ 2483 int 2484 futimes(struct futimes_args *uap) 2485 { 2486 struct timeval tv[2]; 2487 int error; 2488 2489 if (uap->tptr) { 2490 error = copyin(uap->tptr, tv, sizeof(tv)); 2491 if (error) 2492 return (error); 2493 } 2494 2495 error = kern_futimes(uap->fd, uap->tptr ? tv : NULL); 2496 2497 return (error); 2498 } 2499 2500 int 2501 kern_truncate(struct nlookupdata *nd, off_t length) 2502 { 2503 struct vnode *vp; 2504 struct vattr vattr; 2505 int error; 2506 2507 if (length < 0) 2508 return(EINVAL); 2509 /* XXX Add NLC flag indicating modifying operation? */ 2510 if ((error = nlookup(nd)) != 0) 2511 return (error); 2512 if ((error = cache_vref(nd->nl_ncp, nd->nl_cred, &vp)) != 0) 2513 return (error); 2514 VOP_LEASE(vp, nd->nl_td, nd->nl_cred, LEASE_WRITE); 2515 if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, nd->nl_td)) != 0) { 2516 vrele(vp); 2517 return (error); 2518 } 2519 if (vp->v_type == VDIR) { 2520 error = EISDIR; 2521 } else if ((error = vn_writechk(vp)) == 0 && 2522 (error = VOP_ACCESS(vp, VWRITE, nd->nl_cred, nd->nl_td)) == 0) { 2523 VATTR_NULL(&vattr); 2524 vattr.va_size = length; 2525 error = VOP_SETATTR(vp, &vattr, nd->nl_cred, nd->nl_td); 2526 } 2527 vput(vp); 2528 return (error); 2529 } 2530 2531 /* 2532 * truncate(char *path, int pad, off_t length) 2533 * 2534 * Truncate a file given its path name. 2535 */ 2536 int 2537 truncate(struct truncate_args *uap) 2538 { 2539 struct nlookupdata nd; 2540 int error; 2541 2542 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 2543 if (error == 0) 2544 error = kern_truncate(&nd, uap->length); 2545 nlookup_done(&nd); 2546 return error; 2547 } 2548 2549 int 2550 kern_ftruncate(int fd, off_t length) 2551 { 2552 struct thread *td = curthread; 2553 struct proc *p = td->td_proc; 2554 struct vattr vattr; 2555 struct vnode *vp; 2556 struct file *fp; 2557 int error; 2558 2559 if (length < 0) 2560 return(EINVAL); 2561 if ((error = getvnode(p->p_fd, fd, &fp)) != 0) 2562 return (error); 2563 if ((fp->f_flag & FWRITE) == 0) 2564 return (EINVAL); 2565 vp = (struct vnode *)fp->f_data; 2566 VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE); 2567 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2568 if (vp->v_type == VDIR) 2569 error = EISDIR; 2570 else if ((error = vn_writechk(vp)) == 0) { 2571 VATTR_NULL(&vattr); 2572 vattr.va_size = length; 2573 error = VOP_SETATTR(vp, &vattr, fp->f_cred, td); 2574 } 2575 VOP_UNLOCK(vp, 0, td); 2576 return (error); 2577 } 2578 2579 /* 2580 * ftruncate_args(int fd, int pad, off_t length) 2581 * 2582 * Truncate a file given a file descriptor. 2583 */ 2584 int 2585 ftruncate(struct ftruncate_args *uap) 2586 { 2587 int error; 2588 2589 error = kern_ftruncate(uap->fd, uap->length); 2590 2591 return (error); 2592 } 2593 2594 /* 2595 * fsync(int fd) 2596 * 2597 * Sync an open file. 2598 */ 2599 /* ARGSUSED */ 2600 int 2601 fsync(struct fsync_args *uap) 2602 { 2603 struct thread *td = curthread; 2604 struct proc *p = td->td_proc; 2605 struct vnode *vp; 2606 struct file *fp; 2607 vm_object_t obj; 2608 int error; 2609 2610 if ((error = getvnode(p->p_fd, uap->fd, &fp)) != 0) 2611 return (error); 2612 vp = (struct vnode *)fp->f_data; 2613 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2614 if (VOP_GETVOBJECT(vp, &obj) == 0) 2615 vm_object_page_clean(obj, 0, 0, 0); 2616 if ((error = VOP_FSYNC(vp, MNT_WAIT, td)) == 0 && 2617 vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP) && 2618 bioops.io_fsync) 2619 error = (*bioops.io_fsync)(vp); 2620 VOP_UNLOCK(vp, 0, td); 2621 return (error); 2622 } 2623 2624 int 2625 kern_rename(struct nlookupdata *fromnd, struct nlookupdata *tond) 2626 { 2627 struct namecache *fncpd; 2628 struct namecache *tncpd; 2629 struct namecache *ncp; 2630 struct mount *mp; 2631 int error; 2632 2633 bwillwrite(); 2634 if ((error = nlookup(fromnd)) != 0) 2635 return (error); 2636 if ((fncpd = fromnd->nl_ncp->nc_parent) == NULL) 2637 return (ENOENT); 2638 cache_hold(fncpd); 2639 2640 /* 2641 * unlock the source ncp so we can lookup the target ncp without 2642 * deadlocking. The target may or may not exist so we do not check 2643 * for a target vp like kern_mkdir() and other creation functions do. 2644 * 2645 * The source and target directories are ref'd and rechecked after 2646 * everything is relocked to determine if the source or target file 2647 * has been renamed. 2648 */ 2649 KKASSERT(fromnd->nl_flags & NLC_NCPISLOCKED); 2650 fromnd->nl_flags &= ~NLC_NCPISLOCKED; 2651 cache_unlock(fromnd->nl_ncp); 2652 2653 tond->nl_flags |= NLC_CREATE; 2654 if ((error = nlookup(tond)) != 0) { 2655 cache_drop(fncpd); 2656 return (error); 2657 } 2658 if ((tncpd = tond->nl_ncp->nc_parent) == NULL) { 2659 cache_drop(fncpd); 2660 return (ENOENT); 2661 } 2662 cache_hold(tncpd); 2663 2664 /* 2665 * If the source and target are the same there is nothing to do 2666 */ 2667 if (fromnd->nl_ncp == tond->nl_ncp) { 2668 cache_drop(fncpd); 2669 cache_drop(tncpd); 2670 return (0); 2671 } 2672 2673 /* 2674 * relock the source ncp. NOTE AFTER RELOCKING: the source ncp 2675 * may have become invalid while it was unlocked, nc_vp and nc_mount 2676 * could be NULL. 2677 */ 2678 if (cache_lock_nonblock(fromnd->nl_ncp) == 0) { 2679 cache_resolve(fromnd->nl_ncp, fromnd->nl_cred); 2680 } else if (fromnd->nl_ncp > tond->nl_ncp) { 2681 cache_lock(fromnd->nl_ncp); 2682 cache_resolve(fromnd->nl_ncp, fromnd->nl_cred); 2683 } else { 2684 cache_unlock(tond->nl_ncp); 2685 cache_lock(fromnd->nl_ncp); 2686 cache_resolve(fromnd->nl_ncp, fromnd->nl_cred); 2687 cache_lock(tond->nl_ncp); 2688 cache_resolve(tond->nl_ncp, tond->nl_cred); 2689 } 2690 fromnd->nl_flags |= NLC_NCPISLOCKED; 2691 2692 /* 2693 * make sure the parent directories linkages are the same 2694 */ 2695 if (fncpd != fromnd->nl_ncp->nc_parent || 2696 tncpd != tond->nl_ncp->nc_parent) { 2697 cache_drop(fncpd); 2698 cache_drop(tncpd); 2699 return (ENOENT); 2700 } 2701 2702 /* 2703 * Both the source and target must be within the same filesystem and 2704 * in the same filesystem as their parent directories within the 2705 * namecache topology. 2706 * 2707 * NOTE: fromnd's nc_mount or nc_vp could be NULL. 2708 */ 2709 mp = fncpd->nc_mount; 2710 if (mp != tncpd->nc_mount || mp != fromnd->nl_ncp->nc_mount || 2711 mp != tond->nl_ncp->nc_mount) { 2712 cache_drop(fncpd); 2713 cache_drop(tncpd); 2714 return (EXDEV); 2715 } 2716 2717 /* 2718 * If the target exists and either the source or target is a directory, 2719 * then both must be directories. 2720 * 2721 * Due to relocking of the source, fromnd->nl_ncp->nc_vp might have 2722 * become NULL. 2723 */ 2724 if (tond->nl_ncp->nc_vp) { 2725 if (fromnd->nl_ncp->nc_vp == NULL) { 2726 error = ENOENT; 2727 } else if (fromnd->nl_ncp->nc_vp->v_type == VDIR) { 2728 if (tond->nl_ncp->nc_vp->v_type != VDIR) 2729 error = ENOTDIR; 2730 } else if (tond->nl_ncp->nc_vp->v_type == VDIR) { 2731 error = EISDIR; 2732 } 2733 } 2734 2735 /* 2736 * You cannot rename a source into itself or a subdirectory of itself. 2737 * We check this by travsersing the target directory upwards looking 2738 * for a match against the source. 2739 */ 2740 if (error == 0) { 2741 for (ncp = tncpd; ncp; ncp = ncp->nc_parent) { 2742 if (fromnd->nl_ncp == ncp) { 2743 error = EINVAL; 2744 break; 2745 } 2746 } 2747 } 2748 2749 cache_drop(fncpd); 2750 cache_drop(tncpd); 2751 2752 /* 2753 * Even though the namespaces are different, they may still represent 2754 * hardlinks to the same file. The filesystem might have a hard time 2755 * with this so we issue a NREMOVE of the source instead of a NRENAME 2756 * when we detect the situation. 2757 */ 2758 if (error == 0) { 2759 if (fromnd->nl_ncp->nc_vp == tond->nl_ncp->nc_vp) { 2760 error = VOP_NREMOVE(fromnd->nl_ncp, fromnd->nl_cred); 2761 } else { 2762 error = VOP_NRENAME(fromnd->nl_ncp, tond->nl_ncp, 2763 tond->nl_cred); 2764 } 2765 } 2766 return (error); 2767 } 2768 2769 /* 2770 * rename_args(char *from, char *to) 2771 * 2772 * Rename files. Source and destination must either both be directories, 2773 * or both not be directories. If target is a directory, it must be empty. 2774 */ 2775 int 2776 rename(struct rename_args *uap) 2777 { 2778 struct nlookupdata fromnd, tond; 2779 int error; 2780 2781 error = nlookup_init(&fromnd, uap->from, UIO_USERSPACE, 0); 2782 if (error == 0) { 2783 error = nlookup_init(&tond, uap->to, UIO_USERSPACE, 0); 2784 if (error == 0) 2785 error = kern_rename(&fromnd, &tond); 2786 nlookup_done(&tond); 2787 } 2788 nlookup_done(&fromnd); 2789 return (error); 2790 } 2791 2792 int 2793 kern_mkdir(struct nlookupdata *nd, int mode) 2794 { 2795 struct thread *td = curthread; 2796 struct proc *p = td->td_proc; 2797 struct namecache *ncp; 2798 struct vnode *vp; 2799 struct vattr vattr; 2800 int error; 2801 2802 bwillwrite(); 2803 nd->nl_flags |= NLC_WILLBEDIR | NLC_CREATE; 2804 if ((error = nlookup(nd)) != 0) 2805 return (error); 2806 2807 ncp = nd->nl_ncp; 2808 if (ncp->nc_vp) 2809 return (EEXIST); 2810 2811 VATTR_NULL(&vattr); 2812 vattr.va_type = VDIR; 2813 vattr.va_mode = (mode & ACCESSPERMS) &~ p->p_fd->fd_cmask; 2814 2815 vp = NULL; 2816 error = VOP_NMKDIR(ncp, &vp, p->p_ucred, &vattr); 2817 if (error == 0) 2818 vput(vp); 2819 return (error); 2820 } 2821 2822 /* 2823 * mkdir_args(char *path, int mode) 2824 * 2825 * Make a directory file. 2826 */ 2827 /* ARGSUSED */ 2828 int 2829 mkdir(struct mkdir_args *uap) 2830 { 2831 struct nlookupdata nd; 2832 int error; 2833 2834 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0); 2835 if (error == 0) 2836 error = kern_mkdir(&nd, uap->mode); 2837 nlookup_done(&nd); 2838 return (error); 2839 } 2840 2841 int 2842 kern_rmdir(struct nlookupdata *nd) 2843 { 2844 struct namecache *ncp; 2845 int error; 2846 2847 bwillwrite(); 2848 nd->nl_flags |= NLC_DELETE; 2849 if ((error = nlookup(nd)) != 0) 2850 return (error); 2851 2852 ncp = nd->nl_ncp; 2853 error = VOP_NRMDIR(ncp, nd->nl_cred); 2854 return (error); 2855 } 2856 2857 /* 2858 * rmdir_args(char *path) 2859 * 2860 * Remove a directory file. 2861 */ 2862 /* ARGSUSED */ 2863 int 2864 rmdir(struct rmdir_args *uap) 2865 { 2866 struct nlookupdata nd; 2867 int error; 2868 2869 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0); 2870 if (error == 0) 2871 error = kern_rmdir(&nd); 2872 nlookup_done(&nd); 2873 return (error); 2874 } 2875 2876 int 2877 kern_getdirentries(int fd, char *buf, u_int count, long *basep, int *res, 2878 enum uio_seg direction) 2879 { 2880 struct thread *td = curthread; 2881 struct proc *p = td->td_proc; 2882 struct vnode *vp; 2883 struct file *fp; 2884 struct uio auio; 2885 struct iovec aiov; 2886 long loff; 2887 int error, eofflag; 2888 2889 if ((error = getvnode(p->p_fd, fd, &fp)) != 0) 2890 return (error); 2891 if ((fp->f_flag & FREAD) == 0) 2892 return (EBADF); 2893 vp = (struct vnode *)fp->f_data; 2894 unionread: 2895 if (vp->v_type != VDIR) 2896 return (EINVAL); 2897 aiov.iov_base = buf; 2898 aiov.iov_len = count; 2899 auio.uio_iov = &aiov; 2900 auio.uio_iovcnt = 1; 2901 auio.uio_rw = UIO_READ; 2902 auio.uio_segflg = direction; 2903 auio.uio_td = td; 2904 auio.uio_resid = count; 2905 /* vn_lock(vp, LK_SHARED | LK_RETRY, td); */ 2906 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2907 loff = auio.uio_offset = fp->f_offset; 2908 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL); 2909 fp->f_offset = auio.uio_offset; 2910 VOP_UNLOCK(vp, 0, td); 2911 if (error) 2912 return (error); 2913 if (count == auio.uio_resid) { 2914 if (union_dircheckp) { 2915 error = union_dircheckp(td, &vp, fp); 2916 if (error == -1) 2917 goto unionread; 2918 if (error) 2919 return (error); 2920 } 2921 if ((vp->v_flag & VROOT) && 2922 (vp->v_mount->mnt_flag & MNT_UNION)) { 2923 struct vnode *tvp = vp; 2924 vp = vp->v_mount->mnt_vnodecovered; 2925 vref(vp); 2926 fp->f_data = vp; 2927 fp->f_offset = 0; 2928 vrele(tvp); 2929 goto unionread; 2930 } 2931 } 2932 if (basep) { 2933 *basep = loff; 2934 } 2935 *res = count - auio.uio_resid; 2936 return (error); 2937 } 2938 2939 /* 2940 * getdirentries_args(int fd, char *buf, u_int conut, long *basep) 2941 * 2942 * Read a block of directory entries in a file system independent format. 2943 */ 2944 int 2945 getdirentries(struct getdirentries_args *uap) 2946 { 2947 long base; 2948 int error; 2949 2950 error = kern_getdirentries(uap->fd, uap->buf, uap->count, &base, 2951 &uap->sysmsg_result, UIO_USERSPACE); 2952 2953 if (error == 0) 2954 error = copyout(&base, uap->basep, sizeof(*uap->basep)); 2955 return (error); 2956 } 2957 2958 /* 2959 * getdents_args(int fd, char *buf, size_t count) 2960 */ 2961 int 2962 getdents(struct getdents_args *uap) 2963 { 2964 int error; 2965 2966 error = kern_getdirentries(uap->fd, uap->buf, uap->count, NULL, 2967 &uap->sysmsg_result, UIO_USERSPACE); 2968 2969 return (error); 2970 } 2971 2972 /* 2973 * umask(int newmask) 2974 * 2975 * Set the mode mask for creation of filesystem nodes. 2976 * 2977 * MP SAFE 2978 */ 2979 int 2980 umask(struct umask_args *uap) 2981 { 2982 struct thread *td = curthread; 2983 struct proc *p = td->td_proc; 2984 struct filedesc *fdp; 2985 2986 fdp = p->p_fd; 2987 uap->sysmsg_result = fdp->fd_cmask; 2988 fdp->fd_cmask = uap->newmask & ALLPERMS; 2989 return (0); 2990 } 2991 2992 /* 2993 * revoke(char *path) 2994 * 2995 * Void all references to file by ripping underlying filesystem 2996 * away from vnode. 2997 */ 2998 /* ARGSUSED */ 2999 int 3000 revoke(struct revoke_args *uap) 3001 { 3002 struct thread *td = curthread; 3003 struct nlookupdata nd; 3004 struct vattr vattr; 3005 struct vnode *vp; 3006 struct ucred *cred; 3007 int error; 3008 3009 vp = NULL; 3010 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 3011 if (error == 0) 3012 error = nlookup(&nd); 3013 if (error == 0) 3014 error = cache_vref(nd.nl_ncp, nd.nl_cred, &vp); 3015 cred = crhold(nd.nl_cred); 3016 nlookup_done(&nd); 3017 if (error == 0) { 3018 if (vp->v_type != VCHR && vp->v_type != VBLK) 3019 error = EINVAL; 3020 if (error == 0) 3021 error = VOP_GETATTR(vp, &vattr, td); 3022 if (error == 0 && cred->cr_uid != vattr.va_uid) 3023 error = suser_cred(cred, PRISON_ROOT); 3024 if (error == 0 && count_udev(vp->v_udev) > 0) { 3025 if ((error = vx_lock(vp)) == 0) { 3026 VOP_REVOKE(vp, REVOKEALL); 3027 vx_unlock(vp); 3028 } 3029 } 3030 vrele(vp); 3031 } 3032 crfree(cred); 3033 return (error); 3034 } 3035 3036 /* 3037 * Convert a user file descriptor to a kernel file entry. 3038 */ 3039 int 3040 getvnode(struct filedesc *fdp, int fd, struct file **fpp) 3041 { 3042 struct file *fp; 3043 3044 if ((u_int)fd >= fdp->fd_nfiles || 3045 (fp = fdp->fd_files[fd].fp) == NULL) 3046 return (EBADF); 3047 if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_FIFO) 3048 return (EINVAL); 3049 *fpp = fp; 3050 return (0); 3051 } 3052 /* 3053 * getfh_args(char *fname, fhandle_t *fhp) 3054 * 3055 * Get (NFS) file handle 3056 */ 3057 int 3058 getfh(struct getfh_args *uap) 3059 { 3060 struct thread *td = curthread; 3061 struct nlookupdata nd; 3062 fhandle_t fh; 3063 struct vnode *vp; 3064 int error; 3065 3066 /* 3067 * Must be super user 3068 */ 3069 if ((error = suser(td)) != 0) 3070 return (error); 3071 3072 vp = NULL; 3073 error = nlookup_init(&nd, uap->fname, UIO_USERSPACE, NLC_FOLLOW); 3074 if (error == 0) 3075 error = nlookup(&nd); 3076 if (error == 0) 3077 error = cache_vget(nd.nl_ncp, nd.nl_cred, LK_EXCLUSIVE, &vp); 3078 nlookup_done(&nd); 3079 if (error == 0) { 3080 bzero(&fh, sizeof(fh)); 3081 fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid; 3082 error = VFS_VPTOFH(vp, &fh.fh_fid); 3083 vput(vp); 3084 if (error == 0) 3085 error = copyout(&fh, uap->fhp, sizeof(fh)); 3086 } 3087 return (error); 3088 } 3089 3090 /* 3091 * fhopen_args(const struct fhandle *u_fhp, int flags) 3092 * 3093 * syscall for the rpc.lockd to use to translate a NFS file handle into 3094 * an open descriptor. 3095 * 3096 * warning: do not remove the suser() call or this becomes one giant 3097 * security hole. 3098 */ 3099 int 3100 fhopen(struct fhopen_args *uap) 3101 { 3102 struct thread *td = curthread; 3103 struct proc *p = td->td_proc; 3104 struct mount *mp; 3105 struct vnode *vp; 3106 struct fhandle fhp; 3107 struct vattr vat; 3108 struct vattr *vap = &vat; 3109 struct flock lf; 3110 struct filedesc *fdp = p->p_fd; 3111 int fmode, mode, error, type; 3112 struct file *nfp; 3113 struct file *fp; 3114 int indx; 3115 3116 /* 3117 * Must be super user 3118 */ 3119 error = suser(td); 3120 if (error) 3121 return (error); 3122 3123 fmode = FFLAGS(uap->flags); 3124 /* why not allow a non-read/write open for our lockd? */ 3125 if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT)) 3126 return (EINVAL); 3127 error = copyin(uap->u_fhp, &fhp, sizeof(fhp)); 3128 if (error) 3129 return(error); 3130 /* find the mount point */ 3131 mp = vfs_getvfs(&fhp.fh_fsid); 3132 if (mp == NULL) 3133 return (ESTALE); 3134 /* now give me my vnode, it gets returned to me locked */ 3135 error = VFS_FHTOVP(mp, &fhp.fh_fid, &vp); 3136 if (error) 3137 return (error); 3138 /* 3139 * from now on we have to make sure not 3140 * to forget about the vnode 3141 * any error that causes an abort must vput(vp) 3142 * just set error = err and 'goto bad;'. 3143 */ 3144 3145 /* 3146 * from vn_open 3147 */ 3148 if (vp->v_type == VLNK) { 3149 error = EMLINK; 3150 goto bad; 3151 } 3152 if (vp->v_type == VSOCK) { 3153 error = EOPNOTSUPP; 3154 goto bad; 3155 } 3156 mode = 0; 3157 if (fmode & (FWRITE | O_TRUNC)) { 3158 if (vp->v_type == VDIR) { 3159 error = EISDIR; 3160 goto bad; 3161 } 3162 error = vn_writechk(vp); 3163 if (error) 3164 goto bad; 3165 mode |= VWRITE; 3166 } 3167 if (fmode & FREAD) 3168 mode |= VREAD; 3169 if (mode) { 3170 error = VOP_ACCESS(vp, mode, p->p_ucred, td); 3171 if (error) 3172 goto bad; 3173 } 3174 if (fmode & O_TRUNC) { 3175 VOP_UNLOCK(vp, 0, td); /* XXX */ 3176 VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE); 3177 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); /* XXX */ 3178 VATTR_NULL(vap); 3179 vap->va_size = 0; 3180 error = VOP_SETATTR(vp, vap, p->p_ucred, td); 3181 if (error) 3182 goto bad; 3183 } 3184 3185 /* 3186 * VOP_OPEN needs the file pointer so it can potentially override 3187 * it. 3188 * 3189 * WARNING! no f_ncp will be associated when fhopen()ing a directory. 3190 * XXX 3191 */ 3192 if ((error = falloc(p, &nfp, NULL)) != 0) 3193 goto bad; 3194 fp = nfp; 3195 3196 fp->f_type = DTYPE_VNODE; 3197 fp->f_flag = fmode & FMASK; 3198 fp->f_ops = &vnode_fileops; 3199 fp->f_data = vp; 3200 3201 error = VOP_OPEN(vp, fmode, p->p_ucred, fp, td); 3202 if (error) { 3203 /* 3204 * setting f_ops this way prevents VOP_CLOSE from being 3205 * called or fdrop() releasing the vp from v_data. Since 3206 * the VOP_OPEN failed we don't want to VOP_CLOSE. 3207 */ 3208 fp->f_ops = &badfileops; 3209 fp->f_data = NULL; 3210 fdrop(fp, td); 3211 goto bad; 3212 } 3213 if (fmode & FWRITE) 3214 vp->v_writecount++; 3215 3216 /* 3217 * The fp now owns a reference on the vnode. We still have our own 3218 * ref+lock. 3219 */ 3220 vref(vp); 3221 3222 /* 3223 * Make sure that a VM object is created for VMIO support. If this 3224 * fails just fdrop() normally to clean up. 3225 */ 3226 if (vn_canvmio(vp) == TRUE) { 3227 if ((error = vfs_object_create(vp, td)) != 0) { 3228 fdrop(fp, td); 3229 goto bad; 3230 } 3231 } 3232 3233 /* 3234 * The open was successful, associate it with a file descriptor. 3235 */ 3236 if ((error = fsetfd(p, fp, &indx)) != 0) { 3237 if (fmode & FWRITE) 3238 vp->v_writecount--; 3239 fdrop(fp, td); 3240 goto bad; 3241 } 3242 3243 if (fmode & (O_EXLOCK | O_SHLOCK)) { 3244 lf.l_whence = SEEK_SET; 3245 lf.l_start = 0; 3246 lf.l_len = 0; 3247 if (fmode & O_EXLOCK) 3248 lf.l_type = F_WRLCK; 3249 else 3250 lf.l_type = F_RDLCK; 3251 type = F_FLOCK; 3252 if ((fmode & FNONBLOCK) == 0) 3253 type |= F_WAIT; 3254 VOP_UNLOCK(vp, 0, td); 3255 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) { 3256 /* 3257 * lock request failed. Normally close the descriptor 3258 * but handle the case where someone might have dup()d 3259 * or close()d it when we weren't looking. 3260 */ 3261 if (fdp->fd_files[indx].fp == fp) { 3262 funsetfd(fdp, indx); 3263 fdrop(fp, td); 3264 } 3265 3266 /* 3267 * release our private reference. 3268 */ 3269 fdrop(fp, td); 3270 vrele(vp); 3271 return (error); 3272 } 3273 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3274 fp->f_flag |= FHASLOCK; 3275 } 3276 if ((vp->v_type == VREG) && (VOP_GETVOBJECT(vp, NULL) != 0)) 3277 vfs_object_create(vp, td); 3278 3279 vput(vp); 3280 fdrop(fp, td); 3281 uap->sysmsg_result = indx; 3282 return (0); 3283 3284 bad: 3285 vput(vp); 3286 return (error); 3287 } 3288 3289 /* 3290 * fhstat_args(struct fhandle *u_fhp, struct stat *sb) 3291 */ 3292 int 3293 fhstat(struct fhstat_args *uap) 3294 { 3295 struct thread *td = curthread; 3296 struct stat sb; 3297 fhandle_t fh; 3298 struct mount *mp; 3299 struct vnode *vp; 3300 int error; 3301 3302 /* 3303 * Must be super user 3304 */ 3305 error = suser(td); 3306 if (error) 3307 return (error); 3308 3309 error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t)); 3310 if (error) 3311 return (error); 3312 3313 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) 3314 return (ESTALE); 3315 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp))) 3316 return (error); 3317 error = vn_stat(vp, &sb, td); 3318 vput(vp); 3319 if (error) 3320 return (error); 3321 error = copyout(&sb, uap->sb, sizeof(sb)); 3322 return (error); 3323 } 3324 3325 /* 3326 * fhstatfs_args(struct fhandle *u_fhp, struct statfs *buf) 3327 */ 3328 int 3329 fhstatfs(struct fhstatfs_args *uap) 3330 { 3331 struct thread *td = curthread; 3332 struct proc *p = td->td_proc; 3333 struct statfs *sp; 3334 struct mount *mp; 3335 struct vnode *vp; 3336 struct statfs sb; 3337 char *fullpath, *freepath; 3338 fhandle_t fh; 3339 int error; 3340 3341 /* 3342 * Must be super user 3343 */ 3344 if ((error = suser(td))) 3345 return (error); 3346 3347 if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0) 3348 return (error); 3349 3350 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) 3351 return (ESTALE); 3352 3353 if (p != NULL && (p->p_fd->fd_nrdir->nc_flag & NCF_ROOT) == 0 && 3354 !chroot_visible_mnt(mp, p)) 3355 return (ESTALE); 3356 3357 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp))) 3358 return (error); 3359 mp = vp->v_mount; 3360 sp = &mp->mnt_stat; 3361 vput(vp); 3362 if ((error = VFS_STATFS(mp, sp, td)) != 0) 3363 return (error); 3364 3365 error = cache_fullpath(p, mp->mnt_ncp, &fullpath, &freepath); 3366 if (error) 3367 return(error); 3368 bzero(sp->f_mntonname, sizeof(sp->f_mntonname)); 3369 strlcpy(sp->f_mntonname, fullpath, sizeof(sp->f_mntonname)); 3370 free(freepath, M_TEMP); 3371 3372 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 3373 if (suser(td)) { 3374 bcopy(sp, &sb, sizeof(sb)); 3375 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; 3376 sp = &sb; 3377 } 3378 return (copyout(sp, uap->buf, sizeof(*sp))); 3379 } 3380 3381 /* 3382 * Syscall to push extended attribute configuration information into the 3383 * VFS. Accepts a path, which it converts to a mountpoint, as well as 3384 * a command (int cmd), and attribute name and misc data. For now, the 3385 * attribute name is left in userspace for consumption by the VFS_op. 3386 * It will probably be changed to be copied into sysspace by the 3387 * syscall in the future, once issues with various consumers of the 3388 * attribute code have raised their hands. 3389 * 3390 * Currently this is used only by UFS Extended Attributes. 3391 */ 3392 int 3393 extattrctl(struct extattrctl_args *uap) 3394 { 3395 struct nlookupdata nd; 3396 struct mount *mp; 3397 struct vnode *vp; 3398 int error; 3399 3400 vp = NULL; 3401 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 3402 if (error == 0) 3403 error = nlookup(&nd); 3404 if (error == 0) { 3405 mp = nd.nl_ncp->nc_mount; 3406 error = VFS_EXTATTRCTL(mp, uap->cmd, 3407 uap->attrname, uap->arg, 3408 nd.nl_td); 3409 } 3410 nlookup_done(&nd); 3411 return (error); 3412 } 3413 3414 /* 3415 * Syscall to set a named extended attribute on a file or directory. 3416 * Accepts attribute name, and a uio structure pointing to the data to set. 3417 * The uio is consumed in the style of writev(). The real work happens 3418 * in VOP_SETEXTATTR(). 3419 */ 3420 int 3421 extattr_set_file(struct extattr_set_file_args *uap) 3422 { 3423 char attrname[EXTATTR_MAXNAMELEN]; 3424 struct iovec aiov[UIO_SMALLIOV]; 3425 struct iovec *needfree; 3426 struct nlookupdata nd; 3427 struct iovec *iov; 3428 struct vnode *vp; 3429 struct uio auio; 3430 u_int iovlen; 3431 u_int cnt; 3432 int error; 3433 int i; 3434 3435 error = copyin(uap->attrname, attrname, EXTATTR_MAXNAMELEN); 3436 if (error) 3437 return (error); 3438 3439 vp = NULL; 3440 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 3441 if (error == 0) 3442 error = nlookup(&nd); 3443 if (error == 0) 3444 error = cache_vget(nd.nl_ncp, nd.nl_cred, LK_EXCLUSIVE, &vp); 3445 if (error) { 3446 nlookup_done(&nd); 3447 return (error); 3448 } 3449 3450 needfree = NULL; 3451 iovlen = uap->iovcnt * sizeof(struct iovec); 3452 if (uap->iovcnt > UIO_SMALLIOV) { 3453 if (uap->iovcnt > UIO_MAXIOV) { 3454 error = EINVAL; 3455 goto done; 3456 } 3457 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); 3458 needfree = iov; 3459 } else { 3460 iov = aiov; 3461 } 3462 auio.uio_iov = iov; 3463 auio.uio_iovcnt = uap->iovcnt; 3464 auio.uio_rw = UIO_WRITE; 3465 auio.uio_segflg = UIO_USERSPACE; 3466 auio.uio_td = nd.nl_td; 3467 auio.uio_offset = 0; 3468 if ((error = copyin(uap->iovp, iov, iovlen))) 3469 goto done; 3470 auio.uio_resid = 0; 3471 for (i = 0; i < uap->iovcnt; i++) { 3472 if (iov->iov_len > INT_MAX - auio.uio_resid) { 3473 error = EINVAL; 3474 goto done; 3475 } 3476 auio.uio_resid += iov->iov_len; 3477 iov++; 3478 } 3479 cnt = auio.uio_resid; 3480 error = VOP_SETEXTATTR(vp, attrname, &auio, nd.nl_cred, nd.nl_td); 3481 cnt -= auio.uio_resid; 3482 uap->sysmsg_result = cnt; 3483 done: 3484 vput(vp); 3485 nlookup_done(&nd); 3486 if (needfree) 3487 FREE(needfree, M_IOV); 3488 return (error); 3489 } 3490 3491 /* 3492 * Syscall to get a named extended attribute on a file or directory. 3493 * Accepts attribute name, and a uio structure pointing to a buffer for the 3494 * data. The uio is consumed in the style of readv(). The real work 3495 * happens in VOP_GETEXTATTR(); 3496 */ 3497 int 3498 extattr_get_file(struct extattr_get_file_args *uap) 3499 { 3500 char attrname[EXTATTR_MAXNAMELEN]; 3501 struct iovec aiov[UIO_SMALLIOV]; 3502 struct iovec *needfree; 3503 struct nlookupdata nd; 3504 struct iovec *iov; 3505 struct vnode *vp; 3506 struct uio auio; 3507 u_int iovlen; 3508 u_int cnt; 3509 int error; 3510 int i; 3511 3512 error = copyin(uap->attrname, attrname, EXTATTR_MAXNAMELEN); 3513 if (error) 3514 return (error); 3515 3516 vp = NULL; 3517 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 3518 if (error == 0) 3519 error = nlookup(&nd); 3520 if (error == 0) 3521 error = cache_vget(nd.nl_ncp, nd.nl_cred, LK_EXCLUSIVE, &vp); 3522 if (error) { 3523 nlookup_done(&nd); 3524 return (error); 3525 } 3526 3527 iovlen = uap->iovcnt * sizeof (struct iovec); 3528 needfree = NULL; 3529 if (uap->iovcnt > UIO_SMALLIOV) { 3530 if (uap->iovcnt > UIO_MAXIOV) { 3531 error = EINVAL; 3532 goto done; 3533 } 3534 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); 3535 needfree = iov; 3536 } else { 3537 iov = aiov; 3538 } 3539 auio.uio_iov = iov; 3540 auio.uio_iovcnt = uap->iovcnt; 3541 auio.uio_rw = UIO_READ; 3542 auio.uio_segflg = UIO_USERSPACE; 3543 auio.uio_td = nd.nl_td; 3544 auio.uio_offset = 0; 3545 if ((error = copyin(uap->iovp, iov, iovlen))) 3546 goto done; 3547 auio.uio_resid = 0; 3548 for (i = 0; i < uap->iovcnt; i++) { 3549 if (iov->iov_len > INT_MAX - auio.uio_resid) { 3550 error = EINVAL; 3551 goto done; 3552 } 3553 auio.uio_resid += iov->iov_len; 3554 iov++; 3555 } 3556 cnt = auio.uio_resid; 3557 error = VOP_GETEXTATTR(vp, attrname, &auio, nd.nl_cred, nd.nl_td); 3558 cnt -= auio.uio_resid; 3559 uap->sysmsg_result = cnt; 3560 done: 3561 vput(vp); 3562 nlookup_done(&nd); 3563 if (needfree) 3564 FREE(needfree, M_IOV); 3565 return(error); 3566 } 3567 3568 /* 3569 * Syscall to delete a named extended attribute from a file or directory. 3570 * Accepts attribute name. The real work happens in VOP_SETEXTATTR(). 3571 */ 3572 int 3573 extattr_delete_file(struct extattr_delete_file_args *uap) 3574 { 3575 char attrname[EXTATTR_MAXNAMELEN]; 3576 struct nlookupdata nd; 3577 struct vnode *vp; 3578 int error; 3579 3580 error = copyin(uap->attrname, attrname, EXTATTR_MAXNAMELEN); 3581 if (error) 3582 return(error); 3583 3584 vp = NULL; 3585 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 3586 if (error == 0) 3587 error = nlookup(&nd); 3588 if (error == 0) 3589 error = cache_vget(nd.nl_ncp, nd.nl_cred, LK_EXCLUSIVE, &vp); 3590 if (error) { 3591 nlookup_done(&nd); 3592 return (error); 3593 } 3594 3595 error = VOP_SETEXTATTR(vp, attrname, NULL, nd.nl_cred, nd.nl_td); 3596 vput(vp); 3597 nlookup_done(&nd); 3598 return(error); 3599 } 3600 3601 static int 3602 chroot_visible_mnt(struct mount *mp, struct proc *p) 3603 { 3604 struct namecache *ncp; 3605 /* 3606 * First check if this file system is below 3607 * the chroot path. 3608 */ 3609 ncp = mp->mnt_ncp; 3610 while (ncp != NULL && ncp != p->p_fd->fd_nrdir) 3611 ncp = ncp->nc_parent; 3612 if (ncp == NULL) { 3613 /* 3614 * This is not below the chroot path. 3615 * 3616 * Check if the chroot path is on the same filesystem, 3617 * by determing if we have to cross a mount point 3618 * before reaching mp->mnt_ncp. 3619 */ 3620 ncp = p->p_fd->fd_nrdir; 3621 while (ncp != NULL && ncp != mp->mnt_ncp) { 3622 if (ncp->nc_flag & NCF_MOUNTPT) { 3623 ncp = NULL; 3624 break; 3625 } 3626 ncp = ncp->nc_parent; 3627 } 3628 } 3629 return(ncp != NULL); 3630 } 3631