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