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. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94 35 * $FreeBSD: src/sys/kern/vfs_syscalls.c,v 1.151.2.18 2003/04/04 20:35:58 tegge Exp $ 36 */ 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/buf.h> 41 #include <sys/conf.h> 42 #include <sys/sysent.h> 43 #include <sys/malloc.h> 44 #include <sys/mount.h> 45 #include <sys/mountctl.h> 46 #include <sys/sysproto.h> 47 #include <sys/filedesc.h> 48 #include <sys/kernel.h> 49 #include <sys/fcntl.h> 50 #include <sys/file.h> 51 #include <sys/linker.h> 52 #include <sys/stat.h> 53 #include <sys/unistd.h> 54 #include <sys/vnode.h> 55 #include <sys/proc.h> 56 #include <sys/priv.h> 57 #include <sys/jail.h> 58 #include <sys/namei.h> 59 #include <sys/nlookup.h> 60 #include <sys/dirent.h> 61 #include <sys/extattr.h> 62 #include <sys/spinlock.h> 63 #include <sys/kern_syscall.h> 64 #include <sys/objcache.h> 65 #include <sys/sysctl.h> 66 67 #include <sys/buf2.h> 68 #include <sys/file2.h> 69 #include <sys/spinlock2.h> 70 71 #include <vm/vm.h> 72 #include <vm/vm_object.h> 73 #include <vm/vm_page.h> 74 75 #include <machine/limits.h> 76 #include <machine/stdarg.h> 77 78 static void mount_warning(struct mount *mp, const char *ctl, ...) 79 __printflike(2, 3); 80 static int mount_path(struct proc *p, struct mount *mp, char **rb, char **fb); 81 static int checkvp_chdir (struct vnode *vn, struct thread *td); 82 static void checkdirs (struct nchandle *old_nch, struct nchandle *new_nch); 83 static int chroot_refuse_vdir_fds (struct filedesc *fdp); 84 static int chroot_visible_mnt(struct mount *mp, struct proc *p); 85 static int getutimes (struct timeval *, struct timespec *); 86 static int getutimens (const struct timespec *, struct timespec *, int *); 87 static int setfown (struct mount *, struct vnode *, uid_t, gid_t); 88 static int setfmode (struct vnode *, int); 89 static int setfflags (struct vnode *, int); 90 static int setutimes (struct vnode *, struct vattr *, 91 const struct timespec *, int); 92 static int usermount = 0; /* if 1, non-root can mount fs. */ 93 94 SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0, 95 "Allow non-root users to mount filesystems"); 96 97 /* 98 * Virtual File System System Calls 99 */ 100 101 /* 102 * Mount a file system. 103 * 104 * mount_args(char *type, char *path, int flags, caddr_t data) 105 * 106 * MPALMOSTSAFE 107 */ 108 int 109 sys_mount(struct mount_args *uap) 110 { 111 struct thread *td = curthread; 112 struct vnode *vp; 113 struct nchandle nch; 114 struct mount *mp, *nullmp; 115 struct vfsconf *vfsp; 116 int error, flag = 0, flag2 = 0; 117 int hasmount; 118 struct vattr va; 119 struct nlookupdata nd; 120 char fstypename[MFSNAMELEN]; 121 struct ucred *cred; 122 123 cred = td->td_ucred; 124 if (jailed(cred)) { 125 error = EPERM; 126 goto done; 127 } 128 if (usermount == 0 && (error = priv_check(td, PRIV_ROOT))) 129 goto done; 130 131 /* 132 * Do not allow NFS export by non-root users. 133 */ 134 if (uap->flags & MNT_EXPORTED) { 135 error = priv_check(td, PRIV_ROOT); 136 if (error) 137 goto done; 138 } 139 /* 140 * Silently enforce MNT_NOSUID and MNT_NODEV for non-root users 141 */ 142 if (priv_check(td, PRIV_ROOT)) 143 uap->flags |= MNT_NOSUID | MNT_NODEV; 144 145 /* 146 * Lookup the requested path and extract the nch and vnode. 147 */ 148 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 149 if (error == 0) { 150 if ((error = nlookup(&nd)) == 0) { 151 if (nd.nl_nch.ncp->nc_vp == NULL) 152 error = ENOENT; 153 } 154 } 155 if (error) { 156 nlookup_done(&nd); 157 goto done; 158 } 159 160 /* 161 * If the target filesystem is resolved via a nullfs mount, then 162 * nd.nl_nch.mount will be pointing to the nullfs mount structure 163 * instead of the target file system. We need it in case we are 164 * doing an update. 165 */ 166 nullmp = nd.nl_nch.mount; 167 168 /* 169 * Extract the locked+refd ncp and cleanup the nd structure 170 */ 171 nch = nd.nl_nch; 172 cache_zero(&nd.nl_nch); 173 nlookup_done(&nd); 174 175 if ((nch.ncp->nc_flag & NCF_ISMOUNTPT) && 176 (mp = cache_findmount(&nch)) != NULL) { 177 cache_dropmount(mp); 178 hasmount = 1; 179 } else { 180 hasmount = 0; 181 } 182 183 184 /* 185 * now we have the locked ref'd nch and unreferenced vnode. 186 */ 187 vp = nch.ncp->nc_vp; 188 if ((error = vget(vp, LK_EXCLUSIVE)) != 0) { 189 cache_put(&nch); 190 goto done; 191 } 192 cache_unlock(&nch); 193 194 /* 195 * Extract the file system type. We need to know this early, to take 196 * appropriate actions if we are dealing with a nullfs. 197 */ 198 if ((error = copyinstr(uap->type, fstypename, MFSNAMELEN, NULL)) != 0) { 199 cache_drop(&nch); 200 vput(vp); 201 goto done; 202 } 203 204 /* 205 * Now we have an unlocked ref'd nch and a locked ref'd vp 206 */ 207 if (uap->flags & MNT_UPDATE) { 208 if ((vp->v_flag & (VROOT|VPFSROOT)) == 0) { 209 cache_drop(&nch); 210 vput(vp); 211 error = EINVAL; 212 goto done; 213 } 214 215 if (strncmp(fstypename, "null", 5) == 0) { 216 KKASSERT(nullmp); 217 mp = nullmp; 218 } else { 219 mp = vp->v_mount; 220 } 221 222 flag = mp->mnt_flag; 223 flag2 = mp->mnt_kern_flag; 224 /* 225 * We only allow the filesystem to be reloaded if it 226 * is currently mounted read-only. 227 */ 228 if ((uap->flags & MNT_RELOAD) && 229 ((mp->mnt_flag & MNT_RDONLY) == 0)) { 230 cache_drop(&nch); 231 vput(vp); 232 error = EOPNOTSUPP; /* Needs translation */ 233 goto done; 234 } 235 /* 236 * Only root, or the user that did the original mount is 237 * permitted to update it. 238 */ 239 if (mp->mnt_stat.f_owner != cred->cr_uid && 240 (error = priv_check(td, PRIV_ROOT))) { 241 cache_drop(&nch); 242 vput(vp); 243 goto done; 244 } 245 if (vfs_busy(mp, LK_NOWAIT)) { 246 cache_drop(&nch); 247 vput(vp); 248 error = EBUSY; 249 goto done; 250 } 251 if (hasmount) { 252 cache_drop(&nch); 253 vfs_unbusy(mp); 254 vput(vp); 255 error = EBUSY; 256 goto done; 257 } 258 mp->mnt_flag |= 259 uap->flags & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE); 260 lwkt_gettoken(&mp->mnt_token); 261 vn_unlock(vp); 262 vfsp = mp->mnt_vfc; 263 goto update; 264 } 265 266 /* 267 * If the user is not root, ensure that they own the directory 268 * onto which we are attempting to mount. 269 */ 270 if ((error = VOP_GETATTR(vp, &va)) || 271 (va.va_uid != cred->cr_uid && 272 (error = priv_check(td, PRIV_ROOT)))) { 273 cache_drop(&nch); 274 vput(vp); 275 goto done; 276 } 277 if ((error = vinvalbuf(vp, V_SAVE, 0, 0)) != 0) { 278 cache_drop(&nch); 279 vput(vp); 280 goto done; 281 } 282 if (vp->v_type != VDIR) { 283 cache_drop(&nch); 284 vput(vp); 285 error = ENOTDIR; 286 goto done; 287 } 288 if (vp->v_mount->mnt_kern_flag & MNTK_NOSTKMNT) { 289 cache_drop(&nch); 290 vput(vp); 291 error = EPERM; 292 goto done; 293 } 294 vfsp = vfsconf_find_by_name(fstypename); 295 if (vfsp == NULL) { 296 linker_file_t lf; 297 298 /* Only load modules for root (very important!) */ 299 if ((error = priv_check(td, PRIV_ROOT)) != 0) { 300 cache_drop(&nch); 301 vput(vp); 302 goto done; 303 } 304 error = linker_load_file(fstypename, &lf); 305 if (error || lf == NULL) { 306 cache_drop(&nch); 307 vput(vp); 308 if (lf == NULL) 309 error = ENODEV; 310 goto done; 311 } 312 lf->userrefs++; 313 /* lookup again, see if the VFS was loaded */ 314 vfsp = vfsconf_find_by_name(fstypename); 315 if (vfsp == NULL) { 316 lf->userrefs--; 317 linker_file_unload(lf); 318 cache_drop(&nch); 319 vput(vp); 320 error = ENODEV; 321 goto done; 322 } 323 } 324 if (hasmount) { 325 cache_drop(&nch); 326 vput(vp); 327 error = EBUSY; 328 goto done; 329 } 330 331 /* 332 * Allocate and initialize the filesystem. 333 */ 334 mp = kmalloc(sizeof(struct mount), M_MOUNT, M_ZERO|M_WAITOK); 335 mount_init(mp); 336 vfs_busy(mp, LK_NOWAIT); 337 mp->mnt_op = vfsp->vfc_vfsops; 338 mp->mnt_vfc = vfsp; 339 mp->mnt_pbuf_count = nswbuf_kva / NSWBUF_SPLIT; 340 vfsp->vfc_refcount++; 341 mp->mnt_stat.f_type = vfsp->vfc_typenum; 342 mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK; 343 strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN); 344 mp->mnt_stat.f_owner = cred->cr_uid; 345 lwkt_gettoken(&mp->mnt_token); 346 vn_unlock(vp); 347 update: 348 /* 349 * (per-mount token acquired at this point) 350 * 351 * Set the mount level flags. 352 */ 353 if (uap->flags & MNT_RDONLY) 354 mp->mnt_flag |= MNT_RDONLY; 355 else if (mp->mnt_flag & MNT_RDONLY) 356 mp->mnt_kern_flag |= MNTK_WANTRDWR; 357 mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV | 358 MNT_SYNCHRONOUS | MNT_ASYNC | MNT_NOATIME | 359 MNT_NOSYMFOLLOW | MNT_IGNORE | MNT_TRIM | 360 MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR | 361 MNT_AUTOMOUNTED); 362 mp->mnt_flag |= uap->flags & (MNT_NOSUID | MNT_NOEXEC | 363 MNT_NODEV | MNT_SYNCHRONOUS | MNT_ASYNC | MNT_FORCE | 364 MNT_NOSYMFOLLOW | MNT_IGNORE | MNT_TRIM | 365 MNT_NOATIME | MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR | 366 MNT_AUTOMOUNTED); 367 368 /* 369 * Pre-set the mount's ALL_MPSAFE flags if specified in the vfsconf. 370 * This way the initial VFS_MOUNT() call will also be MPSAFE. 371 */ 372 if (vfsp->vfc_flags & VFCF_MPSAFE) 373 mp->mnt_kern_flag |= MNTK_ALL_MPSAFE; 374 375 /* 376 * Mount the filesystem. 377 * XXX The final recipients of VFS_MOUNT just overwrite the ndp they 378 * get. 379 */ 380 error = VFS_MOUNT(mp, uap->path, uap->data, cred); 381 if (mp->mnt_flag & MNT_UPDATE) { 382 if (mp->mnt_kern_flag & MNTK_WANTRDWR) 383 mp->mnt_flag &= ~MNT_RDONLY; 384 mp->mnt_flag &=~ (MNT_UPDATE | MNT_RELOAD | MNT_FORCE); 385 mp->mnt_kern_flag &=~ MNTK_WANTRDWR; 386 if (error) { 387 mp->mnt_flag = flag; 388 mp->mnt_kern_flag = flag2; 389 } 390 lwkt_reltoken(&mp->mnt_token); 391 vfs_unbusy(mp); 392 vrele(vp); 393 cache_drop(&nch); 394 goto done; 395 } 396 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 397 398 /* 399 * Put the new filesystem on the mount list after root. The mount 400 * point gets its own mnt_ncmountpt (unless the VFS already set one 401 * up) which represents the root of the mount. The lookup code 402 * detects the mount point going forward and checks the root of 403 * the mount going backwards. 404 * 405 * It is not necessary to invalidate or purge the vnode underneath 406 * because elements under the mount will be given their own glue 407 * namecache record. 408 */ 409 if (!error) { 410 if (mp->mnt_ncmountpt.ncp == NULL) { 411 /* 412 * Allocate, then unlock, but leave the ref intact. 413 * This is the mnt_refs (1) that we will retain 414 * through to the unmount. 415 */ 416 cache_allocroot(&mp->mnt_ncmountpt, mp, NULL); 417 cache_unlock(&mp->mnt_ncmountpt); 418 } 419 vn_unlock(vp); 420 mp->mnt_ncmounton = nch; /* inherits ref */ 421 cache_lock(&nch); 422 nch.ncp->nc_flag |= NCF_ISMOUNTPT; 423 cache_unlock(&nch); 424 cache_ismounting(mp); 425 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 426 427 mountlist_insert(mp, MNTINS_LAST); 428 vn_unlock(vp); 429 checkdirs(&mp->mnt_ncmounton, &mp->mnt_ncmountpt); 430 error = vfs_allocate_syncvnode(mp); 431 lwkt_reltoken(&mp->mnt_token); 432 vfs_unbusy(mp); 433 error = VFS_START(mp, 0); 434 vrele(vp); 435 KNOTE(&fs_klist, VQ_MOUNT); 436 } else { 437 vn_syncer_thr_stop(mp); 438 vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_coherency_ops); 439 vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_journal_ops); 440 vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_norm_ops); 441 vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_spec_ops); 442 vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_fifo_ops); 443 mp->mnt_vfc->vfc_refcount--; 444 lwkt_reltoken(&mp->mnt_token); 445 vfs_unbusy(mp); 446 kfree(mp, M_MOUNT); 447 cache_drop(&nch); 448 vput(vp); 449 } 450 done: 451 return (error); 452 } 453 454 /* 455 * Scan all active processes to see if any of them have a current 456 * or root directory onto which the new filesystem has just been 457 * mounted. If so, replace them with the new mount point. 458 * 459 * Both old_nch and new_nch are ref'd on call but not locked. 460 * new_nch must be temporarily locked so it can be associated with the 461 * vnode representing the root of the mount point. 462 */ 463 struct checkdirs_info { 464 struct nchandle old_nch; 465 struct nchandle new_nch; 466 struct vnode *old_vp; 467 struct vnode *new_vp; 468 }; 469 470 static int checkdirs_callback(struct proc *p, void *data); 471 472 static void 473 checkdirs(struct nchandle *old_nch, struct nchandle *new_nch) 474 { 475 struct checkdirs_info info; 476 struct vnode *olddp; 477 struct vnode *newdp; 478 struct mount *mp; 479 480 /* 481 * If the old mount point's vnode has a usecount of 1, it is not 482 * being held as a descriptor anywhere. 483 */ 484 olddp = old_nch->ncp->nc_vp; 485 if (olddp == NULL || VREFCNT(olddp) == 1) 486 return; 487 488 /* 489 * Force the root vnode of the new mount point to be resolved 490 * so we can update any matching processes. 491 */ 492 mp = new_nch->mount; 493 if (VFS_ROOT(mp, &newdp)) 494 panic("mount: lost mount"); 495 vn_unlock(newdp); 496 cache_lock(new_nch); 497 vn_lock(newdp, LK_EXCLUSIVE | LK_RETRY); 498 cache_setunresolved(new_nch); 499 cache_setvp(new_nch, newdp); 500 cache_unlock(new_nch); 501 502 /* 503 * Special handling of the root node 504 */ 505 if (rootvnode == olddp) { 506 vref(newdp); 507 vfs_cache_setroot(newdp, cache_hold(new_nch)); 508 } 509 510 /* 511 * Pass newdp separately so the callback does not have to access 512 * it via new_nch->ncp->nc_vp. 513 */ 514 info.old_nch = *old_nch; 515 info.new_nch = *new_nch; 516 info.new_vp = newdp; 517 allproc_scan(checkdirs_callback, &info, 0); 518 vput(newdp); 519 } 520 521 /* 522 * NOTE: callback is not MP safe because the scanned process's filedesc 523 * structure can be ripped out from under us, amoung other things. 524 */ 525 static int 526 checkdirs_callback(struct proc *p, void *data) 527 { 528 struct checkdirs_info *info = data; 529 struct filedesc *fdp; 530 struct nchandle ncdrop1; 531 struct nchandle ncdrop2; 532 struct vnode *vprele1; 533 struct vnode *vprele2; 534 535 if ((fdp = p->p_fd) != NULL) { 536 cache_zero(&ncdrop1); 537 cache_zero(&ncdrop2); 538 vprele1 = NULL; 539 vprele2 = NULL; 540 541 /* 542 * MPUNSAFE - XXX fdp can be pulled out from under a 543 * foreign process. 544 * 545 * A shared filedesc is ok, we don't have to copy it 546 * because we are making this change globally. 547 */ 548 spin_lock(&fdp->fd_spin); 549 if (fdp->fd_ncdir.mount == info->old_nch.mount && 550 fdp->fd_ncdir.ncp == info->old_nch.ncp) { 551 vprele1 = fdp->fd_cdir; 552 vref(info->new_vp); 553 fdp->fd_cdir = info->new_vp; 554 ncdrop1 = fdp->fd_ncdir; 555 cache_copy(&info->new_nch, &fdp->fd_ncdir); 556 } 557 if (fdp->fd_nrdir.mount == info->old_nch.mount && 558 fdp->fd_nrdir.ncp == info->old_nch.ncp) { 559 vprele2 = fdp->fd_rdir; 560 vref(info->new_vp); 561 fdp->fd_rdir = info->new_vp; 562 ncdrop2 = fdp->fd_nrdir; 563 cache_copy(&info->new_nch, &fdp->fd_nrdir); 564 } 565 spin_unlock(&fdp->fd_spin); 566 if (ncdrop1.ncp) 567 cache_drop(&ncdrop1); 568 if (ncdrop2.ncp) 569 cache_drop(&ncdrop2); 570 if (vprele1) 571 vrele(vprele1); 572 if (vprele2) 573 vrele(vprele2); 574 } 575 return(0); 576 } 577 578 /* 579 * Unmount a file system. 580 * 581 * Note: unmount takes a path to the vnode mounted on as argument, 582 * not special file (as before). 583 * 584 * umount_args(char *path, int flags) 585 * 586 * MPALMOSTSAFE 587 */ 588 int 589 sys_unmount(struct unmount_args *uap) 590 { 591 struct thread *td = curthread; 592 struct proc *p __debugvar = td->td_proc; 593 struct mount *mp = NULL; 594 struct nlookupdata nd; 595 int error; 596 597 KKASSERT(p); 598 if (td->td_ucred->cr_prison != NULL) { 599 error = EPERM; 600 goto done; 601 } 602 if (usermount == 0 && (error = priv_check(td, PRIV_ROOT))) 603 goto done; 604 605 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 606 if (error == 0) 607 error = nlookup(&nd); 608 if (error) 609 goto out; 610 611 mp = nd.nl_nch.mount; 612 613 /* 614 * Only root, or the user that did the original mount is 615 * permitted to unmount this filesystem. 616 */ 617 if ((mp->mnt_stat.f_owner != td->td_ucred->cr_uid) && 618 (error = priv_check(td, PRIV_ROOT))) 619 goto out; 620 621 /* 622 * Don't allow unmounting the root file system. 623 */ 624 if (mp->mnt_flag & MNT_ROOTFS) { 625 error = EINVAL; 626 goto out; 627 } 628 629 /* 630 * Must be the root of the filesystem 631 */ 632 if (nd.nl_nch.ncp != mp->mnt_ncmountpt.ncp) { 633 error = EINVAL; 634 goto out; 635 } 636 637 /* 638 * If no error try to issue the unmount. We lose our cache 639 * ref when we call nlookup_done so we must hold the mount point 640 * to prevent use-after-free races. 641 */ 642 out: 643 if (error == 0) { 644 mount_hold(mp); 645 nlookup_done(&nd); 646 error = dounmount(mp, uap->flags); 647 mount_drop(mp); 648 } else { 649 nlookup_done(&nd); 650 } 651 done: 652 return (error); 653 } 654 655 /* 656 * Do the actual file system unmount (interlocked against the mountlist 657 * token and mp->mnt_token). 658 */ 659 static int 660 dounmount_interlock(struct mount *mp) 661 { 662 if (mp->mnt_kern_flag & MNTK_UNMOUNT) 663 return (EBUSY); 664 mp->mnt_kern_flag |= MNTK_UNMOUNT; 665 return(0); 666 } 667 668 static int 669 unmount_allproc_cb(struct proc *p, void *arg) 670 { 671 struct mount *mp; 672 673 if (p->p_textnch.ncp == NULL) 674 return 0; 675 676 mp = (struct mount *)arg; 677 if (p->p_textnch.mount == mp) 678 cache_drop(&p->p_textnch); 679 680 return 0; 681 } 682 683 /* 684 * The guts of the unmount code. The mount owns one ref and one hold 685 * count. If we successfully interlock the unmount, those refs are ours. 686 * (The ref is from mnt_ncmountpt). 687 */ 688 int 689 dounmount(struct mount *mp, int flags) 690 { 691 struct namecache *ncp; 692 struct nchandle nch; 693 struct vnode *vp; 694 int error; 695 int async_flag; 696 int lflags; 697 int freeok = 1; 698 int retry; 699 700 lwkt_gettoken(&mp->mnt_token); 701 702 /* 703 * Exclusive access for unmounting purposes. 704 */ 705 if ((error = mountlist_interlock(dounmount_interlock, mp)) != 0) 706 goto out; 707 708 /* 709 * We now 'own' the last mp->mnt_refs 710 * 711 * Allow filesystems to detect that a forced unmount is in progress. 712 */ 713 if (flags & MNT_FORCE) 714 mp->mnt_kern_flag |= MNTK_UNMOUNTF; 715 lflags = LK_EXCLUSIVE | ((flags & MNT_FORCE) ? 0 : LK_TIMELOCK); 716 error = lockmgr(&mp->mnt_lock, lflags); 717 if (error) { 718 mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF); 719 if (mp->mnt_kern_flag & MNTK_MWAIT) { 720 mp->mnt_kern_flag &= ~MNTK_MWAIT; 721 wakeup(mp); 722 } 723 goto out; 724 } 725 726 if (mp->mnt_flag & MNT_EXPUBLIC) 727 vfs_setpublicfs(NULL, NULL, NULL); 728 729 vfs_msync(mp, MNT_WAIT); 730 async_flag = mp->mnt_flag & MNT_ASYNC; 731 mp->mnt_flag &=~ MNT_ASYNC; 732 733 /* 734 * If this filesystem isn't aliasing other filesystems, 735 * try to invalidate any remaining namecache entries and 736 * check the count afterwords. 737 * 738 * We own the last mnt_refs by owning mnt_ncmountpt. 739 */ 740 if ((mp->mnt_kern_flag & MNTK_NCALIASED) == 0) { 741 cache_lock(&mp->mnt_ncmountpt); 742 cache_inval(&mp->mnt_ncmountpt, CINV_DESTROY|CINV_CHILDREN); 743 cache_unlock(&mp->mnt_ncmountpt); 744 745 cache_clearmntcache(); 746 if ((ncp = mp->mnt_ncmountpt.ncp) != NULL && 747 (ncp->nc_refs != 1 || TAILQ_FIRST(&ncp->nc_list))) { 748 allproc_scan(&unmount_allproc_cb, mp, 0); 749 } 750 751 cache_clearmntcache(); 752 if ((ncp = mp->mnt_ncmountpt.ncp) != NULL && 753 (ncp->nc_refs != 1 || TAILQ_FIRST(&ncp->nc_list))) { 754 755 if ((flags & MNT_FORCE) == 0) { 756 error = EBUSY; 757 mount_warning(mp, "Cannot unmount: " 758 "%d namecache " 759 "references still " 760 "present", 761 ncp->nc_refs - 1); 762 } else { 763 mount_warning(mp, "Forced unmount: " 764 "%d namecache " 765 "references still " 766 "present", 767 ncp->nc_refs - 1); 768 freeok = 0; 769 } 770 } 771 } 772 773 /* 774 * Decomission our special mnt_syncer vnode. This also stops 775 * the vnlru code. If we are unable to unmount we recommission 776 * the vnode. 777 * 778 * Then sync the filesystem. 779 */ 780 if ((vp = mp->mnt_syncer) != NULL) { 781 mp->mnt_syncer = NULL; 782 atomic_set_int(&vp->v_refcnt, VREF_FINALIZE); 783 vrele(vp); 784 } 785 if ((mp->mnt_flag & MNT_RDONLY) == 0) 786 VFS_SYNC(mp, MNT_WAIT); 787 788 /* 789 * nchandle records ref the mount structure. Expect a count of 1 790 * (our mount->mnt_ncmountpt). 791 * 792 * Scans can get temporary refs on a mountpoint (thought really 793 * heavy duty stuff like cache_findmount() do not). 794 */ 795 if (mp->mnt_refs != 1) 796 cache_clearmntcache(); 797 for (retry = 0; retry < 10 && mp->mnt_refs != 1; ++retry) { 798 cache_unmounting(mp); 799 tsleep(&mp->mnt_refs, 0, "mntbsy", hz / 10 + 1); 800 cache_clearmntcache(); 801 } 802 if (mp->mnt_refs != 1) { 803 if ((flags & MNT_FORCE) == 0) { 804 mount_warning(mp, "Cannot unmount: " 805 "%d mount refs still present", 806 mp->mnt_refs - 1); 807 error = EBUSY; 808 } else { 809 mount_warning(mp, "Forced unmount: " 810 "%d mount refs still present", 811 mp->mnt_refs - 1); 812 freeok = 0; 813 } 814 } 815 816 /* 817 * So far so good, sync the filesystem once more and 818 * call the VFS unmount code if the sync succeeds. 819 */ 820 if (error == 0) { 821 if (mp->mnt_flag & MNT_RDONLY) { 822 error = VFS_UNMOUNT(mp, flags); 823 } else { 824 error = VFS_SYNC(mp, MNT_WAIT); 825 if ((error == 0) || 826 (error == EOPNOTSUPP) || /* No sync */ 827 (flags & MNT_FORCE)) { 828 error = VFS_UNMOUNT(mp, flags); 829 } 830 } 831 } 832 833 /* 834 * If an error occurred we can still recover, restoring the 835 * syncer vnode and misc flags. 836 */ 837 if (error) { 838 if (mp->mnt_syncer == NULL) 839 vfs_allocate_syncvnode(mp); 840 mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF); 841 mp->mnt_flag |= async_flag; 842 lockmgr(&mp->mnt_lock, LK_RELEASE); 843 if (mp->mnt_kern_flag & MNTK_MWAIT) { 844 mp->mnt_kern_flag &= ~MNTK_MWAIT; 845 wakeup(mp); 846 } 847 goto out; 848 } 849 /* 850 * Clean up any journals still associated with the mount after 851 * filesystem activity has ceased. 852 */ 853 journal_remove_all_journals(mp, 854 ((flags & MNT_FORCE) ? MC_JOURNAL_STOP_IMM : 0)); 855 856 mountlist_remove(mp); 857 858 /* 859 * Remove any installed vnode ops here so the individual VFSs don't 860 * have to. 861 * 862 * mnt_refs should go to zero when we scrap mnt_ncmountpt. 863 */ 864 vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_coherency_ops); 865 vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_journal_ops); 866 vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_norm_ops); 867 vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_spec_ops); 868 vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_fifo_ops); 869 870 if (mp->mnt_ncmountpt.ncp != NULL) { 871 nch = mp->mnt_ncmountpt; 872 cache_zero(&mp->mnt_ncmountpt); 873 cache_clrmountpt(&nch); 874 cache_drop(&nch); 875 } 876 if (mp->mnt_ncmounton.ncp != NULL) { 877 cache_unmounting(mp); 878 nch = mp->mnt_ncmounton; 879 cache_zero(&mp->mnt_ncmounton); 880 cache_clrmountpt(&nch); 881 cache_drop(&nch); 882 } 883 884 mp->mnt_vfc->vfc_refcount--; 885 if (!TAILQ_EMPTY(&mp->mnt_nvnodelist)) 886 panic("unmount: dangling vnode"); 887 888 /* 889 * Release the lock 890 */ 891 lockmgr(&mp->mnt_lock, LK_RELEASE); 892 if (mp->mnt_kern_flag & MNTK_MWAIT) { 893 mp->mnt_kern_flag &= ~MNTK_MWAIT; 894 wakeup(mp); 895 } 896 897 /* 898 * If we reach here and freeok != 0 we must free the mount. 899 * mnt_refs should already have dropped to 0, so if it is not 900 * zero we must cycle the caches and wait. 901 * 902 * When we are satisfied that the mount has disconnected we can 903 * drop the hold on the mp that represented the mount (though the 904 * caller might actually have another, so the caller's drop may 905 * do the actual free). 906 */ 907 if (freeok) { 908 if (mp->mnt_refs > 0) 909 cache_clearmntcache(); 910 while (mp->mnt_refs > 0) { 911 cache_unmounting(mp); 912 wakeup(mp); 913 tsleep(&mp->mnt_refs, 0, "umntrwait", hz / 10 + 1); 914 cache_clearmntcache(); 915 } 916 lwkt_reltoken(&mp->mnt_token); 917 mount_drop(mp); 918 mp = NULL; 919 } 920 error = 0; 921 KNOTE(&fs_klist, VQ_UNMOUNT); 922 out: 923 if (mp) 924 lwkt_reltoken(&mp->mnt_token); 925 return (error); 926 } 927 928 static 929 void 930 mount_warning(struct mount *mp, const char *ctl, ...) 931 { 932 char *ptr; 933 char *buf; 934 __va_list va; 935 936 __va_start(va, ctl); 937 if (cache_fullpath(NULL, &mp->mnt_ncmounton, NULL, 938 &ptr, &buf, 0) == 0) { 939 kprintf("unmount(%s): ", ptr); 940 kvprintf(ctl, va); 941 kprintf("\n"); 942 kfree(buf, M_TEMP); 943 } else { 944 kprintf("unmount(%p", mp); 945 if (mp->mnt_ncmounton.ncp && mp->mnt_ncmounton.ncp->nc_name) 946 kprintf(",%s", mp->mnt_ncmounton.ncp->nc_name); 947 kprintf("): "); 948 kvprintf(ctl, va); 949 kprintf("\n"); 950 } 951 __va_end(va); 952 } 953 954 /* 955 * Shim cache_fullpath() to handle the case where a process is chrooted into 956 * a subdirectory of a mount. In this case if the root mount matches the 957 * process root directory's mount we have to specify the process's root 958 * directory instead of the mount point, because the mount point might 959 * be above the root directory. 960 */ 961 static 962 int 963 mount_path(struct proc *p, struct mount *mp, char **rb, char **fb) 964 { 965 struct nchandle *nch; 966 967 if (p && p->p_fd->fd_nrdir.mount == mp) 968 nch = &p->p_fd->fd_nrdir; 969 else 970 nch = &mp->mnt_ncmountpt; 971 return(cache_fullpath(p, nch, NULL, rb, fb, 0)); 972 } 973 974 /* 975 * Sync each mounted filesystem. 976 */ 977 978 #ifdef DEBUG 979 static int syncprt = 0; 980 SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, ""); 981 #endif /* DEBUG */ 982 983 static int sync_callback(struct mount *mp, void *data); 984 985 int 986 sys_sync(struct sync_args *uap) 987 { 988 mountlist_scan(sync_callback, NULL, MNTSCAN_FORWARD); 989 return (0); 990 } 991 992 static 993 int 994 sync_callback(struct mount *mp, void *data __unused) 995 { 996 int asyncflag; 997 998 if ((mp->mnt_flag & MNT_RDONLY) == 0) { 999 lwkt_gettoken(&mp->mnt_token); 1000 asyncflag = mp->mnt_flag & MNT_ASYNC; 1001 mp->mnt_flag &= ~MNT_ASYNC; 1002 lwkt_reltoken(&mp->mnt_token); 1003 vfs_msync(mp, MNT_NOWAIT); 1004 VFS_SYNC(mp, MNT_NOWAIT); 1005 lwkt_gettoken(&mp->mnt_token); 1006 mp->mnt_flag |= asyncflag; 1007 lwkt_reltoken(&mp->mnt_token); 1008 } 1009 return(0); 1010 } 1011 1012 /* XXX PRISON: could be per prison flag */ 1013 static int prison_quotas; 1014 #if 0 1015 SYSCTL_INT(_kern_prison, OID_AUTO, quotas, CTLFLAG_RW, &prison_quotas, 0, ""); 1016 #endif 1017 1018 /* 1019 * quotactl_args(char *path, int fcmd, int uid, caddr_t arg) 1020 * 1021 * Change filesystem quotas. 1022 * 1023 * MPALMOSTSAFE 1024 */ 1025 int 1026 sys_quotactl(struct quotactl_args *uap) 1027 { 1028 struct nlookupdata nd; 1029 struct thread *td; 1030 struct mount *mp; 1031 int error; 1032 1033 td = curthread; 1034 if (td->td_ucred->cr_prison && !prison_quotas) { 1035 error = EPERM; 1036 goto done; 1037 } 1038 1039 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 1040 if (error == 0) 1041 error = nlookup(&nd); 1042 if (error == 0) { 1043 mp = nd.nl_nch.mount; 1044 error = VFS_QUOTACTL(mp, uap->cmd, uap->uid, 1045 uap->arg, nd.nl_cred); 1046 } 1047 nlookup_done(&nd); 1048 done: 1049 return (error); 1050 } 1051 1052 /* 1053 * mountctl(char *path, int op, int fd, const void *ctl, int ctllen, 1054 * void *buf, int buflen) 1055 * 1056 * This function operates on a mount point and executes the specified 1057 * operation using the specified control data, and possibly returns data. 1058 * 1059 * The actual number of bytes stored in the result buffer is returned, 0 1060 * if none, otherwise an error is returned. 1061 * 1062 * MPALMOSTSAFE 1063 */ 1064 int 1065 sys_mountctl(struct mountctl_args *uap) 1066 { 1067 struct thread *td = curthread; 1068 struct proc *p = td->td_proc; 1069 struct file *fp; 1070 void *ctl = NULL; 1071 void *buf = NULL; 1072 char *path = NULL; 1073 int error; 1074 1075 /* 1076 * Sanity and permissions checks. We must be root. 1077 */ 1078 KKASSERT(p); 1079 if (td->td_ucred->cr_prison != NULL) 1080 return (EPERM); 1081 if ((uap->op != MOUNTCTL_MOUNTFLAGS) && 1082 (error = priv_check(td, PRIV_ROOT)) != 0) 1083 return (error); 1084 1085 /* 1086 * Argument length checks 1087 */ 1088 if (uap->ctllen < 0 || uap->ctllen > 1024) 1089 return (EINVAL); 1090 if (uap->buflen < 0 || uap->buflen > 16 * 1024) 1091 return (EINVAL); 1092 if (uap->path == NULL) 1093 return (EINVAL); 1094 1095 /* 1096 * Allocate the necessary buffers and copyin data 1097 */ 1098 path = objcache_get(namei_oc, M_WAITOK); 1099 error = copyinstr(uap->path, path, MAXPATHLEN, NULL); 1100 if (error) 1101 goto done; 1102 1103 if (uap->ctllen) { 1104 ctl = kmalloc(uap->ctllen + 1, M_TEMP, M_WAITOK|M_ZERO); 1105 error = copyin(uap->ctl, ctl, uap->ctllen); 1106 if (error) 1107 goto done; 1108 } 1109 if (uap->buflen) 1110 buf = kmalloc(uap->buflen + 1, M_TEMP, M_WAITOK|M_ZERO); 1111 1112 /* 1113 * Validate the descriptor 1114 */ 1115 if (uap->fd >= 0) { 1116 fp = holdfp(p->p_fd, uap->fd, -1); 1117 if (fp == NULL) { 1118 error = EBADF; 1119 goto done; 1120 } 1121 } else { 1122 fp = NULL; 1123 } 1124 1125 /* 1126 * Execute the internal kernel function and clean up. 1127 */ 1128 error = kern_mountctl(path, uap->op, fp, ctl, uap->ctllen, buf, uap->buflen, &uap->sysmsg_result); 1129 if (fp) 1130 fdrop(fp); 1131 if (error == 0 && uap->sysmsg_result > 0) 1132 error = copyout(buf, uap->buf, uap->sysmsg_result); 1133 done: 1134 if (path) 1135 objcache_put(namei_oc, path); 1136 if (ctl) 1137 kfree(ctl, M_TEMP); 1138 if (buf) 1139 kfree(buf, M_TEMP); 1140 return (error); 1141 } 1142 1143 /* 1144 * Execute a mount control operation by resolving the path to a mount point 1145 * and calling vop_mountctl(). 1146 * 1147 * Use the mount point from the nch instead of the vnode so nullfs mounts 1148 * can properly spike the VOP. 1149 */ 1150 int 1151 kern_mountctl(const char *path, int op, struct file *fp, 1152 const void *ctl, int ctllen, 1153 void *buf, int buflen, int *res) 1154 { 1155 struct vnode *vp; 1156 struct nlookupdata nd; 1157 struct nchandle nch; 1158 struct mount *mp; 1159 int error; 1160 1161 *res = 0; 1162 vp = NULL; 1163 error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW); 1164 if (error) 1165 return (error); 1166 error = nlookup(&nd); 1167 if (error) { 1168 nlookup_done(&nd); 1169 return (error); 1170 } 1171 error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp); 1172 if (error) { 1173 nlookup_done(&nd); 1174 return (error); 1175 } 1176 1177 /* 1178 * Yes, all this is needed to use the nch.mount below, because 1179 * we must maintain a ref on the mount to avoid ripouts (e.g. 1180 * due to heavy mount/unmount use by synth or poudriere). 1181 */ 1182 nch = nd.nl_nch; 1183 cache_zero(&nd.nl_nch); 1184 cache_unlock(&nch); 1185 nlookup_done(&nd); 1186 vn_unlock(vp); 1187 1188 mp = nch.mount; 1189 1190 /* 1191 * Must be the root of the filesystem 1192 */ 1193 if ((vp->v_flag & (VROOT|VPFSROOT)) == 0) { 1194 cache_drop(&nch); 1195 vrele(vp); 1196 return (EINVAL); 1197 } 1198 if (mp == NULL || mp->mnt_kern_flag & MNTK_UNMOUNT) { 1199 kprintf("kern_mountctl: Warning, \"%s\" racing unmount\n", 1200 path); 1201 cache_drop(&nch); 1202 vrele(vp); 1203 return (EINVAL); 1204 } 1205 error = vop_mountctl(mp->mnt_vn_use_ops, vp, op, fp, ctl, ctllen, 1206 buf, buflen, res); 1207 vrele(vp); 1208 cache_drop(&nch); 1209 1210 return (error); 1211 } 1212 1213 int 1214 kern_statfs(struct nlookupdata *nd, struct statfs *buf) 1215 { 1216 struct thread *td = curthread; 1217 struct proc *p = td->td_proc; 1218 struct mount *mp; 1219 struct statfs *sp; 1220 char *fullpath, *freepath; 1221 int error; 1222 1223 if ((error = nlookup(nd)) != 0) 1224 return (error); 1225 mp = nd->nl_nch.mount; 1226 sp = &mp->mnt_stat; 1227 if ((error = VFS_STATFS(mp, sp, nd->nl_cred)) != 0) 1228 return (error); 1229 1230 error = mount_path(p, mp, &fullpath, &freepath); 1231 if (error) 1232 return(error); 1233 bzero(sp->f_mntonname, sizeof(sp->f_mntonname)); 1234 strlcpy(sp->f_mntonname, fullpath, sizeof(sp->f_mntonname)); 1235 kfree(freepath, M_TEMP); 1236 1237 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 1238 bcopy(sp, buf, sizeof(*buf)); 1239 /* Only root should have access to the fsid's. */ 1240 if (priv_check(td, PRIV_ROOT)) 1241 buf->f_fsid.val[0] = buf->f_fsid.val[1] = 0; 1242 return (0); 1243 } 1244 1245 /* 1246 * statfs_args(char *path, struct statfs *buf) 1247 * 1248 * Get filesystem statistics. 1249 */ 1250 int 1251 sys_statfs(struct statfs_args *uap) 1252 { 1253 struct nlookupdata nd; 1254 struct statfs buf; 1255 int error; 1256 1257 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 1258 if (error == 0) 1259 error = kern_statfs(&nd, &buf); 1260 nlookup_done(&nd); 1261 if (error == 0) 1262 error = copyout(&buf, uap->buf, sizeof(*uap->buf)); 1263 return (error); 1264 } 1265 1266 int 1267 kern_fstatfs(int fd, struct statfs *buf) 1268 { 1269 struct thread *td = curthread; 1270 struct proc *p = td->td_proc; 1271 struct file *fp; 1272 struct mount *mp; 1273 struct statfs *sp; 1274 char *fullpath, *freepath; 1275 int error; 1276 1277 KKASSERT(p); 1278 if ((error = holdvnode(p->p_fd, fd, &fp)) != 0) 1279 return (error); 1280 1281 /* 1282 * Try to use mount info from any overlays rather than the 1283 * mount info for the underlying vnode, otherwise we will 1284 * fail when operating on null-mounted paths inside a chroot. 1285 */ 1286 if ((mp = fp->f_nchandle.mount) == NULL) 1287 mp = ((struct vnode *)fp->f_data)->v_mount; 1288 if (mp == NULL) { 1289 error = EBADF; 1290 goto done; 1291 } 1292 if (fp->f_cred == NULL) { 1293 error = EINVAL; 1294 goto done; 1295 } 1296 sp = &mp->mnt_stat; 1297 if ((error = VFS_STATFS(mp, sp, fp->f_cred)) != 0) 1298 goto done; 1299 1300 if ((error = mount_path(p, mp, &fullpath, &freepath)) != 0) 1301 goto done; 1302 bzero(sp->f_mntonname, sizeof(sp->f_mntonname)); 1303 strlcpy(sp->f_mntonname, fullpath, sizeof(sp->f_mntonname)); 1304 kfree(freepath, M_TEMP); 1305 1306 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 1307 bcopy(sp, buf, sizeof(*buf)); 1308 1309 /* Only root should have access to the fsid's. */ 1310 if (priv_check(td, PRIV_ROOT)) 1311 buf->f_fsid.val[0] = buf->f_fsid.val[1] = 0; 1312 error = 0; 1313 done: 1314 fdrop(fp); 1315 return (error); 1316 } 1317 1318 /* 1319 * fstatfs_args(int fd, struct statfs *buf) 1320 * 1321 * Get filesystem statistics. 1322 */ 1323 int 1324 sys_fstatfs(struct fstatfs_args *uap) 1325 { 1326 struct statfs buf; 1327 int error; 1328 1329 error = kern_fstatfs(uap->fd, &buf); 1330 1331 if (error == 0) 1332 error = copyout(&buf, uap->buf, sizeof(*uap->buf)); 1333 return (error); 1334 } 1335 1336 int 1337 kern_statvfs(struct nlookupdata *nd, struct statvfs *buf) 1338 { 1339 struct mount *mp; 1340 struct statvfs *sp; 1341 int error; 1342 1343 if ((error = nlookup(nd)) != 0) 1344 return (error); 1345 mp = nd->nl_nch.mount; 1346 sp = &mp->mnt_vstat; 1347 if ((error = VFS_STATVFS(mp, sp, nd->nl_cred)) != 0) 1348 return (error); 1349 1350 sp->f_flag = 0; 1351 if (mp->mnt_flag & MNT_RDONLY) 1352 sp->f_flag |= ST_RDONLY; 1353 if (mp->mnt_flag & MNT_NOSUID) 1354 sp->f_flag |= ST_NOSUID; 1355 bcopy(sp, buf, sizeof(*buf)); 1356 return (0); 1357 } 1358 1359 /* 1360 * statfs_args(char *path, struct statfs *buf) 1361 * 1362 * Get filesystem statistics. 1363 */ 1364 int 1365 sys_statvfs(struct statvfs_args *uap) 1366 { 1367 struct nlookupdata nd; 1368 struct statvfs buf; 1369 int error; 1370 1371 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 1372 if (error == 0) 1373 error = kern_statvfs(&nd, &buf); 1374 nlookup_done(&nd); 1375 if (error == 0) 1376 error = copyout(&buf, uap->buf, sizeof(*uap->buf)); 1377 return (error); 1378 } 1379 1380 int 1381 kern_fstatvfs(int fd, struct statvfs *buf) 1382 { 1383 struct thread *td = curthread; 1384 struct proc *p = td->td_proc; 1385 struct file *fp; 1386 struct mount *mp; 1387 struct statvfs *sp; 1388 int error; 1389 1390 KKASSERT(p); 1391 if ((error = holdvnode(p->p_fd, fd, &fp)) != 0) 1392 return (error); 1393 if ((mp = fp->f_nchandle.mount) == NULL) 1394 mp = ((struct vnode *)fp->f_data)->v_mount; 1395 if (mp == NULL) { 1396 error = EBADF; 1397 goto done; 1398 } 1399 if (fp->f_cred == NULL) { 1400 error = EINVAL; 1401 goto done; 1402 } 1403 sp = &mp->mnt_vstat; 1404 if ((error = VFS_STATVFS(mp, sp, fp->f_cred)) != 0) 1405 goto done; 1406 1407 sp->f_flag = 0; 1408 if (mp->mnt_flag & MNT_RDONLY) 1409 sp->f_flag |= ST_RDONLY; 1410 if (mp->mnt_flag & MNT_NOSUID) 1411 sp->f_flag |= ST_NOSUID; 1412 1413 bcopy(sp, buf, sizeof(*buf)); 1414 error = 0; 1415 done: 1416 fdrop(fp); 1417 return (error); 1418 } 1419 1420 /* 1421 * fstatfs_args(int fd, struct statfs *buf) 1422 * 1423 * Get filesystem statistics. 1424 */ 1425 int 1426 sys_fstatvfs(struct fstatvfs_args *uap) 1427 { 1428 struct statvfs buf; 1429 int error; 1430 1431 error = kern_fstatvfs(uap->fd, &buf); 1432 1433 if (error == 0) 1434 error = copyout(&buf, uap->buf, sizeof(*uap->buf)); 1435 return (error); 1436 } 1437 1438 /* 1439 * getfsstat_args(struct statfs *buf, long bufsize, int flags) 1440 * 1441 * Get statistics on all filesystems. 1442 */ 1443 1444 struct getfsstat_info { 1445 struct statfs *sfsp; 1446 long count; 1447 long maxcount; 1448 int error; 1449 int flags; 1450 struct thread *td; 1451 }; 1452 1453 static int getfsstat_callback(struct mount *, void *); 1454 1455 int 1456 sys_getfsstat(struct getfsstat_args *uap) 1457 { 1458 struct thread *td = curthread; 1459 struct getfsstat_info info; 1460 1461 bzero(&info, sizeof(info)); 1462 1463 info.maxcount = uap->bufsize / sizeof(struct statfs); 1464 info.sfsp = uap->buf; 1465 info.count = 0; 1466 info.flags = uap->flags; 1467 info.td = td; 1468 1469 mountlist_scan(getfsstat_callback, &info, MNTSCAN_FORWARD); 1470 if (info.sfsp && info.count > info.maxcount) 1471 uap->sysmsg_result = info.maxcount; 1472 else 1473 uap->sysmsg_result = info.count; 1474 return (info.error); 1475 } 1476 1477 static int 1478 getfsstat_callback(struct mount *mp, void *data) 1479 { 1480 struct getfsstat_info *info = data; 1481 struct statfs *sp; 1482 char *freepath; 1483 char *fullpath; 1484 int error; 1485 1486 if (info->sfsp && info->count < info->maxcount) { 1487 if (info->td->td_proc && 1488 !chroot_visible_mnt(mp, info->td->td_proc)) { 1489 return(0); 1490 } 1491 sp = &mp->mnt_stat; 1492 1493 /* 1494 * If MNT_NOWAIT or MNT_LAZY is specified, do not 1495 * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY 1496 * overrides MNT_WAIT. 1497 */ 1498 if (((info->flags & (MNT_LAZY|MNT_NOWAIT)) == 0 || 1499 (info->flags & MNT_WAIT)) && 1500 (error = VFS_STATFS(mp, sp, info->td->td_ucred))) { 1501 return(0); 1502 } 1503 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 1504 1505 error = mount_path(info->td->td_proc, mp, &fullpath, &freepath); 1506 if (error) { 1507 info->error = error; 1508 return(-1); 1509 } 1510 bzero(sp->f_mntonname, sizeof(sp->f_mntonname)); 1511 strlcpy(sp->f_mntonname, fullpath, sizeof(sp->f_mntonname)); 1512 kfree(freepath, M_TEMP); 1513 1514 error = copyout(sp, info->sfsp, sizeof(*sp)); 1515 if (error) { 1516 info->error = error; 1517 return (-1); 1518 } 1519 ++info->sfsp; 1520 } 1521 info->count++; 1522 return(0); 1523 } 1524 1525 /* 1526 * getvfsstat_args(struct statfs *buf, struct statvfs *vbuf, 1527 long bufsize, int flags) 1528 * 1529 * Get statistics on all filesystems. 1530 */ 1531 1532 struct getvfsstat_info { 1533 struct statfs *sfsp; 1534 struct statvfs *vsfsp; 1535 long count; 1536 long maxcount; 1537 int error; 1538 int flags; 1539 struct thread *td; 1540 }; 1541 1542 static int getvfsstat_callback(struct mount *, void *); 1543 1544 int 1545 sys_getvfsstat(struct getvfsstat_args *uap) 1546 { 1547 struct thread *td = curthread; 1548 struct getvfsstat_info info; 1549 1550 bzero(&info, sizeof(info)); 1551 1552 info.maxcount = uap->vbufsize / sizeof(struct statvfs); 1553 info.sfsp = uap->buf; 1554 info.vsfsp = uap->vbuf; 1555 info.count = 0; 1556 info.flags = uap->flags; 1557 info.td = td; 1558 1559 mountlist_scan(getvfsstat_callback, &info, MNTSCAN_FORWARD); 1560 if (info.vsfsp && info.count > info.maxcount) 1561 uap->sysmsg_result = info.maxcount; 1562 else 1563 uap->sysmsg_result = info.count; 1564 return (info.error); 1565 } 1566 1567 static int 1568 getvfsstat_callback(struct mount *mp, void *data) 1569 { 1570 struct getvfsstat_info *info = data; 1571 struct statfs *sp; 1572 struct statvfs *vsp; 1573 char *freepath; 1574 char *fullpath; 1575 int error; 1576 1577 if (info->vsfsp && info->count < info->maxcount) { 1578 if (info->td->td_proc && 1579 !chroot_visible_mnt(mp, info->td->td_proc)) { 1580 return(0); 1581 } 1582 sp = &mp->mnt_stat; 1583 vsp = &mp->mnt_vstat; 1584 1585 /* 1586 * If MNT_NOWAIT or MNT_LAZY is specified, do not 1587 * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY 1588 * overrides MNT_WAIT. 1589 */ 1590 if (((info->flags & (MNT_LAZY|MNT_NOWAIT)) == 0 || 1591 (info->flags & MNT_WAIT)) && 1592 (error = VFS_STATFS(mp, sp, info->td->td_ucred))) { 1593 return(0); 1594 } 1595 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 1596 1597 if (((info->flags & (MNT_LAZY|MNT_NOWAIT)) == 0 || 1598 (info->flags & MNT_WAIT)) && 1599 (error = VFS_STATVFS(mp, vsp, info->td->td_ucred))) { 1600 return(0); 1601 } 1602 vsp->f_flag = 0; 1603 if (mp->mnt_flag & MNT_RDONLY) 1604 vsp->f_flag |= ST_RDONLY; 1605 if (mp->mnt_flag & MNT_NOSUID) 1606 vsp->f_flag |= ST_NOSUID; 1607 1608 error = mount_path(info->td->td_proc, mp, &fullpath, &freepath); 1609 if (error) { 1610 info->error = error; 1611 return(-1); 1612 } 1613 bzero(sp->f_mntonname, sizeof(sp->f_mntonname)); 1614 strlcpy(sp->f_mntonname, fullpath, sizeof(sp->f_mntonname)); 1615 kfree(freepath, M_TEMP); 1616 1617 error = copyout(sp, info->sfsp, sizeof(*sp)); 1618 if (error == 0) 1619 error = copyout(vsp, info->vsfsp, sizeof(*vsp)); 1620 if (error) { 1621 info->error = error; 1622 return (-1); 1623 } 1624 ++info->sfsp; 1625 ++info->vsfsp; 1626 } 1627 info->count++; 1628 return(0); 1629 } 1630 1631 1632 /* 1633 * fchdir_args(int fd) 1634 * 1635 * Change current working directory to a given file descriptor. 1636 */ 1637 int 1638 sys_fchdir(struct fchdir_args *uap) 1639 { 1640 struct thread *td = curthread; 1641 struct proc *p = td->td_proc; 1642 struct filedesc *fdp = p->p_fd; 1643 struct vnode *vp, *ovp; 1644 struct mount *mp; 1645 struct file *fp; 1646 struct nchandle nch, onch, tnch; 1647 int error; 1648 1649 if ((error = holdvnode(fdp, uap->fd, &fp)) != 0) 1650 return (error); 1651 lwkt_gettoken(&p->p_token); 1652 vp = (struct vnode *)fp->f_data; 1653 vref(vp); 1654 vn_lock(vp, LK_SHARED | LK_RETRY); 1655 if (fp->f_nchandle.ncp == NULL) 1656 error = ENOTDIR; 1657 else 1658 error = checkvp_chdir(vp, td); 1659 if (error) { 1660 vput(vp); 1661 goto done; 1662 } 1663 cache_copy(&fp->f_nchandle, &nch); 1664 1665 /* 1666 * If the ncp has become a mount point, traverse through 1667 * the mount point. 1668 */ 1669 1670 while (!error && (nch.ncp->nc_flag & NCF_ISMOUNTPT) && 1671 (mp = cache_findmount(&nch)) != NULL 1672 ) { 1673 error = nlookup_mp(mp, &tnch); 1674 if (error == 0) { 1675 cache_unlock(&tnch); /* leave ref intact */ 1676 vput(vp); 1677 vp = tnch.ncp->nc_vp; 1678 error = vget(vp, LK_SHARED); 1679 KKASSERT(error == 0); 1680 cache_drop(&nch); 1681 nch = tnch; 1682 } 1683 cache_dropmount(mp); 1684 } 1685 if (error == 0) { 1686 spin_lock(&fdp->fd_spin); 1687 ovp = fdp->fd_cdir; 1688 onch = fdp->fd_ncdir; 1689 fdp->fd_cdir = vp; 1690 fdp->fd_ncdir = nch; 1691 spin_unlock(&fdp->fd_spin); 1692 vn_unlock(vp); /* leave ref intact */ 1693 cache_drop(&onch); 1694 vrele(ovp); 1695 } else { 1696 cache_drop(&nch); 1697 vput(vp); 1698 } 1699 fdrop(fp); 1700 done: 1701 lwkt_reltoken(&p->p_token); 1702 return (error); 1703 } 1704 1705 int 1706 kern_chdir(struct nlookupdata *nd) 1707 { 1708 struct thread *td = curthread; 1709 struct proc *p = td->td_proc; 1710 struct filedesc *fdp = p->p_fd; 1711 struct vnode *vp, *ovp; 1712 struct nchandle onch; 1713 int error; 1714 1715 nd->nl_flags |= NLC_SHAREDLOCK; 1716 if ((error = nlookup(nd)) != 0) 1717 return (error); 1718 if ((vp = nd->nl_nch.ncp->nc_vp) == NULL) 1719 return (ENOENT); 1720 if ((error = vget(vp, LK_SHARED)) != 0) 1721 return (error); 1722 1723 lwkt_gettoken(&p->p_token); 1724 error = checkvp_chdir(vp, td); 1725 vn_unlock(vp); 1726 if (error == 0) { 1727 spin_lock(&fdp->fd_spin); 1728 ovp = fdp->fd_cdir; 1729 onch = fdp->fd_ncdir; 1730 fdp->fd_ncdir = nd->nl_nch; 1731 fdp->fd_cdir = vp; 1732 spin_unlock(&fdp->fd_spin); 1733 cache_unlock(&nd->nl_nch); /* leave reference intact */ 1734 cache_drop(&onch); 1735 vrele(ovp); 1736 cache_zero(&nd->nl_nch); 1737 } else { 1738 vrele(vp); 1739 } 1740 lwkt_reltoken(&p->p_token); 1741 return (error); 1742 } 1743 1744 /* 1745 * chdir_args(char *path) 1746 * 1747 * Change current working directory (``.''). 1748 */ 1749 int 1750 sys_chdir(struct chdir_args *uap) 1751 { 1752 struct nlookupdata nd; 1753 int error; 1754 1755 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 1756 if (error == 0) 1757 error = kern_chdir(&nd); 1758 nlookup_done(&nd); 1759 return (error); 1760 } 1761 1762 /* 1763 * Helper function for raised chroot(2) security function: Refuse if 1764 * any filedescriptors are open directories. 1765 */ 1766 static int 1767 chroot_refuse_vdir_fds(struct filedesc *fdp) 1768 { 1769 struct vnode *vp; 1770 struct file *fp; 1771 int error; 1772 int fd; 1773 1774 for (fd = 0; fd < fdp->fd_nfiles ; fd++) { 1775 if ((error = holdvnode(fdp, fd, &fp)) != 0) 1776 continue; 1777 vp = (struct vnode *)fp->f_data; 1778 if (vp->v_type != VDIR) { 1779 fdrop(fp); 1780 continue; 1781 } 1782 fdrop(fp); 1783 return(EPERM); 1784 } 1785 return (0); 1786 } 1787 1788 /* 1789 * This sysctl determines if we will allow a process to chroot(2) if it 1790 * has a directory open: 1791 * 0: disallowed for all processes. 1792 * 1: allowed for processes that were not already chroot(2)'ed. 1793 * 2: allowed for all processes. 1794 */ 1795 1796 static int chroot_allow_open_directories = 1; 1797 1798 SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW, 1799 &chroot_allow_open_directories, 0, ""); 1800 1801 /* 1802 * chroot to the specified namecache entry. We obtain the vp from the 1803 * namecache data. The passed ncp must be locked and referenced and will 1804 * remain locked and referenced on return. 1805 */ 1806 int 1807 kern_chroot(struct nchandle *nch) 1808 { 1809 struct thread *td = curthread; 1810 struct proc *p = td->td_proc; 1811 struct filedesc *fdp = p->p_fd; 1812 struct vnode *vp; 1813 int error; 1814 1815 /* 1816 * Only privileged user can chroot 1817 */ 1818 error = priv_check_cred(td->td_ucred, PRIV_VFS_CHROOT, 0); 1819 if (error) 1820 return (error); 1821 1822 /* 1823 * Disallow open directory descriptors (fchdir() breakouts). 1824 */ 1825 if (chroot_allow_open_directories == 0 || 1826 (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) { 1827 if ((error = chroot_refuse_vdir_fds(fdp)) != 0) 1828 return (error); 1829 } 1830 if ((vp = nch->ncp->nc_vp) == NULL) 1831 return (ENOENT); 1832 1833 if ((error = vget(vp, LK_SHARED)) != 0) 1834 return (error); 1835 1836 /* 1837 * Check the validity of vp as a directory to change to and 1838 * associate it with rdir/jdir. 1839 */ 1840 error = checkvp_chdir(vp, td); 1841 vn_unlock(vp); /* leave reference intact */ 1842 if (error == 0) { 1843 lwkt_gettoken(&p->p_token); 1844 vrele(fdp->fd_rdir); 1845 fdp->fd_rdir = vp; /* reference inherited by fd_rdir */ 1846 cache_drop(&fdp->fd_nrdir); 1847 cache_copy(nch, &fdp->fd_nrdir); 1848 if (fdp->fd_jdir == NULL) { 1849 fdp->fd_jdir = vp; 1850 vref(fdp->fd_jdir); 1851 cache_copy(nch, &fdp->fd_njdir); 1852 } 1853 if ((p->p_flags & P_DIDCHROOT) == 0) { 1854 p->p_flags |= P_DIDCHROOT; 1855 if (p->p_depth <= 65535 - 32) 1856 p->p_depth += 32; 1857 } 1858 lwkt_reltoken(&p->p_token); 1859 } else { 1860 vrele(vp); 1861 } 1862 return (error); 1863 } 1864 1865 /* 1866 * chroot_args(char *path) 1867 * 1868 * Change notion of root (``/'') directory. 1869 */ 1870 int 1871 sys_chroot(struct chroot_args *uap) 1872 { 1873 struct thread *td __debugvar = curthread; 1874 struct nlookupdata nd; 1875 int error; 1876 1877 KKASSERT(td->td_proc); 1878 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 1879 if (error == 0) { 1880 nd.nl_flags |= NLC_EXEC; 1881 error = nlookup(&nd); 1882 if (error == 0) 1883 error = kern_chroot(&nd.nl_nch); 1884 } 1885 nlookup_done(&nd); 1886 return(error); 1887 } 1888 1889 int 1890 sys_chroot_kernel(struct chroot_kernel_args *uap) 1891 { 1892 struct thread *td = curthread; 1893 struct nlookupdata nd; 1894 struct nchandle *nch; 1895 struct vnode *vp; 1896 int error; 1897 1898 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 1899 if (error) 1900 goto error_nond; 1901 1902 error = nlookup(&nd); 1903 if (error) 1904 goto error_out; 1905 1906 nch = &nd.nl_nch; 1907 1908 error = priv_check_cred(td->td_ucred, PRIV_VFS_CHROOT, 0); 1909 if (error) 1910 goto error_out; 1911 1912 if ((vp = nch->ncp->nc_vp) == NULL) { 1913 error = ENOENT; 1914 goto error_out; 1915 } 1916 1917 if ((error = cache_vref(nch, nd.nl_cred, &vp)) != 0) 1918 goto error_out; 1919 1920 kprintf("chroot_kernel: set new rootnch/rootvnode to %s\n", uap->path); 1921 vfs_cache_setroot(vp, cache_hold(nch)); 1922 1923 error_out: 1924 nlookup_done(&nd); 1925 error_nond: 1926 return(error); 1927 } 1928 1929 /* 1930 * Common routine for chroot and chdir. Given a locked, referenced vnode, 1931 * determine whether it is legal to chdir to the vnode. The vnode's state 1932 * is not changed by this call. 1933 */ 1934 static int 1935 checkvp_chdir(struct vnode *vp, struct thread *td) 1936 { 1937 int error; 1938 1939 if (vp->v_type != VDIR) 1940 error = ENOTDIR; 1941 else 1942 error = VOP_EACCESS(vp, VEXEC, td->td_ucred); 1943 return (error); 1944 } 1945 1946 int 1947 kern_open(struct nlookupdata *nd, int oflags, int mode, int *res) 1948 { 1949 struct thread *td = curthread; 1950 struct proc *p = td->td_proc; 1951 struct lwp *lp = td->td_lwp; 1952 struct filedesc *fdp = p->p_fd; 1953 int cmode, flags; 1954 struct file *nfp; 1955 struct file *fp; 1956 struct vnode *vp; 1957 int type, indx, error = 0; 1958 struct flock lf; 1959 1960 if ((oflags & O_ACCMODE) == O_ACCMODE) 1961 return (EINVAL); 1962 flags = FFLAGS(oflags); 1963 error = falloc(lp, &nfp, NULL); 1964 if (error) 1965 return (error); 1966 fp = nfp; 1967 cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) & ~S_ISTXT; 1968 1969 /* 1970 * XXX p_dupfd is a real mess. It allows a device to return a 1971 * file descriptor to be duplicated rather then doing the open 1972 * itself. 1973 */ 1974 lp->lwp_dupfd = -1; 1975 1976 /* 1977 * Call vn_open() to do the lookup and assign the vnode to the 1978 * file pointer. vn_open() does not change the ref count on fp 1979 * and the vnode, on success, will be inherited by the file pointer 1980 * and unlocked. 1981 * 1982 * Request a shared lock on the vnode if possible. 1983 * 1984 * Executable binaries can race VTEXT against O_RDWR opens, so 1985 * use an exclusive lock for O_RDWR opens as well. 1986 * 1987 * NOTE: We need a flag to separate terminal vnode locking from 1988 * parent locking. O_CREAT needs parent locking, but O_TRUNC 1989 * and O_RDWR only need to lock the terminal vnode exclusively. 1990 */ 1991 nd->nl_flags |= NLC_LOCKVP; 1992 if ((flags & (O_CREAT|O_TRUNC|O_RDWR)) == 0) 1993 nd->nl_flags |= NLC_SHAREDLOCK; 1994 1995 error = vn_open(nd, fp, flags, cmode); 1996 nlookup_done(nd); 1997 1998 if (error) { 1999 /* 2000 * handle special fdopen() case. bleh. dupfdopen() is 2001 * responsible for dropping the old contents of ofiles[indx] 2002 * if it succeeds. 2003 * 2004 * Note that fsetfd() will add a ref to fp which represents 2005 * the fd_files[] assignment. We must still drop our 2006 * reference. 2007 */ 2008 if ((error == ENODEV || error == ENXIO) && lp->lwp_dupfd >= 0) { 2009 if (fdalloc(p, 0, &indx) == 0) { 2010 error = dupfdopen(fdp, indx, lp->lwp_dupfd, flags, error); 2011 if (error == 0) { 2012 *res = indx; 2013 fdrop(fp); /* our ref */ 2014 return (0); 2015 } 2016 fsetfd(fdp, NULL, indx); 2017 } 2018 } 2019 fdrop(fp); /* our ref */ 2020 if (error == ERESTART) 2021 error = EINTR; 2022 return (error); 2023 } 2024 2025 /* 2026 * ref the vnode for ourselves so it can't be ripped out from under 2027 * is. XXX need an ND flag to request that the vnode be returned 2028 * anyway. 2029 * 2030 * Reserve a file descriptor but do not assign it until the open 2031 * succeeds. 2032 */ 2033 vp = (struct vnode *)fp->f_data; 2034 vref(vp); 2035 if ((error = fdalloc(p, 0, &indx)) != 0) { 2036 fdrop(fp); 2037 vrele(vp); 2038 return (error); 2039 } 2040 2041 /* 2042 * If no error occurs the vp will have been assigned to the file 2043 * pointer. 2044 */ 2045 lp->lwp_dupfd = 0; 2046 2047 if (flags & (O_EXLOCK | O_SHLOCK)) { 2048 lf.l_whence = SEEK_SET; 2049 lf.l_start = 0; 2050 lf.l_len = 0; 2051 if (flags & O_EXLOCK) 2052 lf.l_type = F_WRLCK; 2053 else 2054 lf.l_type = F_RDLCK; 2055 if (flags & FNONBLOCK) 2056 type = 0; 2057 else 2058 type = F_WAIT; 2059 2060 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) { 2061 /* 2062 * lock request failed. Clean up the reserved 2063 * descriptor. 2064 */ 2065 vrele(vp); 2066 fsetfd(fdp, NULL, indx); 2067 fdrop(fp); 2068 return (error); 2069 } 2070 atomic_set_int(&fp->f_flag, FHASLOCK); /* race ok */ 2071 } 2072 #if 0 2073 /* 2074 * Assert that all regular file vnodes were created with a object. 2075 */ 2076 KASSERT(vp->v_type != VREG || vp->v_object != NULL, 2077 ("open: regular file has no backing object after vn_open")); 2078 #endif 2079 2080 vrele(vp); 2081 2082 /* 2083 * release our private reference, leaving the one associated with the 2084 * descriptor table intact. 2085 */ 2086 if (oflags & O_CLOEXEC) 2087 fdp->fd_files[indx].fileflags |= UF_EXCLOSE; 2088 fsetfd(fdp, fp, indx); 2089 fdrop(fp); 2090 *res = indx; 2091 return (error); 2092 } 2093 2094 /* 2095 * open_args(char *path, int flags, int mode) 2096 * 2097 * Check permissions, allocate an open file structure, 2098 * and call the device open routine if any. 2099 */ 2100 int 2101 sys_open(struct open_args *uap) 2102 { 2103 struct nlookupdata nd; 2104 int error; 2105 2106 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0); 2107 if (error == 0) { 2108 error = kern_open(&nd, uap->flags, 2109 uap->mode, &uap->sysmsg_result); 2110 } 2111 nlookup_done(&nd); 2112 return (error); 2113 } 2114 2115 /* 2116 * openat_args(int fd, char *path, int flags, int mode) 2117 */ 2118 int 2119 sys_openat(struct openat_args *uap) 2120 { 2121 struct nlookupdata nd; 2122 int error; 2123 struct file *fp; 2124 2125 error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, UIO_USERSPACE, 0); 2126 if (error == 0) { 2127 error = kern_open(&nd, uap->flags, uap->mode, 2128 &uap->sysmsg_result); 2129 } 2130 nlookup_done_at(&nd, fp); 2131 return (error); 2132 } 2133 2134 int 2135 kern_mknod(struct nlookupdata *nd, int mode, int rmajor, int rminor) 2136 { 2137 struct thread *td = curthread; 2138 struct proc *p = td->td_proc; 2139 struct vnode *vp; 2140 struct vattr vattr; 2141 int error; 2142 int whiteout = 0; 2143 2144 KKASSERT(p); 2145 2146 VATTR_NULL(&vattr); 2147 vattr.va_mode = (mode & ALLPERMS) &~ p->p_fd->fd_cmask; 2148 vattr.va_rmajor = rmajor; 2149 vattr.va_rminor = rminor; 2150 2151 switch (mode & S_IFMT) { 2152 case S_IFMT: /* used by badsect to flag bad sectors */ 2153 error = priv_check_cred(td->td_ucred, PRIV_VFS_MKNOD_BAD, 0); 2154 vattr.va_type = VBAD; 2155 break; 2156 case S_IFCHR: 2157 error = priv_check(td, PRIV_VFS_MKNOD_DEV); 2158 vattr.va_type = VCHR; 2159 break; 2160 case S_IFBLK: 2161 error = priv_check(td, PRIV_VFS_MKNOD_DEV); 2162 vattr.va_type = VBLK; 2163 break; 2164 case S_IFWHT: 2165 error = priv_check_cred(td->td_ucred, PRIV_VFS_MKNOD_WHT, 0); 2166 whiteout = 1; 2167 break; 2168 case S_IFDIR: /* special directories support for HAMMER */ 2169 error = priv_check_cred(td->td_ucred, PRIV_VFS_MKNOD_DIR, 0); 2170 vattr.va_type = VDIR; 2171 break; 2172 default: 2173 error = EINVAL; 2174 break; 2175 } 2176 2177 if (error) 2178 return (error); 2179 2180 bwillinode(1); 2181 nd->nl_flags |= NLC_CREATE | NLC_REFDVP; 2182 if ((error = nlookup(nd)) != 0) 2183 return (error); 2184 if (nd->nl_nch.ncp->nc_vp) 2185 return (EEXIST); 2186 if ((error = ncp_writechk(&nd->nl_nch)) != 0) 2187 return (error); 2188 2189 if (whiteout) { 2190 error = VOP_NWHITEOUT(&nd->nl_nch, nd->nl_dvp, 2191 nd->nl_cred, NAMEI_CREATE); 2192 } else { 2193 vp = NULL; 2194 error = VOP_NMKNOD(&nd->nl_nch, nd->nl_dvp, 2195 &vp, nd->nl_cred, &vattr); 2196 if (error == 0) 2197 vput(vp); 2198 } 2199 return (error); 2200 } 2201 2202 /* 2203 * mknod_args(char *path, int mode, int dev) 2204 * 2205 * Create a special file. 2206 */ 2207 int 2208 sys_mknod(struct mknod_args *uap) 2209 { 2210 struct nlookupdata nd; 2211 int error; 2212 2213 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0); 2214 if (error == 0) { 2215 error = kern_mknod(&nd, uap->mode, 2216 umajor(uap->dev), uminor(uap->dev)); 2217 } 2218 nlookup_done(&nd); 2219 return (error); 2220 } 2221 2222 /* 2223 * mknodat_args(int fd, char *path, mode_t mode, dev_t dev) 2224 * 2225 * Create a special file. The path is relative to the directory associated 2226 * with fd. 2227 */ 2228 int 2229 sys_mknodat(struct mknodat_args *uap) 2230 { 2231 struct nlookupdata nd; 2232 struct file *fp; 2233 int error; 2234 2235 error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, UIO_USERSPACE, 0); 2236 if (error == 0) { 2237 error = kern_mknod(&nd, uap->mode, 2238 umajor(uap->dev), uminor(uap->dev)); 2239 } 2240 nlookup_done_at(&nd, fp); 2241 return (error); 2242 } 2243 2244 int 2245 kern_mkfifo(struct nlookupdata *nd, int mode) 2246 { 2247 struct thread *td = curthread; 2248 struct proc *p = td->td_proc; 2249 struct vattr vattr; 2250 struct vnode *vp; 2251 int error; 2252 2253 bwillinode(1); 2254 2255 nd->nl_flags |= NLC_CREATE | NLC_REFDVP; 2256 if ((error = nlookup(nd)) != 0) 2257 return (error); 2258 if (nd->nl_nch.ncp->nc_vp) 2259 return (EEXIST); 2260 if ((error = ncp_writechk(&nd->nl_nch)) != 0) 2261 return (error); 2262 2263 VATTR_NULL(&vattr); 2264 vattr.va_type = VFIFO; 2265 vattr.va_mode = (mode & ALLPERMS) &~ p->p_fd->fd_cmask; 2266 vp = NULL; 2267 error = VOP_NMKNOD(&nd->nl_nch, nd->nl_dvp, &vp, nd->nl_cred, &vattr); 2268 if (error == 0) 2269 vput(vp); 2270 return (error); 2271 } 2272 2273 /* 2274 * mkfifo_args(char *path, int mode) 2275 * 2276 * Create a named pipe. 2277 */ 2278 int 2279 sys_mkfifo(struct mkfifo_args *uap) 2280 { 2281 struct nlookupdata nd; 2282 int error; 2283 2284 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0); 2285 if (error == 0) 2286 error = kern_mkfifo(&nd, uap->mode); 2287 nlookup_done(&nd); 2288 return (error); 2289 } 2290 2291 /* 2292 * mkfifoat_args(int fd, char *path, mode_t mode) 2293 * 2294 * Create a named pipe. The path is relative to the directory associated 2295 * with fd. 2296 */ 2297 int 2298 sys_mkfifoat(struct mkfifoat_args *uap) 2299 { 2300 struct nlookupdata nd; 2301 struct file *fp; 2302 int error; 2303 2304 error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, UIO_USERSPACE, 0); 2305 if (error == 0) 2306 error = kern_mkfifo(&nd, uap->mode); 2307 nlookup_done_at(&nd, fp); 2308 return (error); 2309 } 2310 2311 static int hardlink_check_uid = 0; 2312 SYSCTL_INT(_security, OID_AUTO, hardlink_check_uid, CTLFLAG_RW, 2313 &hardlink_check_uid, 0, 2314 "Unprivileged processes cannot create hard links to files owned by other " 2315 "users"); 2316 static int hardlink_check_gid = 0; 2317 SYSCTL_INT(_security, OID_AUTO, hardlink_check_gid, CTLFLAG_RW, 2318 &hardlink_check_gid, 0, 2319 "Unprivileged processes cannot create hard links to files owned by other " 2320 "groups"); 2321 2322 static int 2323 can_hardlink(struct vnode *vp, struct thread *td, struct ucred *cred) 2324 { 2325 struct vattr va; 2326 int error; 2327 2328 /* 2329 * Shortcut if disabled 2330 */ 2331 if (hardlink_check_uid == 0 && hardlink_check_gid == 0) 2332 return (0); 2333 2334 /* 2335 * Privileged user can always hardlink 2336 */ 2337 if (priv_check_cred(cred, PRIV_VFS_LINK, 0) == 0) 2338 return (0); 2339 2340 /* 2341 * Otherwise only if the originating file is owned by the 2342 * same user or group. Note that any group is allowed if 2343 * the file is owned by the caller. 2344 */ 2345 error = VOP_GETATTR(vp, &va); 2346 if (error != 0) 2347 return (error); 2348 2349 if (hardlink_check_uid) { 2350 if (cred->cr_uid != va.va_uid) 2351 return (EPERM); 2352 } 2353 2354 if (hardlink_check_gid) { 2355 if (cred->cr_uid != va.va_uid && !groupmember(va.va_gid, cred)) 2356 return (EPERM); 2357 } 2358 2359 return (0); 2360 } 2361 2362 int 2363 kern_link(struct nlookupdata *nd, struct nlookupdata *linknd) 2364 { 2365 struct thread *td = curthread; 2366 struct vnode *vp; 2367 int error; 2368 2369 /* 2370 * Lookup the source and obtained a locked vnode. 2371 * 2372 * You may only hardlink a file which you have write permission 2373 * on or which you own. 2374 * 2375 * XXX relookup on vget failure / race ? 2376 */ 2377 bwillinode(1); 2378 nd->nl_flags |= NLC_WRITE | NLC_OWN | NLC_HLINK; 2379 if ((error = nlookup(nd)) != 0) 2380 return (error); 2381 vp = nd->nl_nch.ncp->nc_vp; 2382 KKASSERT(vp != NULL); 2383 if (vp->v_type == VDIR) 2384 return (EPERM); /* POSIX */ 2385 if ((error = ncp_writechk(&nd->nl_nch)) != 0) 2386 return (error); 2387 if ((error = vget(vp, LK_EXCLUSIVE)) != 0) 2388 return (error); 2389 2390 /* 2391 * Unlock the source so we can lookup the target without deadlocking 2392 * (XXX vp is locked already, possible other deadlock?). The target 2393 * must not exist. 2394 */ 2395 KKASSERT(nd->nl_flags & NLC_NCPISLOCKED); 2396 nd->nl_flags &= ~NLC_NCPISLOCKED; 2397 cache_unlock(&nd->nl_nch); 2398 vn_unlock(vp); 2399 2400 linknd->nl_flags |= NLC_CREATE | NLC_REFDVP; 2401 if ((error = nlookup(linknd)) != 0) { 2402 vrele(vp); 2403 return (error); 2404 } 2405 if (linknd->nl_nch.ncp->nc_vp) { 2406 vrele(vp); 2407 return (EEXIST); 2408 } 2409 error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY | LK_FAILRECLAIM); 2410 if (error) { 2411 vrele(vp); 2412 return (error); 2413 } 2414 2415 /* 2416 * Finally run the new API VOP. 2417 */ 2418 error = can_hardlink(vp, td, td->td_ucred); 2419 if (error == 0) { 2420 error = VOP_NLINK(&linknd->nl_nch, linknd->nl_dvp, 2421 vp, linknd->nl_cred); 2422 } 2423 vput(vp); 2424 return (error); 2425 } 2426 2427 /* 2428 * link_args(char *path, char *link) 2429 * 2430 * Make a hard file link. 2431 */ 2432 int 2433 sys_link(struct link_args *uap) 2434 { 2435 struct nlookupdata nd, linknd; 2436 int error; 2437 2438 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 2439 if (error == 0) { 2440 error = nlookup_init(&linknd, uap->link, UIO_USERSPACE, 0); 2441 if (error == 0) 2442 error = kern_link(&nd, &linknd); 2443 nlookup_done(&linknd); 2444 } 2445 nlookup_done(&nd); 2446 return (error); 2447 } 2448 2449 /* 2450 * linkat_args(int fd1, char *path1, int fd2, char *path2, int flags) 2451 * 2452 * Make a hard file link. The path1 argument is relative to the directory 2453 * associated with fd1, and similarly the path2 argument is relative to 2454 * the directory associated with fd2. 2455 */ 2456 int 2457 sys_linkat(struct linkat_args *uap) 2458 { 2459 struct nlookupdata nd, linknd; 2460 struct file *fp1, *fp2; 2461 int error; 2462 2463 error = nlookup_init_at(&nd, &fp1, uap->fd1, uap->path1, UIO_USERSPACE, 2464 (uap->flags & AT_SYMLINK_FOLLOW) ? NLC_FOLLOW : 0); 2465 if (error == 0) { 2466 error = nlookup_init_at(&linknd, &fp2, uap->fd2, 2467 uap->path2, UIO_USERSPACE, 0); 2468 if (error == 0) 2469 error = kern_link(&nd, &linknd); 2470 nlookup_done_at(&linknd, fp2); 2471 } 2472 nlookup_done_at(&nd, fp1); 2473 return (error); 2474 } 2475 2476 int 2477 kern_symlink(struct nlookupdata *nd, char *path, int mode) 2478 { 2479 struct vattr vattr; 2480 struct vnode *vp; 2481 struct vnode *dvp; 2482 int error; 2483 2484 bwillinode(1); 2485 nd->nl_flags |= NLC_CREATE | NLC_REFDVP; 2486 if ((error = nlookup(nd)) != 0) 2487 return (error); 2488 if (nd->nl_nch.ncp->nc_vp) 2489 return (EEXIST); 2490 if ((error = ncp_writechk(&nd->nl_nch)) != 0) 2491 return (error); 2492 dvp = nd->nl_dvp; 2493 VATTR_NULL(&vattr); 2494 vattr.va_mode = mode; 2495 error = VOP_NSYMLINK(&nd->nl_nch, dvp, &vp, nd->nl_cred, &vattr, path); 2496 if (error == 0) 2497 vput(vp); 2498 return (error); 2499 } 2500 2501 /* 2502 * symlink(char *path, char *link) 2503 * 2504 * Make a symbolic link. 2505 */ 2506 int 2507 sys_symlink(struct symlink_args *uap) 2508 { 2509 struct thread *td = curthread; 2510 struct nlookupdata nd; 2511 char *path; 2512 int error; 2513 int mode; 2514 2515 path = objcache_get(namei_oc, M_WAITOK); 2516 error = copyinstr(uap->path, path, MAXPATHLEN, NULL); 2517 if (error == 0) { 2518 error = nlookup_init(&nd, uap->link, UIO_USERSPACE, 0); 2519 if (error == 0) { 2520 mode = ACCESSPERMS & ~td->td_proc->p_fd->fd_cmask; 2521 error = kern_symlink(&nd, path, mode); 2522 } 2523 nlookup_done(&nd); 2524 } 2525 objcache_put(namei_oc, path); 2526 return (error); 2527 } 2528 2529 /* 2530 * symlinkat_args(char *path1, int fd, char *path2) 2531 * 2532 * Make a symbolic link. The path2 argument is relative to the directory 2533 * associated with fd. 2534 */ 2535 int 2536 sys_symlinkat(struct symlinkat_args *uap) 2537 { 2538 struct thread *td = curthread; 2539 struct nlookupdata nd; 2540 struct file *fp; 2541 char *path1; 2542 int error; 2543 int mode; 2544 2545 path1 = objcache_get(namei_oc, M_WAITOK); 2546 error = copyinstr(uap->path1, path1, MAXPATHLEN, NULL); 2547 if (error == 0) { 2548 error = nlookup_init_at(&nd, &fp, uap->fd, uap->path2, 2549 UIO_USERSPACE, 0); 2550 if (error == 0) { 2551 mode = ACCESSPERMS & ~td->td_proc->p_fd->fd_cmask; 2552 error = kern_symlink(&nd, path1, mode); 2553 } 2554 nlookup_done_at(&nd, fp); 2555 } 2556 objcache_put(namei_oc, path1); 2557 return (error); 2558 } 2559 2560 /* 2561 * undelete_args(char *path) 2562 * 2563 * Delete a whiteout from the filesystem. 2564 */ 2565 int 2566 sys_undelete(struct undelete_args *uap) 2567 { 2568 struct nlookupdata nd; 2569 int error; 2570 2571 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0); 2572 bwillinode(1); 2573 nd.nl_flags |= NLC_DELETE | NLC_REFDVP; 2574 if (error == 0) 2575 error = nlookup(&nd); 2576 if (error == 0) 2577 error = ncp_writechk(&nd.nl_nch); 2578 if (error == 0) { 2579 error = VOP_NWHITEOUT(&nd.nl_nch, nd.nl_dvp, nd.nl_cred, 2580 NAMEI_DELETE); 2581 } 2582 nlookup_done(&nd); 2583 return (error); 2584 } 2585 2586 int 2587 kern_unlink(struct nlookupdata *nd) 2588 { 2589 int error; 2590 2591 bwillinode(1); 2592 nd->nl_flags |= NLC_DELETE | NLC_REFDVP; 2593 if ((error = nlookup(nd)) != 0) 2594 return (error); 2595 if ((error = ncp_writechk(&nd->nl_nch)) != 0) 2596 return (error); 2597 error = VOP_NREMOVE(&nd->nl_nch, nd->nl_dvp, nd->nl_cred); 2598 return (error); 2599 } 2600 2601 /* 2602 * unlink_args(char *path) 2603 * 2604 * Delete a name from the filesystem. 2605 */ 2606 int 2607 sys_unlink(struct unlink_args *uap) 2608 { 2609 struct nlookupdata nd; 2610 int error; 2611 2612 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0); 2613 if (error == 0) 2614 error = kern_unlink(&nd); 2615 nlookup_done(&nd); 2616 return (error); 2617 } 2618 2619 2620 /* 2621 * unlinkat_args(int fd, char *path, int flags) 2622 * 2623 * Delete the file or directory entry pointed to by fd/path. 2624 */ 2625 int 2626 sys_unlinkat(struct unlinkat_args *uap) 2627 { 2628 struct nlookupdata nd; 2629 struct file *fp; 2630 int error; 2631 2632 if (uap->flags & ~AT_REMOVEDIR) 2633 return (EINVAL); 2634 2635 error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, UIO_USERSPACE, 0); 2636 if (error == 0) { 2637 if (uap->flags & AT_REMOVEDIR) 2638 error = kern_rmdir(&nd); 2639 else 2640 error = kern_unlink(&nd); 2641 } 2642 nlookup_done_at(&nd, fp); 2643 return (error); 2644 } 2645 2646 int 2647 kern_lseek(int fd, off_t offset, int whence, off_t *res) 2648 { 2649 struct thread *td = curthread; 2650 struct proc *p = td->td_proc; 2651 struct file *fp; 2652 struct vnode *vp; 2653 struct vattr vattr; 2654 off_t new_offset; 2655 int error; 2656 2657 fp = holdfp(p->p_fd, fd, -1); 2658 if (fp == NULL) 2659 return (EBADF); 2660 if (fp->f_type != DTYPE_VNODE) { 2661 error = ESPIPE; 2662 goto done; 2663 } 2664 vp = (struct vnode *)fp->f_data; 2665 2666 switch (whence) { 2667 case L_INCR: 2668 spin_lock(&fp->f_spin); 2669 new_offset = fp->f_offset + offset; 2670 error = 0; 2671 break; 2672 case L_XTND: 2673 error = VOP_GETATTR(vp, &vattr); 2674 spin_lock(&fp->f_spin); 2675 new_offset = offset + vattr.va_size; 2676 break; 2677 case L_SET: 2678 new_offset = offset; 2679 error = 0; 2680 spin_lock(&fp->f_spin); 2681 break; 2682 default: 2683 new_offset = 0; 2684 error = EINVAL; 2685 spin_lock(&fp->f_spin); 2686 break; 2687 } 2688 2689 /* 2690 * Validate the seek position. Negative offsets are not allowed 2691 * for regular files or directories. 2692 * 2693 * Normally we would also not want to allow negative offsets for 2694 * character and block-special devices. However kvm addresses 2695 * on 64 bit architectures might appear to be negative and must 2696 * be allowed. 2697 */ 2698 if (error == 0) { 2699 if (new_offset < 0 && 2700 (vp->v_type == VREG || vp->v_type == VDIR)) { 2701 error = EINVAL; 2702 } else { 2703 fp->f_offset = new_offset; 2704 } 2705 } 2706 *res = fp->f_offset; 2707 spin_unlock(&fp->f_spin); 2708 done: 2709 fdrop(fp); 2710 return (error); 2711 } 2712 2713 /* 2714 * lseek_args(int fd, int pad, off_t offset, int whence) 2715 * 2716 * Reposition read/write file offset. 2717 */ 2718 int 2719 sys_lseek(struct lseek_args *uap) 2720 { 2721 int error; 2722 2723 error = kern_lseek(uap->fd, uap->offset, uap->whence, 2724 &uap->sysmsg_offset); 2725 2726 return (error); 2727 } 2728 2729 /* 2730 * Check if current process can access given file. amode is a bitmask of *_OK 2731 * access bits. flags is a bitmask of AT_* flags. 2732 */ 2733 int 2734 kern_access(struct nlookupdata *nd, int amode, int flags) 2735 { 2736 struct vnode *vp; 2737 int error, mode; 2738 2739 if (flags & ~AT_EACCESS) 2740 return (EINVAL); 2741 nd->nl_flags |= NLC_SHAREDLOCK; 2742 if ((error = nlookup(nd)) != 0) 2743 return (error); 2744 retry: 2745 error = cache_vget(&nd->nl_nch, nd->nl_cred, LK_SHARED, &vp); 2746 if (error) 2747 return (error); 2748 2749 /* Flags == 0 means only check for existence. */ 2750 if (amode) { 2751 mode = 0; 2752 if (amode & R_OK) 2753 mode |= VREAD; 2754 if (amode & W_OK) 2755 mode |= VWRITE; 2756 if (amode & X_OK) 2757 mode |= VEXEC; 2758 if ((mode & VWRITE) == 0 || 2759 (error = vn_writechk(vp, &nd->nl_nch)) == 0) 2760 error = VOP_ACCESS_FLAGS(vp, mode, flags, nd->nl_cred); 2761 2762 /* 2763 * If the file handle is stale we have to re-resolve the 2764 * entry with the ncp held exclusively. This is a hack 2765 * at the moment. 2766 */ 2767 if (error == ESTALE) { 2768 vput(vp); 2769 cache_unlock(&nd->nl_nch); 2770 cache_lock(&nd->nl_nch); 2771 cache_setunresolved(&nd->nl_nch); 2772 error = cache_resolve(&nd->nl_nch, nd->nl_cred); 2773 if (error == 0) { 2774 vp = NULL; 2775 goto retry; 2776 } 2777 return(error); 2778 } 2779 } 2780 vput(vp); 2781 return (error); 2782 } 2783 2784 /* 2785 * access_args(char *path, int flags) 2786 * 2787 * Check access permissions. 2788 */ 2789 int 2790 sys_access(struct access_args *uap) 2791 { 2792 struct nlookupdata nd; 2793 int error; 2794 2795 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 2796 if (error == 0) 2797 error = kern_access(&nd, uap->flags, 0); 2798 nlookup_done(&nd); 2799 return (error); 2800 } 2801 2802 2803 /* 2804 * eaccess_args(char *path, int flags) 2805 * 2806 * Check access permissions. 2807 */ 2808 int 2809 sys_eaccess(struct eaccess_args *uap) 2810 { 2811 struct nlookupdata nd; 2812 int error; 2813 2814 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 2815 if (error == 0) 2816 error = kern_access(&nd, uap->flags, AT_EACCESS); 2817 nlookup_done(&nd); 2818 return (error); 2819 } 2820 2821 2822 /* 2823 * faccessat_args(int fd, char *path, int amode, int flags) 2824 * 2825 * Check access permissions. 2826 */ 2827 int 2828 sys_faccessat(struct faccessat_args *uap) 2829 { 2830 struct nlookupdata nd; 2831 struct file *fp; 2832 int error; 2833 2834 error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, UIO_USERSPACE, 2835 NLC_FOLLOW); 2836 if (error == 0) 2837 error = kern_access(&nd, uap->amode, uap->flags); 2838 nlookup_done_at(&nd, fp); 2839 return (error); 2840 } 2841 2842 int 2843 kern_stat(struct nlookupdata *nd, struct stat *st) 2844 { 2845 int error; 2846 struct vnode *vp; 2847 2848 nd->nl_flags |= NLC_SHAREDLOCK; 2849 if ((error = nlookup(nd)) != 0) 2850 return (error); 2851 again: 2852 if ((vp = nd->nl_nch.ncp->nc_vp) == NULL) 2853 return (ENOENT); 2854 2855 if ((error = vget(vp, LK_SHARED)) != 0) 2856 return (error); 2857 error = vn_stat(vp, st, nd->nl_cred); 2858 2859 /* 2860 * If the file handle is stale we have to re-resolve the 2861 * entry with the ncp held exclusively. This is a hack 2862 * at the moment. 2863 */ 2864 if (error == ESTALE) { 2865 vput(vp); 2866 cache_unlock(&nd->nl_nch); 2867 cache_lock(&nd->nl_nch); 2868 cache_setunresolved(&nd->nl_nch); 2869 error = cache_resolve(&nd->nl_nch, nd->nl_cred); 2870 if (error == 0) 2871 goto again; 2872 } else { 2873 vput(vp); 2874 } 2875 return (error); 2876 } 2877 2878 /* 2879 * stat_args(char *path, struct stat *ub) 2880 * 2881 * Get file status; this version follows links. 2882 */ 2883 int 2884 sys_stat(struct stat_args *uap) 2885 { 2886 struct nlookupdata nd; 2887 struct stat st; 2888 int error; 2889 2890 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 2891 if (error == 0) { 2892 error = kern_stat(&nd, &st); 2893 if (error == 0) 2894 error = copyout(&st, uap->ub, sizeof(*uap->ub)); 2895 } 2896 nlookup_done(&nd); 2897 return (error); 2898 } 2899 2900 /* 2901 * lstat_args(char *path, struct stat *ub) 2902 * 2903 * Get file status; this version does not follow links. 2904 */ 2905 int 2906 sys_lstat(struct lstat_args *uap) 2907 { 2908 struct nlookupdata nd; 2909 struct stat st; 2910 int error; 2911 2912 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0); 2913 if (error == 0) { 2914 error = kern_stat(&nd, &st); 2915 if (error == 0) 2916 error = copyout(&st, uap->ub, sizeof(*uap->ub)); 2917 } 2918 nlookup_done(&nd); 2919 return (error); 2920 } 2921 2922 /* 2923 * fstatat_args(int fd, char *path, struct stat *sb, int flags) 2924 * 2925 * Get status of file pointed to by fd/path. 2926 */ 2927 int 2928 sys_fstatat(struct fstatat_args *uap) 2929 { 2930 struct nlookupdata nd; 2931 struct stat st; 2932 int error; 2933 int flags; 2934 struct file *fp; 2935 2936 if (uap->flags & ~AT_SYMLINK_NOFOLLOW) 2937 return (EINVAL); 2938 2939 flags = (uap->flags & AT_SYMLINK_NOFOLLOW) ? 0 : NLC_FOLLOW; 2940 2941 error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, 2942 UIO_USERSPACE, flags); 2943 if (error == 0) { 2944 error = kern_stat(&nd, &st); 2945 if (error == 0) 2946 error = copyout(&st, uap->sb, sizeof(*uap->sb)); 2947 } 2948 nlookup_done_at(&nd, fp); 2949 return (error); 2950 } 2951 2952 static int 2953 kern_pathconf(char *path, int name, int flags, register_t *sysmsg_regp) 2954 { 2955 struct nlookupdata nd; 2956 struct vnode *vp; 2957 int error; 2958 2959 vp = NULL; 2960 error = nlookup_init(&nd, path, UIO_USERSPACE, flags); 2961 if (error == 0) 2962 error = nlookup(&nd); 2963 if (error == 0) 2964 error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp); 2965 nlookup_done(&nd); 2966 if (error == 0) { 2967 error = VOP_PATHCONF(vp, name, sysmsg_regp); 2968 vput(vp); 2969 } 2970 return (error); 2971 } 2972 2973 /* 2974 * pathconf_Args(char *path, int name) 2975 * 2976 * Get configurable pathname variables. 2977 */ 2978 int 2979 sys_pathconf(struct pathconf_args *uap) 2980 { 2981 return (kern_pathconf(uap->path, uap->name, NLC_FOLLOW, 2982 &uap->sysmsg_reg)); 2983 } 2984 2985 /* 2986 * lpathconf_Args(char *path, int name) 2987 * 2988 * Get configurable pathname variables, but don't follow symlinks. 2989 */ 2990 int 2991 sys_lpathconf(struct lpathconf_args *uap) 2992 { 2993 return (kern_pathconf(uap->path, uap->name, 0, &uap->sysmsg_reg)); 2994 } 2995 2996 /* 2997 * XXX: daver 2998 * kern_readlink isn't properly split yet. There is a copyin burried 2999 * in VOP_READLINK(). 3000 */ 3001 int 3002 kern_readlink(struct nlookupdata *nd, char *buf, int count, int *res) 3003 { 3004 struct thread *td = curthread; 3005 struct vnode *vp; 3006 struct iovec aiov; 3007 struct uio auio; 3008 int error; 3009 3010 nd->nl_flags |= NLC_SHAREDLOCK; 3011 if ((error = nlookup(nd)) != 0) 3012 return (error); 3013 error = cache_vget(&nd->nl_nch, nd->nl_cred, LK_SHARED, &vp); 3014 if (error) 3015 return (error); 3016 if (vp->v_type != VLNK) { 3017 error = EINVAL; 3018 } else { 3019 aiov.iov_base = buf; 3020 aiov.iov_len = count; 3021 auio.uio_iov = &aiov; 3022 auio.uio_iovcnt = 1; 3023 auio.uio_offset = 0; 3024 auio.uio_rw = UIO_READ; 3025 auio.uio_segflg = UIO_USERSPACE; 3026 auio.uio_td = td; 3027 auio.uio_resid = count; 3028 error = VOP_READLINK(vp, &auio, td->td_ucred); 3029 } 3030 vput(vp); 3031 *res = count - auio.uio_resid; 3032 return (error); 3033 } 3034 3035 /* 3036 * readlink_args(char *path, char *buf, int count) 3037 * 3038 * Return target name of a symbolic link. 3039 */ 3040 int 3041 sys_readlink(struct readlink_args *uap) 3042 { 3043 struct nlookupdata nd; 3044 int error; 3045 3046 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0); 3047 if (error == 0) { 3048 error = kern_readlink(&nd, uap->buf, uap->count, 3049 &uap->sysmsg_result); 3050 } 3051 nlookup_done(&nd); 3052 return (error); 3053 } 3054 3055 /* 3056 * readlinkat_args(int fd, char *path, char *buf, size_t bufsize) 3057 * 3058 * Return target name of a symbolic link. The path is relative to the 3059 * directory associated with fd. 3060 */ 3061 int 3062 sys_readlinkat(struct readlinkat_args *uap) 3063 { 3064 struct nlookupdata nd; 3065 struct file *fp; 3066 int error; 3067 3068 error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, UIO_USERSPACE, 0); 3069 if (error == 0) { 3070 error = kern_readlink(&nd, uap->buf, uap->bufsize, 3071 &uap->sysmsg_result); 3072 } 3073 nlookup_done_at(&nd, fp); 3074 return (error); 3075 } 3076 3077 static int 3078 setfflags(struct vnode *vp, int flags) 3079 { 3080 struct thread *td = curthread; 3081 int error; 3082 struct vattr vattr; 3083 3084 /* 3085 * Prevent non-root users from setting flags on devices. When 3086 * a device is reused, users can retain ownership of the device 3087 * if they are allowed to set flags and programs assume that 3088 * chown can't fail when done as root. 3089 */ 3090 if ((vp->v_type == VCHR || vp->v_type == VBLK) && 3091 ((error = priv_check_cred(td->td_ucred, PRIV_VFS_CHFLAGS_DEV, 0)) != 0)) 3092 return (error); 3093 3094 /* 3095 * note: vget is required for any operation that might mod the vnode 3096 * so VINACTIVE is properly cleared. 3097 */ 3098 if ((error = vget(vp, LK_EXCLUSIVE)) == 0) { 3099 VATTR_NULL(&vattr); 3100 vattr.va_flags = flags; 3101 error = VOP_SETATTR(vp, &vattr, td->td_ucred); 3102 vput(vp); 3103 } 3104 return (error); 3105 } 3106 3107 /* 3108 * chflags(char *path, int flags) 3109 * 3110 * Change flags of a file given a path name. 3111 */ 3112 int 3113 sys_chflags(struct chflags_args *uap) 3114 { 3115 struct nlookupdata nd; 3116 struct vnode *vp; 3117 int error; 3118 3119 vp = NULL; 3120 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 3121 if (error == 0) 3122 error = nlookup(&nd); 3123 if (error == 0) 3124 error = ncp_writechk(&nd.nl_nch); 3125 if (error == 0) 3126 error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp); 3127 nlookup_done(&nd); 3128 if (error == 0) { 3129 error = setfflags(vp, uap->flags); 3130 vrele(vp); 3131 } 3132 return (error); 3133 } 3134 3135 /* 3136 * lchflags(char *path, int flags) 3137 * 3138 * Change flags of a file given a path name, but don't follow symlinks. 3139 */ 3140 int 3141 sys_lchflags(struct lchflags_args *uap) 3142 { 3143 struct nlookupdata nd; 3144 struct vnode *vp; 3145 int error; 3146 3147 vp = NULL; 3148 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0); 3149 if (error == 0) 3150 error = nlookup(&nd); 3151 if (error == 0) 3152 error = ncp_writechk(&nd.nl_nch); 3153 if (error == 0) 3154 error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp); 3155 nlookup_done(&nd); 3156 if (error == 0) { 3157 error = setfflags(vp, uap->flags); 3158 vrele(vp); 3159 } 3160 return (error); 3161 } 3162 3163 /* 3164 * fchflags_args(int fd, int flags) 3165 * 3166 * Change flags of a file given a file descriptor. 3167 */ 3168 int 3169 sys_fchflags(struct fchflags_args *uap) 3170 { 3171 struct thread *td = curthread; 3172 struct proc *p = td->td_proc; 3173 struct file *fp; 3174 int error; 3175 3176 if ((error = holdvnode(p->p_fd, uap->fd, &fp)) != 0) 3177 return (error); 3178 if (fp->f_nchandle.ncp) 3179 error = ncp_writechk(&fp->f_nchandle); 3180 if (error == 0) 3181 error = setfflags((struct vnode *) fp->f_data, uap->flags); 3182 fdrop(fp); 3183 return (error); 3184 } 3185 3186 /* 3187 * chflagsat_args(int fd, const char *path, int flags, int atflags) 3188 * change flags given a pathname relative to a filedescriptor 3189 */ 3190 int sys_chflagsat(struct chflagsat_args *uap) 3191 { 3192 struct nlookupdata nd; 3193 struct vnode *vp; 3194 struct file *fp; 3195 int error; 3196 int lookupflags; 3197 3198 if (uap->atflags & ~AT_SYMLINK_NOFOLLOW) 3199 return (EINVAL); 3200 3201 lookupflags = (uap->atflags & AT_SYMLINK_NOFOLLOW) ? 0 : NLC_FOLLOW; 3202 3203 vp = NULL; 3204 error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, UIO_USERSPACE, lookupflags); 3205 if (error == 0) 3206 error = nlookup(&nd); 3207 if (error == 0) 3208 error = ncp_writechk(&nd.nl_nch); 3209 if (error == 0) 3210 error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp); 3211 nlookup_done_at(&nd, fp); 3212 if (error == 0) { 3213 error = setfflags(vp, uap->flags); 3214 vrele(vp); 3215 } 3216 return (error); 3217 } 3218 3219 3220 static int 3221 setfmode(struct vnode *vp, int mode) 3222 { 3223 struct thread *td = curthread; 3224 int error; 3225 struct vattr vattr; 3226 3227 /* 3228 * note: vget is required for any operation that might mod the vnode 3229 * so VINACTIVE is properly cleared. 3230 */ 3231 if ((error = vget(vp, LK_EXCLUSIVE)) == 0) { 3232 VATTR_NULL(&vattr); 3233 vattr.va_mode = mode & ALLPERMS; 3234 error = VOP_SETATTR(vp, &vattr, td->td_ucred); 3235 cache_inval_wxok(vp); 3236 vput(vp); 3237 } 3238 return error; 3239 } 3240 3241 int 3242 kern_chmod(struct nlookupdata *nd, int mode) 3243 { 3244 struct vnode *vp; 3245 int error; 3246 3247 if ((error = nlookup(nd)) != 0) 3248 return (error); 3249 if ((error = cache_vref(&nd->nl_nch, nd->nl_cred, &vp)) != 0) 3250 return (error); 3251 if ((error = ncp_writechk(&nd->nl_nch)) == 0) 3252 error = setfmode(vp, mode); 3253 vrele(vp); 3254 return (error); 3255 } 3256 3257 /* 3258 * chmod_args(char *path, int mode) 3259 * 3260 * Change mode of a file given path name. 3261 */ 3262 int 3263 sys_chmod(struct chmod_args *uap) 3264 { 3265 struct nlookupdata nd; 3266 int error; 3267 3268 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 3269 if (error == 0) 3270 error = kern_chmod(&nd, uap->mode); 3271 nlookup_done(&nd); 3272 return (error); 3273 } 3274 3275 /* 3276 * lchmod_args(char *path, int mode) 3277 * 3278 * Change mode of a file given path name (don't follow links.) 3279 */ 3280 int 3281 sys_lchmod(struct lchmod_args *uap) 3282 { 3283 struct nlookupdata nd; 3284 int error; 3285 3286 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0); 3287 if (error == 0) 3288 error = kern_chmod(&nd, uap->mode); 3289 nlookup_done(&nd); 3290 return (error); 3291 } 3292 3293 /* 3294 * fchmod_args(int fd, int mode) 3295 * 3296 * Change mode of a file given a file descriptor. 3297 */ 3298 int 3299 sys_fchmod(struct fchmod_args *uap) 3300 { 3301 struct thread *td = curthread; 3302 struct proc *p = td->td_proc; 3303 struct file *fp; 3304 int error; 3305 3306 if ((error = holdvnode(p->p_fd, uap->fd, &fp)) != 0) 3307 return (error); 3308 if (fp->f_nchandle.ncp) 3309 error = ncp_writechk(&fp->f_nchandle); 3310 if (error == 0) 3311 error = setfmode((struct vnode *)fp->f_data, uap->mode); 3312 fdrop(fp); 3313 return (error); 3314 } 3315 3316 /* 3317 * fchmodat_args(char *path, int mode) 3318 * 3319 * Change mode of a file pointed to by fd/path. 3320 */ 3321 int 3322 sys_fchmodat(struct fchmodat_args *uap) 3323 { 3324 struct nlookupdata nd; 3325 struct file *fp; 3326 int error; 3327 int flags; 3328 3329 if (uap->flags & ~AT_SYMLINK_NOFOLLOW) 3330 return (EINVAL); 3331 flags = (uap->flags & AT_SYMLINK_NOFOLLOW) ? 0 : NLC_FOLLOW; 3332 3333 error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, 3334 UIO_USERSPACE, flags); 3335 if (error == 0) 3336 error = kern_chmod(&nd, uap->mode); 3337 nlookup_done_at(&nd, fp); 3338 return (error); 3339 } 3340 3341 static int 3342 setfown(struct mount *mp, struct vnode *vp, uid_t uid, gid_t gid) 3343 { 3344 struct thread *td = curthread; 3345 int error; 3346 struct vattr vattr; 3347 uid_t o_uid; 3348 gid_t o_gid; 3349 uint64_t size; 3350 3351 /* 3352 * note: vget is required for any operation that might mod the vnode 3353 * so VINACTIVE is properly cleared. 3354 */ 3355 if ((error = vget(vp, LK_EXCLUSIVE)) == 0) { 3356 if ((error = VOP_GETATTR(vp, &vattr)) != 0) 3357 return error; 3358 o_uid = vattr.va_uid; 3359 o_gid = vattr.va_gid; 3360 size = vattr.va_size; 3361 3362 VATTR_NULL(&vattr); 3363 vattr.va_uid = uid; 3364 vattr.va_gid = gid; 3365 error = VOP_SETATTR(vp, &vattr, td->td_ucred); 3366 vput(vp); 3367 } 3368 3369 if (error == 0) { 3370 if (uid == -1) 3371 uid = o_uid; 3372 if (gid == -1) 3373 gid = o_gid; 3374 VFS_ACCOUNT(mp, o_uid, o_gid, -size); 3375 VFS_ACCOUNT(mp, uid, gid, size); 3376 } 3377 3378 return error; 3379 } 3380 3381 int 3382 kern_chown(struct nlookupdata *nd, int uid, int gid) 3383 { 3384 struct vnode *vp; 3385 int error; 3386 3387 if ((error = nlookup(nd)) != 0) 3388 return (error); 3389 if ((error = cache_vref(&nd->nl_nch, nd->nl_cred, &vp)) != 0) 3390 return (error); 3391 if ((error = ncp_writechk(&nd->nl_nch)) == 0) 3392 error = setfown(nd->nl_nch.mount, vp, uid, gid); 3393 vrele(vp); 3394 return (error); 3395 } 3396 3397 /* 3398 * chown(char *path, int uid, int gid) 3399 * 3400 * Set ownership given a path name. 3401 */ 3402 int 3403 sys_chown(struct chown_args *uap) 3404 { 3405 struct nlookupdata nd; 3406 int error; 3407 3408 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 3409 if (error == 0) 3410 error = kern_chown(&nd, uap->uid, uap->gid); 3411 nlookup_done(&nd); 3412 return (error); 3413 } 3414 3415 /* 3416 * lchown_args(char *path, int uid, int gid) 3417 * 3418 * Set ownership given a path name, do not cross symlinks. 3419 */ 3420 int 3421 sys_lchown(struct lchown_args *uap) 3422 { 3423 struct nlookupdata nd; 3424 int error; 3425 3426 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0); 3427 if (error == 0) 3428 error = kern_chown(&nd, uap->uid, uap->gid); 3429 nlookup_done(&nd); 3430 return (error); 3431 } 3432 3433 /* 3434 * fchown_args(int fd, int uid, int gid) 3435 * 3436 * Set ownership given a file descriptor. 3437 */ 3438 int 3439 sys_fchown(struct fchown_args *uap) 3440 { 3441 struct thread *td = curthread; 3442 struct proc *p = td->td_proc; 3443 struct file *fp; 3444 int error; 3445 3446 if ((error = holdvnode(p->p_fd, uap->fd, &fp)) != 0) 3447 return (error); 3448 if (fp->f_nchandle.ncp) 3449 error = ncp_writechk(&fp->f_nchandle); 3450 if (error == 0) 3451 error = setfown(p->p_fd->fd_ncdir.mount, 3452 (struct vnode *)fp->f_data, uap->uid, uap->gid); 3453 fdrop(fp); 3454 return (error); 3455 } 3456 3457 /* 3458 * fchownat(int fd, char *path, int uid, int gid, int flags) 3459 * 3460 * Set ownership of file pointed to by fd/path. 3461 */ 3462 int 3463 sys_fchownat(struct fchownat_args *uap) 3464 { 3465 struct nlookupdata nd; 3466 struct file *fp; 3467 int error; 3468 int flags; 3469 3470 if (uap->flags & ~AT_SYMLINK_NOFOLLOW) 3471 return (EINVAL); 3472 flags = (uap->flags & AT_SYMLINK_NOFOLLOW) ? 0 : NLC_FOLLOW; 3473 3474 error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, 3475 UIO_USERSPACE, flags); 3476 if (error == 0) 3477 error = kern_chown(&nd, uap->uid, uap->gid); 3478 nlookup_done_at(&nd, fp); 3479 return (error); 3480 } 3481 3482 3483 static int 3484 getutimes(struct timeval *tvp, struct timespec *tsp) 3485 { 3486 struct timeval tv[2]; 3487 int error; 3488 3489 if (tvp == NULL) { 3490 microtime(&tv[0]); 3491 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]); 3492 tsp[1] = tsp[0]; 3493 } else { 3494 if ((error = itimerfix(tvp)) != 0) 3495 return (error); 3496 TIMEVAL_TO_TIMESPEC(&tvp[0], &tsp[0]); 3497 TIMEVAL_TO_TIMESPEC(&tvp[1], &tsp[1]); 3498 } 3499 return 0; 3500 } 3501 3502 static int 3503 getutimens(const struct timespec *ts, struct timespec *newts, int *nullflag) 3504 { 3505 struct timespec tsnow; 3506 int error; 3507 3508 *nullflag = 0; 3509 nanotime(&tsnow); 3510 if (ts == NULL) { 3511 newts[0] = tsnow; 3512 newts[1] = tsnow; 3513 *nullflag = 1; 3514 return (0); 3515 } 3516 3517 newts[0] = ts[0]; 3518 newts[1] = ts[1]; 3519 if (newts[0].tv_nsec == UTIME_OMIT && newts[1].tv_nsec == UTIME_OMIT) 3520 return (0); 3521 if (newts[0].tv_nsec == UTIME_NOW && newts[1].tv_nsec == UTIME_NOW) 3522 *nullflag = 1; 3523 3524 if (newts[0].tv_nsec == UTIME_OMIT) 3525 newts[0].tv_sec = VNOVAL; 3526 else if (newts[0].tv_nsec == UTIME_NOW) 3527 newts[0] = tsnow; 3528 else if ((error = itimespecfix(&newts[0])) != 0) 3529 return (error); 3530 3531 if (newts[1].tv_nsec == UTIME_OMIT) 3532 newts[1].tv_sec = VNOVAL; 3533 else if (newts[1].tv_nsec == UTIME_NOW) 3534 newts[1] = tsnow; 3535 else if ((error = itimespecfix(&newts[1])) != 0) 3536 return (error); 3537 3538 return (0); 3539 } 3540 3541 static int 3542 setutimes(struct vnode *vp, struct vattr *vattr, 3543 const struct timespec *ts, int nullflag) 3544 { 3545 struct thread *td = curthread; 3546 int error; 3547 3548 VATTR_NULL(vattr); 3549 vattr->va_atime = ts[0]; 3550 vattr->va_mtime = ts[1]; 3551 if (nullflag) 3552 vattr->va_vaflags |= VA_UTIMES_NULL; 3553 error = VOP_SETATTR(vp, vattr, td->td_ucred); 3554 3555 return error; 3556 } 3557 3558 int 3559 kern_utimes(struct nlookupdata *nd, struct timeval *tptr) 3560 { 3561 struct timespec ts[2]; 3562 int error; 3563 3564 if (tptr) { 3565 if ((error = getutimes(tptr, ts)) != 0) 3566 return (error); 3567 } 3568 error = kern_utimensat(nd, tptr ? ts : NULL, 0); 3569 return (error); 3570 } 3571 3572 /* 3573 * utimes_args(char *path, struct timeval *tptr) 3574 * 3575 * Set the access and modification times of a file. 3576 */ 3577 int 3578 sys_utimes(struct utimes_args *uap) 3579 { 3580 struct timeval tv[2]; 3581 struct nlookupdata nd; 3582 int error; 3583 3584 if (uap->tptr) { 3585 error = copyin(uap->tptr, tv, sizeof(tv)); 3586 if (error) 3587 return (error); 3588 } 3589 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 3590 if (error == 0) 3591 error = kern_utimes(&nd, uap->tptr ? tv : NULL); 3592 nlookup_done(&nd); 3593 return (error); 3594 } 3595 3596 /* 3597 * lutimes_args(char *path, struct timeval *tptr) 3598 * 3599 * Set the access and modification times of a file. 3600 */ 3601 int 3602 sys_lutimes(struct lutimes_args *uap) 3603 { 3604 struct timeval tv[2]; 3605 struct nlookupdata nd; 3606 int error; 3607 3608 if (uap->tptr) { 3609 error = copyin(uap->tptr, tv, sizeof(tv)); 3610 if (error) 3611 return (error); 3612 } 3613 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0); 3614 if (error == 0) 3615 error = kern_utimes(&nd, uap->tptr ? tv : NULL); 3616 nlookup_done(&nd); 3617 return (error); 3618 } 3619 3620 /* 3621 * Set utimes on a file descriptor. The creds used to open the 3622 * file are used to determine whether the operation is allowed 3623 * or not. 3624 */ 3625 int 3626 kern_futimens(int fd, struct timespec *ts) 3627 { 3628 struct thread *td = curthread; 3629 struct proc *p = td->td_proc; 3630 struct timespec newts[2]; 3631 struct file *fp; 3632 struct vnode *vp; 3633 struct vattr vattr; 3634 int nullflag; 3635 int error; 3636 3637 error = getutimens(ts, newts, &nullflag); 3638 if (error) 3639 return (error); 3640 if ((error = holdvnode(p->p_fd, fd, &fp)) != 0) 3641 return (error); 3642 if (fp->f_nchandle.ncp) 3643 error = ncp_writechk(&fp->f_nchandle); 3644 if (error == 0) { 3645 vp = fp->f_data; 3646 error = vget(vp, LK_EXCLUSIVE); 3647 if (error == 0) { 3648 error = VOP_GETATTR(vp, &vattr); 3649 if (error == 0) { 3650 error = naccess_va(&vattr, NLC_OWN | NLC_WRITE, 3651 fp->f_cred); 3652 } 3653 if (error == 0) { 3654 error = setutimes(vp, &vattr, newts, nullflag); 3655 } 3656 vput(vp); 3657 } 3658 } 3659 fdrop(fp); 3660 return (error); 3661 } 3662 3663 /* 3664 * futimens_args(int fd, struct timespec *ts) 3665 * 3666 * Set the access and modification times of a file. 3667 */ 3668 int 3669 sys_futimens(struct futimens_args *uap) 3670 { 3671 struct timespec ts[2]; 3672 int error; 3673 3674 if (uap->ts) { 3675 error = copyin(uap->ts, ts, sizeof(ts)); 3676 if (error) 3677 return (error); 3678 } 3679 error = kern_futimens(uap->fd, uap->ts ? ts : NULL); 3680 return (error); 3681 } 3682 3683 int 3684 kern_futimes(int fd, struct timeval *tptr) 3685 { 3686 struct timespec ts[2]; 3687 int error; 3688 3689 if (tptr) { 3690 if ((error = getutimes(tptr, ts)) != 0) 3691 return (error); 3692 } 3693 error = kern_futimens(fd, tptr ? ts : NULL); 3694 return (error); 3695 } 3696 3697 /* 3698 * futimes_args(int fd, struct timeval *tptr) 3699 * 3700 * Set the access and modification times of a file. 3701 */ 3702 int 3703 sys_futimes(struct futimes_args *uap) 3704 { 3705 struct timeval tv[2]; 3706 int error; 3707 3708 if (uap->tptr) { 3709 error = copyin(uap->tptr, tv, sizeof(tv)); 3710 if (error) 3711 return (error); 3712 } 3713 error = kern_futimes(uap->fd, uap->tptr ? tv : NULL); 3714 return (error); 3715 } 3716 3717 int 3718 kern_utimensat(struct nlookupdata *nd, const struct timespec *ts, int flags) 3719 { 3720 struct timespec newts[2]; 3721 struct vnode *vp; 3722 struct vattr vattr; 3723 int nullflag; 3724 int error; 3725 3726 if (flags & ~AT_SYMLINK_NOFOLLOW) 3727 return (EINVAL); 3728 3729 error = getutimens(ts, newts, &nullflag); 3730 if (error) 3731 return (error); 3732 3733 nd->nl_flags |= NLC_OWN | NLC_WRITE; 3734 if ((error = nlookup(nd)) != 0) 3735 return (error); 3736 if ((error = ncp_writechk(&nd->nl_nch)) != 0) 3737 return (error); 3738 if ((error = cache_vref(&nd->nl_nch, nd->nl_cred, &vp)) != 0) 3739 return (error); 3740 if ((error = vn_writechk(vp, &nd->nl_nch)) == 0) { 3741 error = vget(vp, LK_EXCLUSIVE); 3742 if (error == 0) { 3743 error = setutimes(vp, &vattr, newts, nullflag); 3744 vput(vp); 3745 } 3746 } 3747 vrele(vp); 3748 return (error); 3749 } 3750 3751 /* 3752 * utimensat_args(int fd, const char *path, const struct timespec *ts, int flags); 3753 * 3754 * Set file access and modification times of a file. 3755 */ 3756 int 3757 sys_utimensat(struct utimensat_args *uap) 3758 { 3759 struct timespec ts[2]; 3760 struct nlookupdata nd; 3761 struct file *fp; 3762 int error; 3763 int flags; 3764 3765 if (uap->ts) { 3766 error = copyin(uap->ts, ts, sizeof(ts)); 3767 if (error) 3768 return (error); 3769 } 3770 3771 flags = (uap->flags & AT_SYMLINK_NOFOLLOW) ? 0 : NLC_FOLLOW; 3772 error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, 3773 UIO_USERSPACE, flags); 3774 if (error == 0) 3775 error = kern_utimensat(&nd, uap->ts ? ts : NULL, uap->flags); 3776 nlookup_done_at(&nd, fp); 3777 return (error); 3778 } 3779 3780 int 3781 kern_truncate(struct nlookupdata *nd, off_t length) 3782 { 3783 struct vnode *vp; 3784 struct vattr vattr; 3785 int error; 3786 uid_t uid = 0; 3787 gid_t gid = 0; 3788 uint64_t old_size = 0; 3789 3790 if (length < 0) 3791 return(EINVAL); 3792 nd->nl_flags |= NLC_WRITE | NLC_TRUNCATE; 3793 if ((error = nlookup(nd)) != 0) 3794 return (error); 3795 if ((error = ncp_writechk(&nd->nl_nch)) != 0) 3796 return (error); 3797 if ((error = cache_vref(&nd->nl_nch, nd->nl_cred, &vp)) != 0) 3798 return (error); 3799 error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY | LK_FAILRECLAIM); 3800 if (error) { 3801 vrele(vp); 3802 return (error); 3803 } 3804 if (vp->v_type == VDIR) { 3805 error = EISDIR; 3806 goto done; 3807 } 3808 if (vfs_quota_enabled) { 3809 error = VOP_GETATTR(vp, &vattr); 3810 KASSERT(error == 0, ("kern_truncate(): VOP_GETATTR didn't return 0")); 3811 uid = vattr.va_uid; 3812 gid = vattr.va_gid; 3813 old_size = vattr.va_size; 3814 } 3815 3816 if ((error = vn_writechk(vp, &nd->nl_nch)) == 0) { 3817 VATTR_NULL(&vattr); 3818 vattr.va_size = length; 3819 error = VOP_SETATTR(vp, &vattr, nd->nl_cred); 3820 VFS_ACCOUNT(nd->nl_nch.mount, uid, gid, length - old_size); 3821 } 3822 done: 3823 vput(vp); 3824 return (error); 3825 } 3826 3827 /* 3828 * truncate(char *path, int pad, off_t length) 3829 * 3830 * Truncate a file given its path name. 3831 */ 3832 int 3833 sys_truncate(struct truncate_args *uap) 3834 { 3835 struct nlookupdata nd; 3836 int error; 3837 3838 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 3839 if (error == 0) 3840 error = kern_truncate(&nd, uap->length); 3841 nlookup_done(&nd); 3842 return error; 3843 } 3844 3845 int 3846 kern_ftruncate(int fd, off_t length) 3847 { 3848 struct thread *td = curthread; 3849 struct proc *p = td->td_proc; 3850 struct vattr vattr; 3851 struct vnode *vp; 3852 struct file *fp; 3853 int error; 3854 uid_t uid = 0; 3855 gid_t gid = 0; 3856 uint64_t old_size = 0; 3857 struct mount *mp; 3858 3859 if (length < 0) 3860 return(EINVAL); 3861 if ((error = holdvnode(p->p_fd, fd, &fp)) != 0) 3862 return (error); 3863 if (fp->f_nchandle.ncp) { 3864 error = ncp_writechk(&fp->f_nchandle); 3865 if (error) 3866 goto done; 3867 } 3868 if ((fp->f_flag & FWRITE) == 0) { 3869 error = EINVAL; 3870 goto done; 3871 } 3872 if (fp->f_flag & FAPPENDONLY) { /* inode was set s/uapnd */ 3873 error = EINVAL; 3874 goto done; 3875 } 3876 vp = (struct vnode *)fp->f_data; 3877 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 3878 if (vp->v_type == VDIR) { 3879 error = EISDIR; 3880 vn_unlock(vp); 3881 goto done; 3882 } 3883 3884 if (vfs_quota_enabled) { 3885 error = VOP_GETATTR(vp, &vattr); 3886 KASSERT(error == 0, ("kern_ftruncate(): VOP_GETATTR didn't return 0")); 3887 uid = vattr.va_uid; 3888 gid = vattr.va_gid; 3889 old_size = vattr.va_size; 3890 } 3891 3892 if ((error = vn_writechk(vp, NULL)) == 0) { 3893 VATTR_NULL(&vattr); 3894 vattr.va_size = length; 3895 error = VOP_SETATTR(vp, &vattr, fp->f_cred); 3896 mp = vq_vptomp(vp); 3897 VFS_ACCOUNT(mp, uid, gid, length - old_size); 3898 } 3899 vn_unlock(vp); 3900 done: 3901 fdrop(fp); 3902 return (error); 3903 } 3904 3905 /* 3906 * ftruncate_args(int fd, int pad, off_t length) 3907 * 3908 * Truncate a file given a file descriptor. 3909 */ 3910 int 3911 sys_ftruncate(struct ftruncate_args *uap) 3912 { 3913 int error; 3914 3915 error = kern_ftruncate(uap->fd, uap->length); 3916 3917 return (error); 3918 } 3919 3920 /* 3921 * fsync(int fd) 3922 * 3923 * Sync an open file. 3924 */ 3925 int 3926 sys_fsync(struct fsync_args *uap) 3927 { 3928 struct thread *td = curthread; 3929 struct proc *p = td->td_proc; 3930 struct vnode *vp; 3931 struct file *fp; 3932 vm_object_t obj; 3933 int error; 3934 3935 if ((error = holdvnode(p->p_fd, uap->fd, &fp)) != 0) 3936 return (error); 3937 vp = (struct vnode *)fp->f_data; 3938 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 3939 if ((obj = vp->v_object) != NULL) { 3940 if (vp->v_mount == NULL || 3941 (vp->v_mount->mnt_kern_flag & MNTK_NOMSYNC) == 0) { 3942 vm_object_page_clean(obj, 0, 0, 0); 3943 } 3944 } 3945 error = VOP_FSYNC(vp, MNT_WAIT, VOP_FSYNC_SYSCALL); 3946 if (error == 0 && vp->v_mount) 3947 error = buf_fsync(vp); 3948 vn_unlock(vp); 3949 fdrop(fp); 3950 3951 return (error); 3952 } 3953 3954 int 3955 kern_rename(struct nlookupdata *fromnd, struct nlookupdata *tond) 3956 { 3957 struct nchandle fnchd; 3958 struct nchandle tnchd; 3959 struct namecache *ncp; 3960 struct vnode *fdvp; 3961 struct vnode *tdvp; 3962 struct mount *mp; 3963 int error; 3964 u_int fncp_gen; 3965 u_int tncp_gen; 3966 3967 bwillinode(1); 3968 fromnd->nl_flags |= NLC_REFDVP | NLC_RENAME_SRC; 3969 if ((error = nlookup(fromnd)) != 0) 3970 return (error); 3971 if ((fnchd.ncp = fromnd->nl_nch.ncp->nc_parent) == NULL) 3972 return (ENOENT); 3973 fnchd.mount = fromnd->nl_nch.mount; 3974 cache_hold(&fnchd); 3975 3976 /* 3977 * unlock the source nch so we can lookup the target nch without 3978 * deadlocking. The target may or may not exist so we do not check 3979 * for a target vp like kern_mkdir() and other creation functions do. 3980 * 3981 * The source and target directories are ref'd and rechecked after 3982 * everything is relocked to determine if the source or target file 3983 * has been renamed. 3984 */ 3985 KKASSERT(fromnd->nl_flags & NLC_NCPISLOCKED); 3986 fromnd->nl_flags &= ~NLC_NCPISLOCKED; 3987 3988 fncp_gen = fromnd->nl_nch.ncp->nc_generation; 3989 3990 cache_unlock(&fromnd->nl_nch); 3991 3992 tond->nl_flags |= NLC_RENAME_DST | NLC_REFDVP; 3993 if ((error = nlookup(tond)) != 0) { 3994 cache_drop(&fnchd); 3995 return (error); 3996 } 3997 tncp_gen = tond->nl_nch.ncp->nc_generation; 3998 3999 if ((tnchd.ncp = tond->nl_nch.ncp->nc_parent) == NULL) { 4000 cache_drop(&fnchd); 4001 return (ENOENT); 4002 } 4003 tnchd.mount = tond->nl_nch.mount; 4004 cache_hold(&tnchd); 4005 4006 /* 4007 * If the source and target are the same there is nothing to do 4008 */ 4009 if (fromnd->nl_nch.ncp == tond->nl_nch.ncp) { 4010 cache_drop(&fnchd); 4011 cache_drop(&tnchd); 4012 return (0); 4013 } 4014 4015 /* 4016 * Mount points cannot be renamed or overwritten 4017 */ 4018 if ((fromnd->nl_nch.ncp->nc_flag | tond->nl_nch.ncp->nc_flag) & 4019 NCF_ISMOUNTPT 4020 ) { 4021 cache_drop(&fnchd); 4022 cache_drop(&tnchd); 4023 return (EINVAL); 4024 } 4025 4026 /* 4027 * Relock the source ncp. cache_relock() will deal with any 4028 * deadlocks against the already-locked tond and will also 4029 * make sure both are resolved. 4030 * 4031 * NOTE AFTER RELOCKING: The source or target ncp may have become 4032 * invalid while they were unlocked, nc_vp and nc_mount could 4033 * be NULL. 4034 */ 4035 cache_relock(&fromnd->nl_nch, fromnd->nl_cred, 4036 &tond->nl_nch, tond->nl_cred); 4037 fromnd->nl_flags |= NLC_NCPISLOCKED; 4038 4039 /* 4040 * If the namecache generation changed for either fromnd or tond, 4041 * we must retry. 4042 */ 4043 if (fromnd->nl_nch.ncp->nc_generation != fncp_gen || 4044 tond->nl_nch.ncp->nc_generation != tncp_gen) { 4045 kprintf("kern_rename: retry due to gen on: " 4046 "\"%s\" -> \"%s\"\n", 4047 fromnd->nl_nch.ncp->nc_name, 4048 tond->nl_nch.ncp->nc_name); 4049 cache_drop(&fnchd); 4050 cache_drop(&tnchd); 4051 return (EAGAIN); 4052 } 4053 4054 /* 4055 * If either fromnd or tond are marked destroyed a ripout occured 4056 * out from under us and we must retry. 4057 */ 4058 if ((fromnd->nl_nch.ncp->nc_flag & (NCF_DESTROYED | NCF_UNRESOLVED)) || 4059 fromnd->nl_nch.ncp->nc_vp == NULL || 4060 (tond->nl_nch.ncp->nc_flag & NCF_DESTROYED)) { 4061 kprintf("kern_rename: retry due to ripout on: " 4062 "\"%s\" -> \"%s\"\n", 4063 fromnd->nl_nch.ncp->nc_name, 4064 tond->nl_nch.ncp->nc_name); 4065 cache_drop(&fnchd); 4066 cache_drop(&tnchd); 4067 return (EAGAIN); 4068 } 4069 4070 /* 4071 * Make sure the parent directories linkages are the same. 4072 * XXX shouldn't be needed any more w/ generation check above. 4073 */ 4074 if (fnchd.ncp != fromnd->nl_nch.ncp->nc_parent || 4075 tnchd.ncp != tond->nl_nch.ncp->nc_parent) { 4076 cache_drop(&fnchd); 4077 cache_drop(&tnchd); 4078 return (ENOENT); 4079 } 4080 4081 /* 4082 * Both the source and target must be within the same filesystem and 4083 * in the same filesystem as their parent directories within the 4084 * namecache topology. 4085 * 4086 * NOTE: fromnd's nc_mount or nc_vp could be NULL. 4087 */ 4088 mp = fnchd.mount; 4089 if (mp != tnchd.mount || mp != fromnd->nl_nch.mount || 4090 mp != tond->nl_nch.mount) { 4091 cache_drop(&fnchd); 4092 cache_drop(&tnchd); 4093 return (EXDEV); 4094 } 4095 4096 /* 4097 * Make sure the mount point is writable 4098 */ 4099 if ((error = ncp_writechk(&tond->nl_nch)) != 0) { 4100 cache_drop(&fnchd); 4101 cache_drop(&tnchd); 4102 return (error); 4103 } 4104 4105 /* 4106 * If the target exists and either the source or target is a directory, 4107 * then both must be directories. 4108 * 4109 * Due to relocking of the source, fromnd->nl_nch.ncp->nc_vp might h 4110 * have become NULL. 4111 */ 4112 if (tond->nl_nch.ncp->nc_vp) { 4113 if (fromnd->nl_nch.ncp->nc_vp == NULL) { 4114 error = ENOENT; 4115 } else if (fromnd->nl_nch.ncp->nc_vp->v_type == VDIR) { 4116 if (tond->nl_nch.ncp->nc_vp->v_type != VDIR) 4117 error = ENOTDIR; 4118 } else if (tond->nl_nch.ncp->nc_vp->v_type == VDIR) { 4119 error = EISDIR; 4120 } 4121 } 4122 4123 /* 4124 * You cannot rename a source into itself or a subdirectory of itself. 4125 * We check this by travsersing the target directory upwards looking 4126 * for a match against the source. 4127 * 4128 * XXX MPSAFE 4129 */ 4130 if (error == 0) { 4131 for (ncp = tnchd.ncp; ncp; ncp = ncp->nc_parent) { 4132 if (fromnd->nl_nch.ncp == ncp) { 4133 error = EINVAL; 4134 break; 4135 } 4136 } 4137 } 4138 4139 cache_drop(&fnchd); 4140 cache_drop(&tnchd); 4141 4142 /* 4143 * Even though the namespaces are different, they may still represent 4144 * hardlinks to the same file. The filesystem might have a hard time 4145 * with this so we issue a NREMOVE of the source instead of a NRENAME 4146 * when we detect the situation. 4147 */ 4148 if (error == 0) { 4149 fdvp = fromnd->nl_dvp; 4150 tdvp = tond->nl_dvp; 4151 if (fdvp == NULL || tdvp == NULL) { 4152 error = EPERM; 4153 } else if (fromnd->nl_nch.ncp->nc_vp == tond->nl_nch.ncp->nc_vp) { 4154 error = VOP_NREMOVE(&fromnd->nl_nch, fdvp, 4155 fromnd->nl_cred); 4156 } else { 4157 error = VOP_NRENAME(&fromnd->nl_nch, &tond->nl_nch, 4158 fdvp, tdvp, tond->nl_cred); 4159 } 4160 } 4161 return (error); 4162 } 4163 4164 /* 4165 * rename_args(char *from, char *to) 4166 * 4167 * Rename files. Source and destination must either both be directories, 4168 * or both not be directories. If target is a directory, it must be empty. 4169 */ 4170 int 4171 sys_rename(struct rename_args *uap) 4172 { 4173 struct nlookupdata fromnd, tond; 4174 int error; 4175 4176 do { 4177 error = nlookup_init(&fromnd, uap->from, UIO_USERSPACE, 0); 4178 if (error == 0) { 4179 error = nlookup_init(&tond, uap->to, UIO_USERSPACE, 0); 4180 if (error == 0) 4181 error = kern_rename(&fromnd, &tond); 4182 nlookup_done(&tond); 4183 } 4184 nlookup_done(&fromnd); 4185 } while (error == EAGAIN); 4186 return (error); 4187 } 4188 4189 /* 4190 * renameat_args(int oldfd, char *old, int newfd, char *new) 4191 * 4192 * Rename files using paths relative to the directories associated with 4193 * oldfd and newfd. Source and destination must either both be directories, 4194 * or both not be directories. If target is a directory, it must be empty. 4195 */ 4196 int 4197 sys_renameat(struct renameat_args *uap) 4198 { 4199 struct nlookupdata oldnd, newnd; 4200 struct file *oldfp, *newfp; 4201 int error; 4202 4203 do { 4204 error = nlookup_init_at(&oldnd, &oldfp, 4205 uap->oldfd, uap->old, 4206 UIO_USERSPACE, 0); 4207 if (error == 0) { 4208 error = nlookup_init_at(&newnd, &newfp, 4209 uap->newfd, uap->new, 4210 UIO_USERSPACE, 0); 4211 if (error == 0) 4212 error = kern_rename(&oldnd, &newnd); 4213 nlookup_done_at(&newnd, newfp); 4214 } 4215 nlookup_done_at(&oldnd, oldfp); 4216 } while (error == EAGAIN); 4217 return (error); 4218 } 4219 4220 int 4221 kern_mkdir(struct nlookupdata *nd, int mode) 4222 { 4223 struct thread *td = curthread; 4224 struct proc *p = td->td_proc; 4225 struct vnode *vp; 4226 struct vattr vattr; 4227 int error; 4228 4229 bwillinode(1); 4230 nd->nl_flags |= NLC_WILLBEDIR | NLC_CREATE | NLC_REFDVP; 4231 if ((error = nlookup(nd)) != 0) 4232 return (error); 4233 4234 if (nd->nl_nch.ncp->nc_vp) 4235 return (EEXIST); 4236 if ((error = ncp_writechk(&nd->nl_nch)) != 0) 4237 return (error); 4238 VATTR_NULL(&vattr); 4239 vattr.va_type = VDIR; 4240 vattr.va_mode = (mode & ACCESSPERMS) &~ p->p_fd->fd_cmask; 4241 4242 vp = NULL; 4243 error = VOP_NMKDIR(&nd->nl_nch, nd->nl_dvp, &vp, td->td_ucred, &vattr); 4244 if (error == 0) 4245 vput(vp); 4246 return (error); 4247 } 4248 4249 /* 4250 * mkdir_args(char *path, int mode) 4251 * 4252 * Make a directory file. 4253 */ 4254 int 4255 sys_mkdir(struct mkdir_args *uap) 4256 { 4257 struct nlookupdata nd; 4258 int error; 4259 4260 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0); 4261 if (error == 0) 4262 error = kern_mkdir(&nd, uap->mode); 4263 nlookup_done(&nd); 4264 return (error); 4265 } 4266 4267 /* 4268 * mkdirat_args(int fd, char *path, mode_t mode) 4269 * 4270 * Make a directory file. The path is relative to the directory associated 4271 * with fd. 4272 */ 4273 int 4274 sys_mkdirat(struct mkdirat_args *uap) 4275 { 4276 struct nlookupdata nd; 4277 struct file *fp; 4278 int error; 4279 4280 error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, UIO_USERSPACE, 0); 4281 if (error == 0) 4282 error = kern_mkdir(&nd, uap->mode); 4283 nlookup_done_at(&nd, fp); 4284 return (error); 4285 } 4286 4287 int 4288 kern_rmdir(struct nlookupdata *nd) 4289 { 4290 int error; 4291 4292 bwillinode(1); 4293 nd->nl_flags |= NLC_DELETE | NLC_REFDVP; 4294 if ((error = nlookup(nd)) != 0) 4295 return (error); 4296 4297 /* 4298 * Do not allow directories representing mount points to be 4299 * deleted, even if empty. Check write perms on mount point 4300 * in case the vnode is aliased (aka nullfs). 4301 */ 4302 if (nd->nl_nch.ncp->nc_flag & (NCF_ISMOUNTPT)) 4303 return (EBUSY); 4304 if ((error = ncp_writechk(&nd->nl_nch)) != 0) 4305 return (error); 4306 error = VOP_NRMDIR(&nd->nl_nch, nd->nl_dvp, nd->nl_cred); 4307 return (error); 4308 } 4309 4310 /* 4311 * rmdir_args(char *path) 4312 * 4313 * Remove a directory file. 4314 */ 4315 int 4316 sys_rmdir(struct rmdir_args *uap) 4317 { 4318 struct nlookupdata nd; 4319 int error; 4320 4321 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0); 4322 if (error == 0) 4323 error = kern_rmdir(&nd); 4324 nlookup_done(&nd); 4325 return (error); 4326 } 4327 4328 int 4329 kern_getdirentries(int fd, char *buf, u_int count, long *basep, int *res, 4330 enum uio_seg direction) 4331 { 4332 struct thread *td = curthread; 4333 struct proc *p = td->td_proc; 4334 struct vnode *vp; 4335 struct file *fp; 4336 struct uio auio; 4337 struct iovec aiov; 4338 off_t loff; 4339 int error, eofflag; 4340 4341 if ((error = holdvnode(p->p_fd, fd, &fp)) != 0) 4342 return (error); 4343 if ((fp->f_flag & FREAD) == 0) { 4344 error = EBADF; 4345 goto done; 4346 } 4347 vp = (struct vnode *)fp->f_data; 4348 if (vp->v_type != VDIR) { 4349 error = EINVAL; 4350 goto done; 4351 } 4352 aiov.iov_base = buf; 4353 aiov.iov_len = count; 4354 auio.uio_iov = &aiov; 4355 auio.uio_iovcnt = 1; 4356 auio.uio_rw = UIO_READ; 4357 auio.uio_segflg = direction; 4358 auio.uio_td = td; 4359 auio.uio_resid = count; 4360 loff = auio.uio_offset = fp->f_offset; 4361 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL); 4362 fp->f_offset = auio.uio_offset; 4363 if (error) 4364 goto done; 4365 4366 /* 4367 * WARNING! *basep may not be wide enough to accomodate the 4368 * seek offset. XXX should we hack this to return the upper 32 bits 4369 * for offsets greater then 4G? 4370 */ 4371 if (basep) { 4372 *basep = (long)loff; 4373 } 4374 *res = count - auio.uio_resid; 4375 done: 4376 fdrop(fp); 4377 return (error); 4378 } 4379 4380 /* 4381 * getdirentries_args(int fd, char *buf, u_int conut, long *basep) 4382 * 4383 * Read a block of directory entries in a file system independent format. 4384 */ 4385 int 4386 sys_getdirentries(struct getdirentries_args *uap) 4387 { 4388 long base; 4389 int error; 4390 4391 error = kern_getdirentries(uap->fd, uap->buf, uap->count, &base, 4392 &uap->sysmsg_result, UIO_USERSPACE); 4393 4394 if (error == 0 && uap->basep) 4395 error = copyout(&base, uap->basep, sizeof(*uap->basep)); 4396 return (error); 4397 } 4398 4399 /* 4400 * getdents_args(int fd, char *buf, size_t count) 4401 */ 4402 int 4403 sys_getdents(struct getdents_args *uap) 4404 { 4405 int error; 4406 4407 error = kern_getdirentries(uap->fd, uap->buf, uap->count, NULL, 4408 &uap->sysmsg_result, UIO_USERSPACE); 4409 4410 return (error); 4411 } 4412 4413 /* 4414 * Set the mode mask for creation of filesystem nodes. 4415 * 4416 * umask(int newmask) 4417 */ 4418 int 4419 sys_umask(struct umask_args *uap) 4420 { 4421 struct thread *td = curthread; 4422 struct proc *p = td->td_proc; 4423 struct filedesc *fdp; 4424 4425 fdp = p->p_fd; 4426 uap->sysmsg_result = fdp->fd_cmask; 4427 fdp->fd_cmask = uap->newmask & ALLPERMS; 4428 return (0); 4429 } 4430 4431 /* 4432 * revoke(char *path) 4433 * 4434 * Void all references to file by ripping underlying filesystem 4435 * away from vnode. 4436 */ 4437 int 4438 sys_revoke(struct revoke_args *uap) 4439 { 4440 struct nlookupdata nd; 4441 struct vattr vattr; 4442 struct vnode *vp; 4443 struct ucred *cred; 4444 int error; 4445 4446 vp = NULL; 4447 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 4448 if (error == 0) 4449 error = nlookup(&nd); 4450 if (error == 0) 4451 error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp); 4452 cred = crhold(nd.nl_cred); 4453 nlookup_done(&nd); 4454 if (error == 0) { 4455 if (error == 0) 4456 error = VOP_GETATTR(vp, &vattr); 4457 if (error == 0 && cred->cr_uid != vattr.va_uid) 4458 error = priv_check_cred(cred, PRIV_VFS_REVOKE, 0); 4459 if (error == 0 && (vp->v_type == VCHR || vp->v_type == VBLK)) { 4460 if (vcount(vp) > 0) 4461 error = vrevoke(vp, cred); 4462 } else if (error == 0) { 4463 error = vrevoke(vp, cred); 4464 } 4465 vrele(vp); 4466 } 4467 if (cred) 4468 crfree(cred); 4469 return (error); 4470 } 4471 4472 /* 4473 * getfh_args(char *fname, fhandle_t *fhp) 4474 * 4475 * Get (NFS) file handle 4476 * 4477 * NOTE: We use the fsid of the covering mount, even if it is a nullfs 4478 * mount. This allows nullfs mounts to be explicitly exported. 4479 * 4480 * WARNING: nullfs mounts of HAMMER PFS ROOTs are safe. 4481 * 4482 * nullfs mounts of subdirectories are not safe. That is, it will 4483 * work, but you do not really have protection against access to 4484 * the related parent directories. 4485 */ 4486 int 4487 sys_getfh(struct getfh_args *uap) 4488 { 4489 struct thread *td = curthread; 4490 struct nlookupdata nd; 4491 fhandle_t fh; 4492 struct vnode *vp; 4493 struct mount *mp; 4494 int error; 4495 4496 /* 4497 * Must be super user 4498 */ 4499 if ((error = priv_check(td, PRIV_ROOT)) != 0) 4500 return (error); 4501 4502 vp = NULL; 4503 error = nlookup_init(&nd, uap->fname, UIO_USERSPACE, NLC_FOLLOW); 4504 if (error == 0) 4505 error = nlookup(&nd); 4506 if (error == 0) 4507 error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp); 4508 mp = nd.nl_nch.mount; 4509 nlookup_done(&nd); 4510 if (error == 0) { 4511 bzero(&fh, sizeof(fh)); 4512 fh.fh_fsid = mp->mnt_stat.f_fsid; 4513 error = VFS_VPTOFH(vp, &fh.fh_fid); 4514 vput(vp); 4515 if (error == 0) 4516 error = copyout(&fh, uap->fhp, sizeof(fh)); 4517 } 4518 return (error); 4519 } 4520 4521 /* 4522 * fhopen_args(const struct fhandle *u_fhp, int flags) 4523 * 4524 * syscall for the rpc.lockd to use to translate a NFS file handle into 4525 * an open descriptor. 4526 * 4527 * warning: do not remove the priv_check() call or this becomes one giant 4528 * security hole. 4529 */ 4530 int 4531 sys_fhopen(struct fhopen_args *uap) 4532 { 4533 struct thread *td = curthread; 4534 struct filedesc *fdp = td->td_proc->p_fd; 4535 struct mount *mp; 4536 struct vnode *vp; 4537 struct fhandle fhp; 4538 struct vattr vat; 4539 struct vattr *vap = &vat; 4540 struct flock lf; 4541 int fmode, mode, error = 0, type; 4542 struct file *nfp; 4543 struct file *fp; 4544 int indx; 4545 4546 /* 4547 * Must be super user 4548 */ 4549 error = priv_check(td, PRIV_ROOT); 4550 if (error) 4551 return (error); 4552 4553 fmode = FFLAGS(uap->flags); 4554 4555 /* 4556 * Why not allow a non-read/write open for our lockd? 4557 */ 4558 if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT)) 4559 return (EINVAL); 4560 error = copyin(uap->u_fhp, &fhp, sizeof(fhp)); 4561 if (error) 4562 return(error); 4563 4564 /* 4565 * Find the mount point 4566 */ 4567 mp = vfs_getvfs(&fhp.fh_fsid); 4568 if (mp == NULL) { 4569 error = ESTALE; 4570 goto done2; 4571 } 4572 /* now give me my vnode, it gets returned to me locked */ 4573 error = VFS_FHTOVP(mp, NULL, &fhp.fh_fid, &vp); 4574 if (error) 4575 goto done; 4576 /* 4577 * from now on we have to make sure not 4578 * to forget about the vnode 4579 * any error that causes an abort must vput(vp) 4580 * just set error = err and 'goto bad;'. 4581 */ 4582 4583 /* 4584 * from vn_open 4585 */ 4586 if (vp->v_type == VLNK) { 4587 error = EMLINK; 4588 goto bad; 4589 } 4590 if (vp->v_type == VSOCK) { 4591 error = EOPNOTSUPP; 4592 goto bad; 4593 } 4594 mode = 0; 4595 if (fmode & (FWRITE | O_TRUNC)) { 4596 if (vp->v_type == VDIR) { 4597 error = EISDIR; 4598 goto bad; 4599 } 4600 error = vn_writechk(vp, NULL); 4601 if (error) 4602 goto bad; 4603 mode |= VWRITE; 4604 } 4605 if (fmode & FREAD) 4606 mode |= VREAD; 4607 if (mode) { 4608 error = VOP_ACCESS(vp, mode, td->td_ucred); 4609 if (error) 4610 goto bad; 4611 } 4612 if (fmode & O_TRUNC) { 4613 vn_unlock(vp); /* XXX */ 4614 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); /* XXX */ 4615 VATTR_NULL(vap); 4616 vap->va_size = 0; 4617 error = VOP_SETATTR(vp, vap, td->td_ucred); 4618 if (error) 4619 goto bad; 4620 } 4621 4622 /* 4623 * VOP_OPEN needs the file pointer so it can potentially override 4624 * it. 4625 * 4626 * WARNING! no f_nchandle will be associated when fhopen()ing a 4627 * directory. XXX 4628 */ 4629 if ((error = falloc(td->td_lwp, &nfp, &indx)) != 0) 4630 goto bad; 4631 fp = nfp; 4632 4633 error = VOP_OPEN(vp, fmode, td->td_ucred, fp); 4634 if (error) { 4635 /* 4636 * setting f_ops this way prevents VOP_CLOSE from being 4637 * called or fdrop() releasing the vp from v_data. Since 4638 * the VOP_OPEN failed we don't want to VOP_CLOSE. 4639 */ 4640 fp->f_ops = &badfileops; 4641 fp->f_data = NULL; 4642 goto bad_drop; 4643 } 4644 4645 /* 4646 * The fp is given its own reference, we still have our ref and lock. 4647 * 4648 * Assert that all regular files must be created with a VM object. 4649 */ 4650 if (vp->v_type == VREG && vp->v_object == NULL) { 4651 kprintf("fhopen: regular file did not " 4652 "have VM object: %p\n", 4653 vp); 4654 goto bad_drop; 4655 } 4656 4657 /* 4658 * The open was successful. Handle any locking requirements. 4659 */ 4660 if (fmode & (O_EXLOCK | O_SHLOCK)) { 4661 lf.l_whence = SEEK_SET; 4662 lf.l_start = 0; 4663 lf.l_len = 0; 4664 if (fmode & O_EXLOCK) 4665 lf.l_type = F_WRLCK; 4666 else 4667 lf.l_type = F_RDLCK; 4668 if (fmode & FNONBLOCK) 4669 type = 0; 4670 else 4671 type = F_WAIT; 4672 vn_unlock(vp); 4673 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, 4674 &lf, type)) != 0) { 4675 /* 4676 * release our private reference. 4677 */ 4678 fsetfd(fdp, NULL, indx); 4679 fdrop(fp); 4680 vrele(vp); 4681 goto done; 4682 } 4683 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 4684 atomic_set_int(&fp->f_flag, FHASLOCK); /* race ok */ 4685 } 4686 4687 /* 4688 * Clean up. Associate the file pointer with the previously 4689 * reserved descriptor and return it. 4690 */ 4691 vput(vp); 4692 if (uap->flags & O_CLOEXEC) 4693 fdp->fd_files[indx].fileflags |= UF_EXCLOSE; 4694 fsetfd(fdp, fp, indx); 4695 fdrop(fp); 4696 uap->sysmsg_result = indx; 4697 mount_drop(mp); 4698 4699 return (error); 4700 4701 bad_drop: 4702 fsetfd(fdp, NULL, indx); 4703 fdrop(fp); 4704 bad: 4705 vput(vp); 4706 done: 4707 mount_drop(mp); 4708 done2: 4709 return (error); 4710 } 4711 4712 /* 4713 * fhstat_args(struct fhandle *u_fhp, struct stat *sb) 4714 */ 4715 int 4716 sys_fhstat(struct fhstat_args *uap) 4717 { 4718 struct thread *td = curthread; 4719 struct stat sb; 4720 fhandle_t fh; 4721 struct mount *mp; 4722 struct vnode *vp; 4723 int error; 4724 4725 /* 4726 * Must be super user 4727 */ 4728 error = priv_check(td, PRIV_ROOT); 4729 if (error) 4730 return (error); 4731 4732 error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t)); 4733 if (error) 4734 return (error); 4735 4736 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) 4737 error = ESTALE; 4738 if (error == 0) { 4739 if ((error = VFS_FHTOVP(mp, NULL, &fh.fh_fid, &vp)) == 0) { 4740 error = vn_stat(vp, &sb, td->td_ucred); 4741 vput(vp); 4742 } 4743 } 4744 if (error == 0) 4745 error = copyout(&sb, uap->sb, sizeof(sb)); 4746 if (mp) 4747 mount_drop(mp); 4748 4749 return (error); 4750 } 4751 4752 /* 4753 * fhstatfs_args(struct fhandle *u_fhp, struct statfs *buf) 4754 */ 4755 int 4756 sys_fhstatfs(struct fhstatfs_args *uap) 4757 { 4758 struct thread *td = curthread; 4759 struct proc *p = td->td_proc; 4760 struct statfs *sp; 4761 struct mount *mp; 4762 struct vnode *vp; 4763 struct statfs sb; 4764 char *fullpath, *freepath; 4765 fhandle_t fh; 4766 int error; 4767 4768 /* 4769 * Must be super user 4770 */ 4771 if ((error = priv_check(td, PRIV_ROOT))) 4772 return (error); 4773 4774 if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0) 4775 return (error); 4776 4777 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) { 4778 error = ESTALE; 4779 goto done; 4780 } 4781 if (p != NULL && !chroot_visible_mnt(mp, p)) { 4782 error = ESTALE; 4783 goto done; 4784 } 4785 4786 if ((error = VFS_FHTOVP(mp, NULL, &fh.fh_fid, &vp)) != 0) 4787 goto done; 4788 mp = vp->v_mount; 4789 sp = &mp->mnt_stat; 4790 vput(vp); 4791 if ((error = VFS_STATFS(mp, sp, td->td_ucred)) != 0) 4792 goto done; 4793 4794 error = mount_path(p, mp, &fullpath, &freepath); 4795 if (error) 4796 goto done; 4797 bzero(sp->f_mntonname, sizeof(sp->f_mntonname)); 4798 strlcpy(sp->f_mntonname, fullpath, sizeof(sp->f_mntonname)); 4799 kfree(freepath, M_TEMP); 4800 4801 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 4802 if (priv_check(td, PRIV_ROOT)) { 4803 bcopy(sp, &sb, sizeof(sb)); 4804 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; 4805 sp = &sb; 4806 } 4807 error = copyout(sp, uap->buf, sizeof(*sp)); 4808 done: 4809 if (mp) 4810 mount_drop(mp); 4811 4812 return (error); 4813 } 4814 4815 /* 4816 * fhstatvfs_args(struct fhandle *u_fhp, struct statvfs *buf) 4817 */ 4818 int 4819 sys_fhstatvfs(struct fhstatvfs_args *uap) 4820 { 4821 struct thread *td = curthread; 4822 struct proc *p = td->td_proc; 4823 struct statvfs *sp; 4824 struct mount *mp; 4825 struct vnode *vp; 4826 fhandle_t fh; 4827 int error; 4828 4829 /* 4830 * Must be super user 4831 */ 4832 if ((error = priv_check(td, PRIV_ROOT))) 4833 return (error); 4834 4835 if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0) 4836 return (error); 4837 4838 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) { 4839 error = ESTALE; 4840 goto done; 4841 } 4842 if (p != NULL && !chroot_visible_mnt(mp, p)) { 4843 error = ESTALE; 4844 goto done; 4845 } 4846 4847 if ((error = VFS_FHTOVP(mp, NULL, &fh.fh_fid, &vp))) 4848 goto done; 4849 mp = vp->v_mount; 4850 sp = &mp->mnt_vstat; 4851 vput(vp); 4852 if ((error = VFS_STATVFS(mp, sp, td->td_ucred)) != 0) 4853 goto done; 4854 4855 sp->f_flag = 0; 4856 if (mp->mnt_flag & MNT_RDONLY) 4857 sp->f_flag |= ST_RDONLY; 4858 if (mp->mnt_flag & MNT_NOSUID) 4859 sp->f_flag |= ST_NOSUID; 4860 error = copyout(sp, uap->buf, sizeof(*sp)); 4861 done: 4862 if (mp) 4863 mount_drop(mp); 4864 return (error); 4865 } 4866 4867 4868 /* 4869 * Syscall to push extended attribute configuration information into the 4870 * VFS. Accepts a path, which it converts to a mountpoint, as well as 4871 * a command (int cmd), and attribute name and misc data. For now, the 4872 * attribute name is left in userspace for consumption by the VFS_op. 4873 * It will probably be changed to be copied into sysspace by the 4874 * syscall in the future, once issues with various consumers of the 4875 * attribute code have raised their hands. 4876 * 4877 * Currently this is used only by UFS Extended Attributes. 4878 */ 4879 int 4880 sys_extattrctl(struct extattrctl_args *uap) 4881 { 4882 struct nlookupdata nd; 4883 struct vnode *vp; 4884 char attrname[EXTATTR_MAXNAMELEN]; 4885 int error; 4886 size_t size; 4887 4888 attrname[0] = 0; 4889 vp = NULL; 4890 error = 0; 4891 4892 if (error == 0 && uap->filename) { 4893 error = nlookup_init(&nd, uap->filename, UIO_USERSPACE, 4894 NLC_FOLLOW); 4895 if (error == 0) 4896 error = nlookup(&nd); 4897 if (error == 0) 4898 error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp); 4899 nlookup_done(&nd); 4900 } 4901 4902 if (error == 0 && uap->attrname) { 4903 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, 4904 &size); 4905 } 4906 4907 if (error == 0) { 4908 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 4909 if (error == 0) 4910 error = nlookup(&nd); 4911 if (error == 0) 4912 error = ncp_writechk(&nd.nl_nch); 4913 if (error == 0) { 4914 error = VFS_EXTATTRCTL(nd.nl_nch.mount, uap->cmd, vp, 4915 uap->attrnamespace, 4916 uap->attrname, nd.nl_cred); 4917 } 4918 nlookup_done(&nd); 4919 } 4920 4921 return (error); 4922 } 4923 4924 /* 4925 * Syscall to get a named extended attribute on a file or directory. 4926 */ 4927 int 4928 sys_extattr_set_file(struct extattr_set_file_args *uap) 4929 { 4930 char attrname[EXTATTR_MAXNAMELEN]; 4931 struct nlookupdata nd; 4932 struct vnode *vp; 4933 struct uio auio; 4934 struct iovec aiov; 4935 int error; 4936 4937 error = copyin(uap->attrname, attrname, EXTATTR_MAXNAMELEN); 4938 if (error) 4939 return (error); 4940 4941 vp = NULL; 4942 4943 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 4944 if (error == 0) 4945 error = nlookup(&nd); 4946 if (error == 0) 4947 error = ncp_writechk(&nd.nl_nch); 4948 if (error == 0) 4949 error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp); 4950 if (error) { 4951 nlookup_done(&nd); 4952 return (error); 4953 } 4954 4955 bzero(&auio, sizeof(auio)); 4956 aiov.iov_base = uap->data; 4957 aiov.iov_len = uap->nbytes; 4958 auio.uio_iov = &aiov; 4959 auio.uio_iovcnt = 1; 4960 auio.uio_offset = 0; 4961 auio.uio_resid = uap->nbytes; 4962 auio.uio_rw = UIO_WRITE; 4963 auio.uio_td = curthread; 4964 4965 error = VOP_SETEXTATTR(vp, uap->attrnamespace, attrname, 4966 &auio, nd.nl_cred); 4967 4968 vput(vp); 4969 nlookup_done(&nd); 4970 return (error); 4971 } 4972 4973 /* 4974 * Syscall to get a named extended attribute on a file or directory. 4975 */ 4976 int 4977 sys_extattr_get_file(struct extattr_get_file_args *uap) 4978 { 4979 char attrname[EXTATTR_MAXNAMELEN]; 4980 struct nlookupdata nd; 4981 struct uio auio; 4982 struct iovec aiov; 4983 struct vnode *vp; 4984 int error; 4985 4986 error = copyin(uap->attrname, attrname, EXTATTR_MAXNAMELEN); 4987 if (error) 4988 return (error); 4989 4990 vp = NULL; 4991 4992 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 4993 if (error == 0) 4994 error = nlookup(&nd); 4995 if (error == 0) 4996 error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_SHARED, &vp); 4997 if (error) { 4998 nlookup_done(&nd); 4999 return (error); 5000 } 5001 5002 bzero(&auio, sizeof(auio)); 5003 aiov.iov_base = uap->data; 5004 aiov.iov_len = uap->nbytes; 5005 auio.uio_iov = &aiov; 5006 auio.uio_iovcnt = 1; 5007 auio.uio_offset = 0; 5008 auio.uio_resid = uap->nbytes; 5009 auio.uio_rw = UIO_READ; 5010 auio.uio_td = curthread; 5011 5012 error = VOP_GETEXTATTR(vp, uap->attrnamespace, attrname, 5013 &auio, nd.nl_cred); 5014 uap->sysmsg_result = uap->nbytes - auio.uio_resid; 5015 5016 vput(vp); 5017 nlookup_done(&nd); 5018 return(error); 5019 } 5020 5021 /* 5022 * Syscall to delete a named extended attribute from a file or directory. 5023 * Accepts attribute name. The real work happens in VOP_SETEXTATTR(). 5024 */ 5025 int 5026 sys_extattr_delete_file(struct extattr_delete_file_args *uap) 5027 { 5028 char attrname[EXTATTR_MAXNAMELEN]; 5029 struct nlookupdata nd; 5030 struct vnode *vp; 5031 int error; 5032 5033 error = copyin(uap->attrname, attrname, EXTATTR_MAXNAMELEN); 5034 if (error) 5035 return(error); 5036 5037 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); 5038 if (error == 0) 5039 error = nlookup(&nd); 5040 if (error == 0) 5041 error = ncp_writechk(&nd.nl_nch); 5042 if (error == 0) { 5043 error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp); 5044 if (error == 0) { 5045 error = VOP_SETEXTATTR(vp, uap->attrnamespace, 5046 attrname, NULL, nd.nl_cred); 5047 vput(vp); 5048 } 5049 } 5050 nlookup_done(&nd); 5051 return(error); 5052 } 5053 5054 /* 5055 * Determine if the mount is visible to the process. 5056 */ 5057 static int 5058 chroot_visible_mnt(struct mount *mp, struct proc *p) 5059 { 5060 struct nchandle nch; 5061 5062 /* 5063 * Traverse from the mount point upwards. If we hit the process 5064 * root then the mount point is visible to the process. 5065 */ 5066 nch = mp->mnt_ncmountpt; 5067 while (nch.ncp) { 5068 if (nch.mount == p->p_fd->fd_nrdir.mount && 5069 nch.ncp == p->p_fd->fd_nrdir.ncp) { 5070 return(1); 5071 } 5072 if (nch.ncp == nch.mount->mnt_ncmountpt.ncp) { 5073 nch = nch.mount->mnt_ncmounton; 5074 } else { 5075 nch.ncp = nch.ncp->nc_parent; 5076 } 5077 } 5078 5079 /* 5080 * If the mount point is not visible to the process, but the 5081 * process root is in a subdirectory of the mount, return 5082 * TRUE anyway. 5083 */ 5084 if (p->p_fd->fd_nrdir.mount == mp) 5085 return(1); 5086 5087 return(0); 5088 } 5089 5090