1 /* $NetBSD: vfs_syscalls.c,v 1.243 2006/06/17 07:06:51 yamt Exp $ */ 2 3 /* 4 * Copyright (c) 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * (c) UNIX System Laboratories, Inc. 7 * All or some portions of this file are derived from material licensed 8 * to the University of California by American Telephone and Telegraph 9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 10 * the permission of UNIX System Laboratories, Inc. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)vfs_syscalls.c 8.42 (Berkeley) 7/31/95 37 */ 38 39 #include <sys/cdefs.h> 40 __KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.243 2006/06/17 07:06:51 yamt Exp $"); 41 42 #include "opt_compat_netbsd.h" 43 #include "opt_compat_43.h" 44 #include "opt_ktrace.h" 45 #include "opt_verified_exec.h" 46 #include "fss.h" 47 48 #include <sys/param.h> 49 #include <sys/systm.h> 50 #include <sys/namei.h> 51 #include <sys/filedesc.h> 52 #include <sys/kernel.h> 53 #include <sys/file.h> 54 #include <sys/stat.h> 55 #include <sys/vnode.h> 56 #include <sys/mount.h> 57 #include <sys/proc.h> 58 #include <sys/uio.h> 59 #include <sys/malloc.h> 60 #include <sys/dirent.h> 61 #include <sys/sysctl.h> 62 #include <sys/sa.h> 63 #include <sys/syscallargs.h> 64 #ifdef KTRACE 65 #include <sys/ktrace.h> 66 #endif 67 #ifdef VERIFIED_EXEC 68 #include <sys/verified_exec.h> 69 #endif /* VERIFIED_EXEC */ 70 #include <sys/kauth.h> 71 72 #include <miscfs/genfs/genfs.h> 73 #include <miscfs/syncfs/syncfs.h> 74 75 #ifdef COMPAT_30 76 #include "opt_nfsserver.h" 77 #include <nfs/rpcv2.h> 78 #include <nfs/nfsproto.h> 79 #include <nfs/nfs.h> 80 #include <nfs/nfs_var.h> 81 #endif 82 83 #if NFSS > 0 84 #include <dev/fssvar.h> 85 #endif 86 87 MALLOC_DEFINE(M_MOUNT, "mount", "vfs mount struct"); 88 89 static int change_dir(struct nameidata *, struct lwp *); 90 static int change_flags(struct vnode *, u_long, struct lwp *); 91 static int change_mode(struct vnode *, int, struct lwp *l); 92 static int change_owner(struct vnode *, uid_t, gid_t, struct lwp *, int); 93 static int change_utimes(struct vnode *vp, const struct timeval *, 94 struct lwp *l); 95 static int rename_files(const char *, const char *, struct lwp *, int); 96 97 void checkdirs(struct vnode *); 98 99 int dovfsusermount = 0; 100 101 /* 102 * Virtual File System System Calls 103 */ 104 105 /* 106 * Mount a file system. 107 */ 108 109 #if defined(COMPAT_09) || defined(COMPAT_43) 110 /* 111 * This table is used to maintain compatibility with 4.3BSD 112 * and NetBSD 0.9 mount syscalls. Note, the order is important! 113 * 114 * Do not modify this table. It should only contain filesystems 115 * supported by NetBSD 0.9 and 4.3BSD. 116 */ 117 const char * const mountcompatnames[] = { 118 NULL, /* 0 = MOUNT_NONE */ 119 MOUNT_FFS, /* 1 = MOUNT_UFS */ 120 MOUNT_NFS, /* 2 */ 121 MOUNT_MFS, /* 3 */ 122 MOUNT_MSDOS, /* 4 */ 123 MOUNT_CD9660, /* 5 = MOUNT_ISOFS */ 124 MOUNT_FDESC, /* 6 */ 125 MOUNT_KERNFS, /* 7 */ 126 NULL, /* 8 = MOUNT_DEVFS */ 127 MOUNT_AFS, /* 9 */ 128 }; 129 const int nmountcompatnames = sizeof(mountcompatnames) / 130 sizeof(mountcompatnames[0]); 131 #endif /* COMPAT_09 || COMPAT_43 */ 132 133 /* ARGSUSED */ 134 int 135 sys_mount(struct lwp *l, void *v, register_t *retval) 136 { 137 struct sys_mount_args /* { 138 syscallarg(const char *) type; 139 syscallarg(const char *) path; 140 syscallarg(int) flags; 141 syscallarg(void *) data; 142 } */ *uap = v; 143 struct proc *p = l->l_proc; 144 struct vnode *vp; 145 struct mount *mp; 146 int error, flag = 0; 147 char fstypename[MFSNAMELEN]; 148 struct vattr va; 149 struct nameidata nd; 150 struct vfsops *vfs; 151 152 /* 153 * if MNT_GETARGS is specified, it should be only flag. 154 */ 155 156 if ((SCARG(uap, flags) & MNT_GETARGS) != 0 && 157 (SCARG(uap, flags) & ~MNT_GETARGS) != 0) { 158 return EINVAL; 159 } 160 161 if (dovfsusermount == 0 && (SCARG(uap, flags) & MNT_GETARGS) == 0 && 162 (error = kauth_authorize_generic(p->p_cred, KAUTH_GENERIC_ISSUSER, 163 &p->p_acflag))) 164 return (error); 165 /* 166 * Get vnode to be covered 167 */ 168 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, 169 SCARG(uap, path), l); 170 if ((error = namei(&nd)) != 0) 171 return (error); 172 vp = nd.ni_vp; 173 /* 174 * A lookup in VFS_MOUNT might result in an attempt to 175 * lock this vnode again, so make the lock recursive. 176 */ 177 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY | LK_SETRECURSE); 178 if (SCARG(uap, flags) & (MNT_UPDATE | MNT_GETARGS)) { 179 if ((vp->v_flag & VROOT) == 0) { 180 vput(vp); 181 return (EINVAL); 182 } 183 mp = vp->v_mount; 184 flag = mp->mnt_flag; 185 vfs = mp->mnt_op; 186 /* 187 * We only allow the filesystem to be reloaded if it 188 * is currently mounted read-only. 189 */ 190 if ((SCARG(uap, flags) & MNT_RELOAD) && 191 ((mp->mnt_flag & MNT_RDONLY) == 0)) { 192 vput(vp); 193 return (EOPNOTSUPP); /* Needs translation */ 194 } 195 /* 196 * In "highly secure" mode, don't let the caller do anything 197 * but downgrade a filesystem from read-write to read-only. 198 * (see also below; MNT_UPDATE or MNT_GETARGS is required.) 199 */ 200 if (securelevel >= 2 && 201 SCARG(uap, flags) != MNT_GETARGS && 202 SCARG(uap, flags) != 203 (mp->mnt_flag | MNT_RDONLY | 204 MNT_RELOAD | MNT_FORCE | MNT_UPDATE)) { 205 vput(vp); 206 return (EPERM); 207 } 208 mp->mnt_flag |= SCARG(uap, flags) & 209 (MNT_RELOAD | MNT_FORCE | MNT_UPDATE | MNT_GETARGS); 210 /* 211 * Only root, or the user that did the original mount is 212 * permitted to update it. 213 */ 214 if ((mp->mnt_flag & MNT_GETARGS) == 0 && 215 mp->mnt_stat.f_owner != kauth_cred_geteuid(p->p_cred) && 216 (error = kauth_authorize_generic(p->p_cred, 217 KAUTH_GENERIC_ISSUSER, 218 &p->p_acflag)) != 0) { 219 vput(vp); 220 return (error); 221 } 222 /* 223 * Do not allow NFS export by non-root users. For non-root 224 * users, silently enforce MNT_NOSUID and MNT_NODEV, and 225 * MNT_NOEXEC if mount point is already MNT_NOEXEC. 226 */ 227 if (kauth_cred_geteuid(p->p_cred) != 0) { 228 if (SCARG(uap, flags) & MNT_EXPORTED) { 229 vput(vp); 230 return (EPERM); 231 } 232 SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV; 233 if (flag & MNT_NOEXEC) 234 SCARG(uap, flags) |= MNT_NOEXEC; 235 } 236 if (vfs_busy(mp, LK_NOWAIT, 0)) { 237 vput(vp); 238 return (EPERM); 239 } 240 goto update; 241 } else { 242 if (securelevel >= 2) { 243 vput(vp); 244 return (EPERM); 245 } 246 } 247 /* 248 * If the user is not root, ensure that they own the directory 249 * onto which we are attempting to mount. 250 */ 251 if ((error = VOP_GETATTR(vp, &va, p->p_cred, l)) != 0 || 252 (va.va_uid != kauth_cred_geteuid(p->p_cred) && 253 (error = kauth_authorize_generic(p->p_cred, 254 KAUTH_GENERIC_ISSUSER, 255 &p->p_acflag)) != 0)) { 256 vput(vp); 257 return (error); 258 } 259 /* 260 * Do not allow NFS export by non-root users. For non-root users, 261 * silently enforce MNT_NOSUID and MNT_NODEV, and MNT_NOEXEC if the 262 * mount point is already MNT_NOEXEC. 263 */ 264 if (kauth_cred_geteuid(p->p_cred) != 0) { 265 if (SCARG(uap, flags) & MNT_EXPORTED) { 266 vput(vp); 267 return (EPERM); 268 } 269 SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV; 270 if (vp->v_mount->mnt_flag & MNT_NOEXEC) 271 SCARG(uap, flags) |= MNT_NOEXEC; 272 } 273 if ((error = vinvalbuf(vp, V_SAVE, p->p_cred, l, 0, 0)) != 0) { 274 vput(vp); 275 return (error); 276 } 277 if (vp->v_type != VDIR) { 278 vput(vp); 279 return (ENOTDIR); 280 } 281 error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL); 282 if (error) { 283 #if defined(COMPAT_09) || defined(COMPAT_43) 284 /* 285 * Historically, filesystem types were identified by numbers. 286 * If we get an integer for the filesystem type instead of a 287 * string, we check to see if it matches one of the historic 288 * filesystem types. 289 */ 290 u_long fsindex = (u_long)SCARG(uap, type); 291 if (fsindex >= nmountcompatnames || 292 mountcompatnames[fsindex] == NULL) { 293 vput(vp); 294 return (ENODEV); 295 } 296 strncpy(fstypename, mountcompatnames[fsindex], MFSNAMELEN); 297 #else 298 vput(vp); 299 return (error); 300 #endif 301 } 302 #ifdef COMPAT_10 303 /* Accept `ufs' as an alias for `ffs'. */ 304 if (!strncmp(fstypename, "ufs", MFSNAMELEN)) 305 strncpy(fstypename, "ffs", MFSNAMELEN); 306 #endif 307 if ((vfs = vfs_getopsbyname(fstypename)) == NULL) { 308 vput(vp); 309 return (ENODEV); 310 } 311 if (vp->v_mountedhere != NULL) { 312 vput(vp); 313 return (EBUSY); 314 } 315 316 /* 317 * Allocate and initialize the file system. 318 */ 319 mp = (struct mount *)malloc((u_long)sizeof(struct mount), 320 M_MOUNT, M_WAITOK); 321 memset((char *)mp, 0, (u_long)sizeof(struct mount)); 322 lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0); 323 simple_lock_init(&mp->mnt_slock); 324 (void)vfs_busy(mp, LK_NOWAIT, 0); 325 mp->mnt_op = vfs; 326 vfs->vfs_refcount++; 327 mp->mnt_vnodecovered = vp; 328 mp->mnt_stat.f_owner = kauth_cred_geteuid(p->p_cred); 329 mp->mnt_unmounter = NULL; 330 mp->mnt_leaf = mp; 331 332 /* 333 * The underlying file system may refuse the mount for 334 * various reasons. Allow the user to force it to happen. 335 */ 336 mp->mnt_flag |= SCARG(uap, flags) & MNT_FORCE; 337 update: 338 if ((SCARG(uap, flags) & MNT_GETARGS) == 0) { 339 /* 340 * Set the mount level flags. 341 */ 342 if (SCARG(uap, flags) & MNT_RDONLY) 343 mp->mnt_flag |= MNT_RDONLY; 344 else if (mp->mnt_flag & MNT_RDONLY) 345 mp->mnt_iflag |= IMNT_WANTRDWR; 346 mp->mnt_flag &= 347 ~(MNT_NOSUID | MNT_NOEXEC | MNT_NODEV | 348 MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_NOCOREDUMP | 349 MNT_NOATIME | MNT_NODEVMTIME | MNT_SYMPERM | MNT_SOFTDEP); 350 mp->mnt_flag |= SCARG(uap, flags) & 351 (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV | 352 MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_NOCOREDUMP | 353 MNT_NOATIME | MNT_NODEVMTIME | MNT_SYMPERM | MNT_SOFTDEP | 354 MNT_IGNORE); 355 } 356 /* 357 * Mount the filesystem. 358 */ 359 error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, l); 360 if (mp->mnt_flag & (MNT_UPDATE | MNT_GETARGS)) { 361 #if defined(COMPAT_30) && defined(NFSSERVER) 362 if (mp->mnt_flag & MNT_UPDATE && error != 0) { 363 int error2; 364 365 /* Update failed; let's try and see if it was an 366 * export request. */ 367 error2 = nfs_update_exports_30(mp, SCARG(uap, path), 368 SCARG(uap, data), l); 369 370 /* Only update error code if the export request was 371 * understood but some problem occurred while 372 * processing it. */ 373 if (error2 != EJUSTRETURN) 374 error = error2; 375 } 376 #endif 377 if (mp->mnt_iflag & IMNT_WANTRDWR) 378 mp->mnt_flag &= ~MNT_RDONLY; 379 if (error) 380 mp->mnt_flag = flag; 381 mp->mnt_flag &=~ 382 (MNT_RELOAD | MNT_FORCE | MNT_UPDATE | MNT_GETARGS); 383 mp->mnt_iflag &=~ IMNT_WANTRDWR; 384 if ((mp->mnt_flag & (MNT_RDONLY | MNT_ASYNC)) == 0) { 385 if (mp->mnt_syncer == NULL) 386 error = vfs_allocate_syncvnode(mp); 387 } else { 388 if (mp->mnt_syncer != NULL) 389 vfs_deallocate_syncvnode(mp); 390 } 391 vfs_unbusy(mp); 392 VOP_UNLOCK(vp, 0); 393 vrele(vp); 394 return (error); 395 } 396 /* 397 * Put the new filesystem on the mount list after root. 398 */ 399 cache_purge(vp); 400 if (!error) { 401 mp->mnt_flag &=~ 402 (MNT_RELOAD | MNT_FORCE | MNT_UPDATE | MNT_GETARGS); 403 mp->mnt_iflag &=~ IMNT_WANTRDWR; 404 vp->v_mountedhere = mp; 405 simple_lock(&mountlist_slock); 406 CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); 407 simple_unlock(&mountlist_slock); 408 checkdirs(vp); 409 VOP_UNLOCK(vp, 0); 410 if ((mp->mnt_flag & (MNT_RDONLY | MNT_ASYNC)) == 0) 411 error = vfs_allocate_syncvnode(mp); 412 vfs_unbusy(mp); 413 (void) VFS_STATVFS(mp, &mp->mnt_stat, l); 414 if ((error = VFS_START(mp, 0, l))) 415 vrele(vp); 416 } else { 417 vp->v_mountedhere = (struct mount *)0; 418 vfs->vfs_refcount--; 419 vfs_unbusy(mp); 420 free(mp, M_MOUNT); 421 vput(vp); 422 } 423 return (error); 424 } 425 426 /* 427 * Scan all active processes to see if any of them have a current 428 * or root directory onto which the new filesystem has just been 429 * mounted. If so, replace them with the new mount point. 430 */ 431 void 432 checkdirs(struct vnode *olddp) 433 { 434 struct cwdinfo *cwdi; 435 struct vnode *newdp; 436 struct proc *p; 437 438 if (olddp->v_usecount == 1) 439 return; 440 if (VFS_ROOT(olddp->v_mountedhere, &newdp)) 441 panic("mount: lost mount"); 442 proclist_lock_read(); 443 PROCLIST_FOREACH(p, &allproc) { 444 cwdi = p->p_cwdi; 445 if (!cwdi) 446 continue; 447 if (cwdi->cwdi_cdir == olddp) { 448 vrele(cwdi->cwdi_cdir); 449 VREF(newdp); 450 cwdi->cwdi_cdir = newdp; 451 } 452 if (cwdi->cwdi_rdir == olddp) { 453 vrele(cwdi->cwdi_rdir); 454 VREF(newdp); 455 cwdi->cwdi_rdir = newdp; 456 } 457 } 458 proclist_unlock_read(); 459 if (rootvnode == olddp) { 460 vrele(rootvnode); 461 VREF(newdp); 462 rootvnode = newdp; 463 } 464 vput(newdp); 465 } 466 467 /* 468 * Unmount a file system. 469 * 470 * Note: unmount takes a path to the vnode mounted on as argument, 471 * not special file (as before). 472 */ 473 /* ARGSUSED */ 474 int 475 sys_unmount(struct lwp *l, void *v, register_t *retval) 476 { 477 struct sys_unmount_args /* { 478 syscallarg(const char *) path; 479 syscallarg(int) flags; 480 } */ *uap = v; 481 struct proc *p = l->l_proc; 482 struct vnode *vp; 483 struct mount *mp; 484 int error; 485 struct nameidata nd; 486 487 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 488 SCARG(uap, path), l); 489 if ((error = namei(&nd)) != 0) 490 return (error); 491 vp = nd.ni_vp; 492 mp = vp->v_mount; 493 494 /* 495 * Only root, or the user that did the original mount is 496 * permitted to unmount this filesystem. 497 */ 498 if ((mp->mnt_stat.f_owner != kauth_cred_geteuid(p->p_cred)) && 499 (error = kauth_authorize_generic(p->p_cred, KAUTH_GENERIC_ISSUSER, 500 &p->p_acflag)) != 0) { 501 vput(vp); 502 return (error); 503 } 504 505 /* 506 * Don't allow unmounting the root file system. 507 */ 508 if (mp->mnt_flag & MNT_ROOTFS) { 509 vput(vp); 510 return (EINVAL); 511 } 512 513 /* 514 * Must be the root of the filesystem 515 */ 516 if ((vp->v_flag & VROOT) == 0) { 517 vput(vp); 518 return (EINVAL); 519 } 520 vput(vp); 521 522 /* 523 * XXX Freeze syncer. Must do this before locking the 524 * mount point. See dounmount() for details. 525 */ 526 lockmgr(&syncer_lock, LK_EXCLUSIVE, NULL); 527 528 if (vfs_busy(mp, 0, 0)) { 529 lockmgr(&syncer_lock, LK_RELEASE, NULL); 530 return (EBUSY); 531 } 532 533 return (dounmount(mp, SCARG(uap, flags), l)); 534 } 535 536 /* 537 * Do the actual file system unmount. File system is assumed to have been 538 * marked busy by the caller. 539 */ 540 int 541 dounmount(struct mount *mp, int flags, struct lwp *l) 542 { 543 struct vnode *coveredvp; 544 int error; 545 int async; 546 int used_syncer; 547 548 simple_lock(&mountlist_slock); 549 vfs_unbusy(mp); 550 used_syncer = (mp->mnt_syncer != NULL); 551 552 /* 553 * XXX Syncer must be frozen when we get here. This should really 554 * be done on a per-mountpoint basis, but especially the softdep 555 * code possibly called from the syncer doesn't exactly work on a 556 * per-mountpoint basis, so the softdep code would become a maze 557 * of vfs_busy() calls. 558 * 559 * The caller of dounmount() must acquire syncer_lock because 560 * the syncer itself acquires locks in syncer_lock -> vfs_busy 561 * order, and we must preserve that order to avoid deadlock. 562 * 563 * So, if the file system did not use the syncer, now is 564 * the time to release the syncer_lock. 565 */ 566 if (used_syncer == 0) 567 lockmgr(&syncer_lock, LK_RELEASE, NULL); 568 569 mp->mnt_iflag |= IMNT_UNMOUNT; 570 mp->mnt_unmounter = l; 571 lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK, &mountlist_slock); 572 vn_start_write(NULL, &mp, V_WAIT); 573 574 async = mp->mnt_flag & MNT_ASYNC; 575 mp->mnt_flag &= ~MNT_ASYNC; 576 cache_purgevfs(mp); /* remove cache entries for this file sys */ 577 if (mp->mnt_syncer != NULL) 578 vfs_deallocate_syncvnode(mp); 579 error = 0; 580 if ((mp->mnt_flag & MNT_RDONLY) == 0) { 581 #if NFSS > 0 582 error = fss_umount_hook(mp, (flags & MNT_FORCE)); 583 #endif 584 if (error == 0) 585 error = VFS_SYNC(mp, MNT_WAIT, l->l_proc->p_cred, l); 586 } 587 if (error == 0 || (flags & MNT_FORCE)) 588 error = VFS_UNMOUNT(mp, flags, l); 589 vn_finished_write(mp, 0); 590 simple_lock(&mountlist_slock); 591 if (error) { 592 if ((mp->mnt_flag & (MNT_RDONLY | MNT_ASYNC)) == 0) 593 (void) vfs_allocate_syncvnode(mp); 594 mp->mnt_iflag &= ~IMNT_UNMOUNT; 595 mp->mnt_unmounter = NULL; 596 mp->mnt_flag |= async; 597 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE, 598 &mountlist_slock); 599 if (used_syncer) 600 lockmgr(&syncer_lock, LK_RELEASE, NULL); 601 simple_lock(&mp->mnt_slock); 602 while (mp->mnt_wcnt > 0) { 603 wakeup(mp); 604 ltsleep(&mp->mnt_wcnt, PVFS, "mntwcnt1", 605 0, &mp->mnt_slock); 606 } 607 simple_unlock(&mp->mnt_slock); 608 return (error); 609 } 610 CIRCLEQ_REMOVE(&mountlist, mp, mnt_list); 611 if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) { 612 coveredvp->v_mountedhere = NULL; 613 vrele(coveredvp); 614 } 615 mp->mnt_op->vfs_refcount--; 616 if (LIST_FIRST(&mp->mnt_vnodelist) != NULL) 617 panic("unmount: dangling vnode"); 618 mp->mnt_iflag |= IMNT_GONE; 619 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_slock); 620 if (used_syncer) 621 lockmgr(&syncer_lock, LK_RELEASE, NULL); 622 simple_lock(&mp->mnt_slock); 623 while (mp->mnt_wcnt > 0) { 624 wakeup(mp); 625 ltsleep(&mp->mnt_wcnt, PVFS, "mntwcnt2", 0, &mp->mnt_slock); 626 } 627 simple_unlock(&mp->mnt_slock); 628 vfs_hooks_unmount(mp); 629 free(mp, M_MOUNT); 630 return (0); 631 } 632 633 /* 634 * Sync each mounted filesystem. 635 */ 636 #ifdef DEBUG 637 int syncprt = 0; 638 struct ctldebug debug0 = { "syncprt", &syncprt }; 639 #endif 640 641 /* ARGSUSED */ 642 int 643 sys_sync(struct lwp *l, void *v, register_t *retval) 644 { 645 struct mount *mp, *nmp; 646 int asyncflag; 647 struct proc *p = l == NULL ? &proc0 : l->l_proc; 648 649 simple_lock(&mountlist_slock); 650 for (mp = mountlist.cqh_last; mp != (void *)&mountlist; mp = nmp) { 651 if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock)) { 652 nmp = mp->mnt_list.cqe_prev; 653 continue; 654 } 655 if ((mp->mnt_flag & MNT_RDONLY) == 0 && 656 vn_start_write(NULL, &mp, V_NOWAIT) == 0) { 657 asyncflag = mp->mnt_flag & MNT_ASYNC; 658 mp->mnt_flag &= ~MNT_ASYNC; 659 VFS_SYNC(mp, MNT_NOWAIT, p->p_cred, l); 660 if (asyncflag) 661 mp->mnt_flag |= MNT_ASYNC; 662 vn_finished_write(mp, 0); 663 } 664 simple_lock(&mountlist_slock); 665 nmp = mp->mnt_list.cqe_prev; 666 vfs_unbusy(mp); 667 668 } 669 simple_unlock(&mountlist_slock); 670 #ifdef DEBUG 671 if (syncprt) 672 vfs_bufstats(); 673 #endif /* DEBUG */ 674 return (0); 675 } 676 677 /* 678 * Change filesystem quotas. 679 */ 680 /* ARGSUSED */ 681 int 682 sys_quotactl(struct lwp *l, void *v, register_t *retval) 683 { 684 struct sys_quotactl_args /* { 685 syscallarg(const char *) path; 686 syscallarg(int) cmd; 687 syscallarg(int) uid; 688 syscallarg(caddr_t) arg; 689 } */ *uap = v; 690 struct mount *mp; 691 int error; 692 struct nameidata nd; 693 694 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), l); 695 if ((error = namei(&nd)) != 0) 696 return (error); 697 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | V_PCATCH); 698 vrele(nd.ni_vp); 699 if (error) 700 return (error); 701 error = VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid), 702 SCARG(uap, arg), l); 703 vn_finished_write(mp, 0); 704 return (error); 705 } 706 707 int 708 dostatvfs(struct mount *mp, struct statvfs *sp, struct lwp *l, int flags, 709 int root) 710 { 711 struct cwdinfo *cwdi = l->l_proc->p_cwdi; 712 int error = 0; 713 714 /* 715 * If MNT_NOWAIT or MNT_LAZY is specified, do not 716 * refresh the fsstat cache. MNT_WAIT or MNT_LAZY 717 * overrides MNT_NOWAIT. 718 */ 719 if (flags == MNT_NOWAIT || flags == MNT_LAZY || 720 (flags != MNT_WAIT && flags != 0)) { 721 memcpy(sp, &mp->mnt_stat, sizeof(*sp)); 722 goto done; 723 } 724 725 /* Get the filesystem stats now */ 726 memset(sp, 0, sizeof(*sp)); 727 if ((error = VFS_STATVFS(mp, sp, l)) != 0) { 728 return error; 729 } 730 731 if (cwdi->cwdi_rdir == NULL) 732 (void)memcpy(&mp->mnt_stat, sp, sizeof(mp->mnt_stat)); 733 done: 734 if (cwdi->cwdi_rdir != NULL) { 735 size_t len; 736 char *bp; 737 char *path = PNBUF_GET(); 738 if (!path) 739 return ENOMEM; 740 741 bp = path + MAXPATHLEN; 742 *--bp = '\0'; 743 error = getcwd_common(cwdi->cwdi_rdir, rootvnode, &bp, path, 744 MAXPATHLEN / 2, 0, l); 745 if (error) { 746 PNBUF_PUT(path); 747 return error; 748 } 749 len = strlen(bp); 750 /* 751 * for mount points that are below our root, we can see 752 * them, so we fix up the pathname and return them. The 753 * rest we cannot see, so we don't allow viewing the 754 * data. 755 */ 756 if (strncmp(bp, sp->f_mntonname, len) == 0) { 757 strlcpy(sp->f_mntonname, &sp->f_mntonname[len], 758 sizeof(sp->f_mntonname)); 759 if (sp->f_mntonname[0] == '\0') 760 (void)strlcpy(sp->f_mntonname, "/", 761 sizeof(sp->f_mntonname)); 762 } else { 763 if (root) 764 (void)strlcpy(sp->f_mntonname, "/", 765 sizeof(sp->f_mntonname)); 766 else 767 error = EPERM; 768 } 769 PNBUF_PUT(path); 770 } 771 sp->f_flag = mp->mnt_flag & MNT_VISFLAGMASK; 772 return error; 773 } 774 775 /* 776 * Get filesystem statistics. 777 */ 778 /* ARGSUSED */ 779 int 780 sys_statvfs1(struct lwp *l, void *v, register_t *retval) 781 { 782 struct sys_statvfs1_args /* { 783 syscallarg(const char *) path; 784 syscallarg(struct statvfs *) buf; 785 syscallarg(int) flags; 786 } */ *uap = v; 787 struct mount *mp; 788 struct statvfs *sb; 789 int error; 790 struct nameidata nd; 791 792 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), l); 793 if ((error = namei(&nd)) != 0) 794 return error; 795 mp = nd.ni_vp->v_mount; 796 vrele(nd.ni_vp); 797 sb = STATVFSBUF_GET(); 798 error = dostatvfs(mp, sb, l, SCARG(uap, flags), 1); 799 if (error == 0) { 800 error = copyout(sb, SCARG(uap, buf), sizeof(*sb)); 801 } 802 STATVFSBUF_PUT(sb); 803 return error; 804 } 805 806 /* 807 * Get filesystem statistics. 808 */ 809 /* ARGSUSED */ 810 int 811 sys_fstatvfs1(struct lwp *l, void *v, register_t *retval) 812 { 813 struct sys_fstatvfs1_args /* { 814 syscallarg(int) fd; 815 syscallarg(struct statvfs *) buf; 816 syscallarg(int) flags; 817 } */ *uap = v; 818 struct proc *p = l->l_proc; 819 struct file *fp; 820 struct mount *mp; 821 struct statvfs *sb; 822 int error; 823 824 /* getvnode() will use the descriptor for us */ 825 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 826 return (error); 827 mp = ((struct vnode *)fp->f_data)->v_mount; 828 sb = STATVFSBUF_GET(); 829 if ((error = dostatvfs(mp, sb, l, SCARG(uap, flags), 1)) != 0) 830 goto out; 831 error = copyout(sb, SCARG(uap, buf), sizeof(*sb)); 832 out: 833 FILE_UNUSE(fp, l); 834 STATVFSBUF_PUT(sb); 835 return error; 836 } 837 838 839 /* 840 * Get statistics on all filesystems. 841 */ 842 int 843 sys_getvfsstat(struct lwp *l, void *v, register_t *retval) 844 { 845 struct sys_getvfsstat_args /* { 846 syscallarg(struct statvfs *) buf; 847 syscallarg(size_t) bufsize; 848 syscallarg(int) flags; 849 } */ *uap = v; 850 int root = 0; 851 struct proc *p = l->l_proc; 852 struct mount *mp, *nmp; 853 struct statvfs *sb; 854 struct statvfs *sfsp; 855 size_t count, maxcount; 856 int error = 0; 857 858 sb = STATVFSBUF_GET(); 859 maxcount = SCARG(uap, bufsize) / sizeof(struct statvfs); 860 sfsp = SCARG(uap, buf); 861 simple_lock(&mountlist_slock); 862 count = 0; 863 for (mp = CIRCLEQ_FIRST(&mountlist); mp != (void *)&mountlist; 864 mp = nmp) { 865 if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock)) { 866 nmp = CIRCLEQ_NEXT(mp, mnt_list); 867 continue; 868 } 869 if (sfsp && count < maxcount) { 870 error = dostatvfs(mp, sb, l, SCARG(uap, flags), 0); 871 if (error) { 872 simple_lock(&mountlist_slock); 873 nmp = CIRCLEQ_NEXT(mp, mnt_list); 874 vfs_unbusy(mp); 875 continue; 876 } 877 error = copyout(sb, sfsp, sizeof(*sfsp)); 878 if (error) { 879 vfs_unbusy(mp); 880 goto out; 881 } 882 sfsp++; 883 root |= strcmp(sb->f_mntonname, "/") == 0; 884 } 885 count++; 886 simple_lock(&mountlist_slock); 887 nmp = CIRCLEQ_NEXT(mp, mnt_list); 888 vfs_unbusy(mp); 889 } 890 simple_unlock(&mountlist_slock); 891 if (root == 0 && p->p_cwdi->cwdi_rdir) { 892 /* 893 * fake a root entry 894 */ 895 if ((error = dostatvfs(p->p_cwdi->cwdi_rdir->v_mount, sb, l, 896 SCARG(uap, flags), 1)) != 0) 897 goto out; 898 if (sfsp) 899 error = copyout(sb, sfsp, sizeof(*sfsp)); 900 count++; 901 } 902 if (sfsp && count > maxcount) 903 *retval = maxcount; 904 else 905 *retval = count; 906 out: 907 STATVFSBUF_PUT(sb); 908 return error; 909 } 910 911 /* 912 * Change current working directory to a given file descriptor. 913 */ 914 /* ARGSUSED */ 915 int 916 sys_fchdir(struct lwp *l, void *v, register_t *retval) 917 { 918 struct sys_fchdir_args /* { 919 syscallarg(int) fd; 920 } */ *uap = v; 921 struct proc *p = l->l_proc; 922 struct filedesc *fdp = p->p_fd; 923 struct cwdinfo *cwdi = p->p_cwdi; 924 struct vnode *vp, *tdp; 925 struct mount *mp; 926 struct file *fp; 927 int error; 928 929 /* getvnode() will use the descriptor for us */ 930 if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0) 931 return (error); 932 vp = (struct vnode *)fp->f_data; 933 934 VREF(vp); 935 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 936 if (vp->v_type != VDIR) 937 error = ENOTDIR; 938 else 939 error = VOP_ACCESS(vp, VEXEC, p->p_cred, l); 940 while (!error && (mp = vp->v_mountedhere) != NULL) { 941 if (vfs_busy(mp, 0, 0)) 942 continue; 943 error = VFS_ROOT(mp, &tdp); 944 vfs_unbusy(mp); 945 if (error) 946 break; 947 vput(vp); 948 vp = tdp; 949 } 950 if (error) { 951 vput(vp); 952 goto out; 953 } 954 VOP_UNLOCK(vp, 0); 955 956 /* 957 * Disallow changing to a directory not under the process's 958 * current root directory (if there is one). 959 */ 960 if (cwdi->cwdi_rdir && !vn_isunder(vp, NULL, l)) { 961 vrele(vp); 962 error = EPERM; /* operation not permitted */ 963 goto out; 964 } 965 966 vrele(cwdi->cwdi_cdir); 967 cwdi->cwdi_cdir = vp; 968 out: 969 FILE_UNUSE(fp, l); 970 return (error); 971 } 972 973 /* 974 * Change this process's notion of the root directory to a given file 975 * descriptor. 976 */ 977 int 978 sys_fchroot(struct lwp *l, void *v, register_t *retval) 979 { 980 struct sys_fchroot_args *uap = v; 981 struct proc *p = l->l_proc; 982 struct filedesc *fdp = p->p_fd; 983 struct cwdinfo *cwdi = p->p_cwdi; 984 struct vnode *vp; 985 struct file *fp; 986 int error; 987 988 if ((error = kauth_authorize_generic(p->p_cred, KAUTH_GENERIC_ISSUSER, 989 &p->p_acflag)) != 0) 990 return error; 991 /* getvnode() will use the descriptor for us */ 992 if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0) 993 return error; 994 vp = (struct vnode *) fp->f_data; 995 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 996 if (vp->v_type != VDIR) 997 error = ENOTDIR; 998 else 999 error = VOP_ACCESS(vp, VEXEC, p->p_cred, l); 1000 VOP_UNLOCK(vp, 0); 1001 if (error) 1002 goto out; 1003 VREF(vp); 1004 1005 /* 1006 * Prevent escaping from chroot by putting the root under 1007 * the working directory. Silently chdir to / if we aren't 1008 * already there. 1009 */ 1010 if (!vn_isunder(cwdi->cwdi_cdir, vp, l)) { 1011 /* 1012 * XXX would be more failsafe to change directory to a 1013 * deadfs node here instead 1014 */ 1015 vrele(cwdi->cwdi_cdir); 1016 VREF(vp); 1017 cwdi->cwdi_cdir = vp; 1018 } 1019 1020 if (cwdi->cwdi_rdir != NULL) 1021 vrele(cwdi->cwdi_rdir); 1022 cwdi->cwdi_rdir = vp; 1023 out: 1024 FILE_UNUSE(fp, l); 1025 return (error); 1026 } 1027 1028 /* 1029 * Change current working directory (``.''). 1030 */ 1031 /* ARGSUSED */ 1032 int 1033 sys_chdir(struct lwp *l, void *v, register_t *retval) 1034 { 1035 struct sys_chdir_args /* { 1036 syscallarg(const char *) path; 1037 } */ *uap = v; 1038 struct proc *p = l->l_proc; 1039 struct cwdinfo *cwdi = p->p_cwdi; 1040 int error; 1041 struct nameidata nd; 1042 1043 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1044 SCARG(uap, path), l); 1045 if ((error = change_dir(&nd, l)) != 0) 1046 return (error); 1047 vrele(cwdi->cwdi_cdir); 1048 cwdi->cwdi_cdir = nd.ni_vp; 1049 return (0); 1050 } 1051 1052 /* 1053 * Change notion of root (``/'') directory. 1054 */ 1055 /* ARGSUSED */ 1056 int 1057 sys_chroot(struct lwp *l, void *v, register_t *retval) 1058 { 1059 struct sys_chroot_args /* { 1060 syscallarg(const char *) path; 1061 } */ *uap = v; 1062 struct proc *p = l->l_proc; 1063 struct cwdinfo *cwdi = p->p_cwdi; 1064 struct vnode *vp; 1065 int error; 1066 struct nameidata nd; 1067 1068 if ((error = kauth_authorize_generic(p->p_cred, KAUTH_GENERIC_ISSUSER, 1069 &p->p_acflag)) != 0) 1070 return (error); 1071 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1072 SCARG(uap, path), l); 1073 if ((error = change_dir(&nd, l)) != 0) 1074 return (error); 1075 if (cwdi->cwdi_rdir != NULL) 1076 vrele(cwdi->cwdi_rdir); 1077 vp = nd.ni_vp; 1078 cwdi->cwdi_rdir = vp; 1079 1080 /* 1081 * Prevent escaping from chroot by putting the root under 1082 * the working directory. Silently chdir to / if we aren't 1083 * already there. 1084 */ 1085 if (!vn_isunder(cwdi->cwdi_cdir, vp, l)) { 1086 /* 1087 * XXX would be more failsafe to change directory to a 1088 * deadfs node here instead 1089 */ 1090 vrele(cwdi->cwdi_cdir); 1091 VREF(vp); 1092 cwdi->cwdi_cdir = vp; 1093 } 1094 1095 return (0); 1096 } 1097 1098 /* 1099 * Common routine for chroot and chdir. 1100 */ 1101 static int 1102 change_dir(struct nameidata *ndp, struct lwp *l) 1103 { 1104 struct vnode *vp; 1105 int error; 1106 1107 if ((error = namei(ndp)) != 0) 1108 return (error); 1109 vp = ndp->ni_vp; 1110 if (vp->v_type != VDIR) 1111 error = ENOTDIR; 1112 else 1113 error = VOP_ACCESS(vp, VEXEC, l->l_proc->p_cred, l); 1114 1115 if (error) 1116 vput(vp); 1117 else 1118 VOP_UNLOCK(vp, 0); 1119 return (error); 1120 } 1121 1122 /* 1123 * Check permissions, allocate an open file structure, 1124 * and call the device open routine if any. 1125 */ 1126 int 1127 sys_open(struct lwp *l, void *v, register_t *retval) 1128 { 1129 struct sys_open_args /* { 1130 syscallarg(const char *) path; 1131 syscallarg(int) flags; 1132 syscallarg(int) mode; 1133 } */ *uap = v; 1134 struct proc *p = l->l_proc; 1135 struct cwdinfo *cwdi = p->p_cwdi; 1136 struct filedesc *fdp = p->p_fd; 1137 struct file *fp; 1138 struct vnode *vp; 1139 int flags, cmode; 1140 int type, indx, error; 1141 struct flock lf; 1142 struct nameidata nd; 1143 1144 flags = FFLAGS(SCARG(uap, flags)); 1145 if ((flags & (FREAD | FWRITE)) == 0) 1146 return (EINVAL); 1147 /* falloc() will use the file descriptor for us */ 1148 if ((error = falloc(p, &fp, &indx)) != 0) 1149 return (error); 1150 cmode = ((SCARG(uap, mode) &~ cwdi->cwdi_cmask) & ALLPERMS) &~ S_ISTXT; 1151 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), l); 1152 l->l_dupfd = -indx - 1; /* XXX check for fdopen */ 1153 if ((error = vn_open(&nd, flags, cmode)) != 0) { 1154 FILE_UNUSE(fp, l); 1155 fdp->fd_ofiles[indx] = NULL; 1156 ffree(fp); 1157 if ((error == EDUPFD || error == EMOVEFD) && 1158 l->l_dupfd >= 0 && /* XXX from fdopen */ 1159 (error = 1160 dupfdopen(l, indx, l->l_dupfd, flags, error)) == 0) { 1161 *retval = indx; 1162 return (0); 1163 } 1164 if (error == ERESTART) 1165 error = EINTR; 1166 fdremove(fdp, indx); 1167 return (error); 1168 } 1169 l->l_dupfd = 0; 1170 vp = nd.ni_vp; 1171 fp->f_flag = flags & FMASK; 1172 fp->f_type = DTYPE_VNODE; 1173 fp->f_ops = &vnops; 1174 fp->f_data = vp; 1175 if (flags & (O_EXLOCK | O_SHLOCK)) { 1176 lf.l_whence = SEEK_SET; 1177 lf.l_start = 0; 1178 lf.l_len = 0; 1179 if (flags & O_EXLOCK) 1180 lf.l_type = F_WRLCK; 1181 else 1182 lf.l_type = F_RDLCK; 1183 type = F_FLOCK; 1184 if ((flags & FNONBLOCK) == 0) 1185 type |= F_WAIT; 1186 VOP_UNLOCK(vp, 0); 1187 error = VOP_ADVLOCK(vp, fp, F_SETLK, &lf, type); 1188 if (error) { 1189 (void) vn_close(vp, fp->f_flag, fp->f_cred, l); 1190 FILE_UNUSE(fp, l); 1191 ffree(fp); 1192 fdremove(fdp, indx); 1193 return (error); 1194 } 1195 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 1196 fp->f_flag |= FHASLOCK; 1197 } 1198 VOP_UNLOCK(vp, 0); 1199 *retval = indx; 1200 FILE_SET_MATURE(fp); 1201 FILE_UNUSE(fp, l); 1202 return (0); 1203 } 1204 1205 /* 1206 * vfs_composefh: compose a filehandle. 1207 */ 1208 1209 int 1210 vfs_composefh(struct vnode *vp, fhandle_t *fhp) 1211 { 1212 struct mount *mp; 1213 int error; 1214 1215 mp = vp->v_mount; 1216 if (mp->mnt_op->vfs_vptofh == NULL) { 1217 return EOPNOTSUPP; 1218 } 1219 memset(fhp, 0, sizeof(*fhp)); 1220 fhp->fh_fsid = mp->mnt_stat.f_fsidx; 1221 error = VFS_VPTOFH(vp, &fhp->fh_fid); 1222 KASSERT(fhp->fh_fid.fid_len <= _VFS_MAXFIDSZ); 1223 return error; 1224 } 1225 1226 /* 1227 * Get file handle system call 1228 */ 1229 int 1230 sys_getfh(struct lwp *l, void *v, register_t *retval) 1231 { 1232 struct sys_getfh_args /* { 1233 syscallarg(char *) fname; 1234 syscallarg(fhandle_t *) fhp; 1235 } */ *uap = v; 1236 struct proc *p = l->l_proc; 1237 struct vnode *vp; 1238 fhandle_t fh; 1239 int error; 1240 struct nameidata nd; 1241 1242 /* 1243 * Must be super user 1244 */ 1245 error = kauth_authorize_generic(p->p_cred, KAUTH_GENERIC_ISSUSER, 1246 &p->p_acflag); 1247 if (error) 1248 return (error); 1249 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1250 SCARG(uap, fname), l); 1251 error = namei(&nd); 1252 if (error) 1253 return (error); 1254 vp = nd.ni_vp; 1255 error = vfs_composefh(vp, &fh); 1256 vput(vp); 1257 if (error) 1258 return (error); 1259 error = copyout(&fh, (caddr_t)SCARG(uap, fhp), sizeof (fh)); 1260 return (error); 1261 } 1262 1263 /* 1264 * Open a file given a file handle. 1265 * 1266 * Check permissions, allocate an open file structure, 1267 * and call the device open routine if any. 1268 */ 1269 int 1270 sys_fhopen(struct lwp *l, void *v, register_t *retval) 1271 { 1272 struct sys_fhopen_args /* { 1273 syscallarg(const fhandle_t *) fhp; 1274 syscallarg(int) flags; 1275 } */ *uap = v; 1276 struct proc *p = l->l_proc; 1277 struct filedesc *fdp = p->p_fd; 1278 struct file *fp; 1279 struct vnode *vp = NULL; 1280 struct mount *mp; 1281 kauth_cred_t cred = p->p_cred; 1282 int flags; 1283 struct file *nfp; 1284 int type, indx, error=0; 1285 struct flock lf; 1286 struct vattr va; 1287 fhandle_t fh; 1288 1289 /* 1290 * Must be super user 1291 */ 1292 if ((error = kauth_authorize_generic(p->p_cred, KAUTH_GENERIC_ISSUSER, 1293 &p->p_acflag))) 1294 return (error); 1295 1296 flags = FFLAGS(SCARG(uap, flags)); 1297 if ((flags & (FREAD | FWRITE)) == 0) 1298 return (EINVAL); 1299 if ((flags & O_CREAT)) 1300 return (EINVAL); 1301 /* falloc() will use the file descriptor for us */ 1302 if ((error = falloc(p, &nfp, &indx)) != 0) 1303 return (error); 1304 fp = nfp; 1305 if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0) 1306 goto bad; 1307 1308 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) { 1309 error = ESTALE; 1310 goto bad; 1311 } 1312 1313 if (mp->mnt_op->vfs_fhtovp == NULL) { 1314 error = EOPNOTSUPP; 1315 goto bad; 1316 } 1317 1318 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)) != 0) { 1319 vp = NULL; /* most likely unnecessary sanity for bad: */ 1320 goto bad; 1321 } 1322 1323 /* Now do an effective vn_open */ 1324 1325 if (vp->v_type == VSOCK) { 1326 error = EOPNOTSUPP; 1327 goto bad; 1328 } 1329 if (flags & FREAD) { 1330 if ((error = VOP_ACCESS(vp, VREAD, cred, l)) != 0) 1331 goto bad; 1332 } 1333 if (flags & (FWRITE | O_TRUNC)) { 1334 if (vp->v_type == VDIR) { 1335 error = EISDIR; 1336 goto bad; 1337 } 1338 if ((error = vn_writechk(vp)) != 0 || 1339 (error = VOP_ACCESS(vp, VWRITE, cred, l)) != 0) 1340 goto bad; 1341 } 1342 if (flags & O_TRUNC) { 1343 if ((error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) != 0) 1344 goto bad; 1345 VOP_UNLOCK(vp, 0); /* XXX */ 1346 VOP_LEASE(vp, l, cred, LEASE_WRITE); 1347 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); /* XXX */ 1348 VATTR_NULL(&va); 1349 va.va_size = 0; 1350 error = VOP_SETATTR(vp, &va, cred, l); 1351 vn_finished_write(mp, 0); 1352 if (error) 1353 goto bad; 1354 } 1355 if ((error = VOP_OPEN(vp, flags, cred, l)) != 0) 1356 goto bad; 1357 if (vp->v_type == VREG && 1358 uvn_attach(vp, flags & FWRITE ? VM_PROT_WRITE : 0) == NULL) { 1359 error = EIO; 1360 goto bad; 1361 } 1362 if (flags & FWRITE) 1363 vp->v_writecount++; 1364 1365 /* done with modified vn_open, now finish what sys_open does. */ 1366 1367 fp->f_flag = flags & FMASK; 1368 fp->f_type = DTYPE_VNODE; 1369 fp->f_ops = &vnops; 1370 fp->f_data = vp; 1371 if (flags & (O_EXLOCK | O_SHLOCK)) { 1372 lf.l_whence = SEEK_SET; 1373 lf.l_start = 0; 1374 lf.l_len = 0; 1375 if (flags & O_EXLOCK) 1376 lf.l_type = F_WRLCK; 1377 else 1378 lf.l_type = F_RDLCK; 1379 type = F_FLOCK; 1380 if ((flags & FNONBLOCK) == 0) 1381 type |= F_WAIT; 1382 VOP_UNLOCK(vp, 0); 1383 error = VOP_ADVLOCK(vp, fp, F_SETLK, &lf, type); 1384 if (error) { 1385 (void) vn_close(vp, fp->f_flag, fp->f_cred, l); 1386 FILE_UNUSE(fp, l); 1387 ffree(fp); 1388 fdremove(fdp, indx); 1389 return (error); 1390 } 1391 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 1392 fp->f_flag |= FHASLOCK; 1393 } 1394 VOP_UNLOCK(vp, 0); 1395 *retval = indx; 1396 FILE_SET_MATURE(fp); 1397 FILE_UNUSE(fp, l); 1398 return (0); 1399 1400 bad: 1401 FILE_UNUSE(fp, l); 1402 ffree(fp); 1403 fdremove(fdp, indx); 1404 if (vp != NULL) 1405 vput(vp); 1406 return (error); 1407 } 1408 1409 /* ARGSUSED */ 1410 int 1411 sys___fhstat30(struct lwp *l, void *v, register_t *retval) 1412 { 1413 struct sys___fhstat30_args /* { 1414 syscallarg(const fhandle_t *) fhp; 1415 syscallarg(struct stat *) sb; 1416 } */ *uap = v; 1417 struct proc *p = l->l_proc; 1418 struct stat sb; 1419 int error; 1420 fhandle_t fh; 1421 struct mount *mp; 1422 struct vnode *vp; 1423 1424 /* 1425 * Must be super user 1426 */ 1427 if ((error = kauth_authorize_generic(p->p_cred, KAUTH_GENERIC_ISSUSER, 1428 &p->p_acflag))) 1429 return (error); 1430 1431 if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0) 1432 return (error); 1433 1434 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) 1435 return (ESTALE); 1436 if (mp->mnt_op->vfs_fhtovp == NULL) 1437 return EOPNOTSUPP; 1438 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp))) 1439 return (error); 1440 error = vn_stat(vp, &sb, l); 1441 vput(vp); 1442 if (error) 1443 return (error); 1444 error = copyout(&sb, SCARG(uap, sb), sizeof(sb)); 1445 return (error); 1446 } 1447 1448 /* ARGSUSED */ 1449 int 1450 sys_fhstatvfs1(struct lwp *l, void *v, register_t *retval) 1451 { 1452 struct sys_fhstatvfs1_args /* { 1453 syscallarg(const fhandle_t *) fhp; 1454 syscallarg(struct statvfs *) buf; 1455 syscallarg(int) flags; 1456 } */ *uap = v; 1457 struct proc *p = l->l_proc; 1458 struct statvfs *sb; 1459 fhandle_t fh; 1460 struct mount *mp; 1461 struct vnode *vp; 1462 int error; 1463 1464 /* 1465 * Must be super user 1466 */ 1467 if ((error = kauth_authorize_generic(p->p_cred, KAUTH_GENERIC_ISSUSER, 1468 &p->p_acflag)) != 0) 1469 return error; 1470 1471 if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0) 1472 return error; 1473 1474 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) 1475 return ESTALE; 1476 if (mp->mnt_op->vfs_fhtovp == NULL) 1477 return EOPNOTSUPP; 1478 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp))) 1479 return error; 1480 1481 mp = vp->v_mount; 1482 sb = STATVFSBUF_GET(); 1483 if ((error = dostatvfs(mp, sb, l, SCARG(uap, flags), 1)) != 0) { 1484 vput(vp); 1485 goto out; 1486 } 1487 vput(vp); 1488 error = copyout(sb, SCARG(uap, buf), sizeof(*sb)); 1489 out: 1490 STATVFSBUF_PUT(sb); 1491 return error; 1492 } 1493 1494 /* 1495 * Create a special file. 1496 */ 1497 /* ARGSUSED */ 1498 int 1499 sys_mknod(struct lwp *l, void *v, register_t *retval) 1500 { 1501 struct sys_mknod_args /* { 1502 syscallarg(const char *) path; 1503 syscallarg(int) mode; 1504 syscallarg(int) dev; 1505 } */ *uap = v; 1506 struct proc *p = l->l_proc; 1507 struct vnode *vp; 1508 struct mount *mp; 1509 struct vattr vattr; 1510 int error; 1511 int whiteout = 0; 1512 struct nameidata nd; 1513 1514 if ((error = kauth_authorize_generic(p->p_cred, KAUTH_GENERIC_ISSUSER, 1515 &p->p_acflag)) != 0) 1516 return (error); 1517 restart: 1518 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), l); 1519 if ((error = namei(&nd)) != 0) 1520 return (error); 1521 vp = nd.ni_vp; 1522 if (vp != NULL) 1523 error = EEXIST; 1524 else { 1525 VATTR_NULL(&vattr); 1526 vattr.va_mode = 1527 (SCARG(uap, mode) & ALLPERMS) &~ p->p_cwdi->cwdi_cmask; 1528 vattr.va_rdev = SCARG(uap, dev); 1529 whiteout = 0; 1530 1531 switch (SCARG(uap, mode) & S_IFMT) { 1532 case S_IFMT: /* used by badsect to flag bad sectors */ 1533 vattr.va_type = VBAD; 1534 break; 1535 case S_IFCHR: 1536 vattr.va_type = VCHR; 1537 break; 1538 case S_IFBLK: 1539 vattr.va_type = VBLK; 1540 break; 1541 case S_IFWHT: 1542 whiteout = 1; 1543 break; 1544 default: 1545 error = EINVAL; 1546 break; 1547 } 1548 } 1549 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1550 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1551 if (nd.ni_dvp == vp) 1552 vrele(nd.ni_dvp); 1553 else 1554 vput(nd.ni_dvp); 1555 if (vp) 1556 vrele(vp); 1557 if ((error = vn_start_write(NULL, &mp, 1558 V_WAIT | V_SLEEPONLY | V_PCATCH)) != 0) 1559 return (error); 1560 goto restart; 1561 } 1562 if (!error) { 1563 VOP_LEASE(nd.ni_dvp, l, p->p_cred, LEASE_WRITE); 1564 if (whiteout) { 1565 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE); 1566 if (error) 1567 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1568 vput(nd.ni_dvp); 1569 } else { 1570 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, 1571 &nd.ni_cnd, &vattr); 1572 if (error == 0) 1573 vput(nd.ni_vp); 1574 } 1575 } else { 1576 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1577 if (nd.ni_dvp == vp) 1578 vrele(nd.ni_dvp); 1579 else 1580 vput(nd.ni_dvp); 1581 if (vp) 1582 vrele(vp); 1583 } 1584 vn_finished_write(mp, 0); 1585 return (error); 1586 } 1587 1588 /* 1589 * Create a named pipe. 1590 */ 1591 /* ARGSUSED */ 1592 int 1593 sys_mkfifo(struct lwp *l, void *v, register_t *retval) 1594 { 1595 struct sys_mkfifo_args /* { 1596 syscallarg(const char *) path; 1597 syscallarg(int) mode; 1598 } */ *uap = v; 1599 struct proc *p = l->l_proc; 1600 struct mount *mp; 1601 struct vattr vattr; 1602 int error; 1603 struct nameidata nd; 1604 1605 restart: 1606 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), l); 1607 if ((error = namei(&nd)) != 0) 1608 return (error); 1609 if (nd.ni_vp != NULL) { 1610 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1611 if (nd.ni_dvp == nd.ni_vp) 1612 vrele(nd.ni_dvp); 1613 else 1614 vput(nd.ni_dvp); 1615 vrele(nd.ni_vp); 1616 return (EEXIST); 1617 } 1618 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1619 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1620 if (nd.ni_dvp == nd.ni_vp) 1621 vrele(nd.ni_dvp); 1622 else 1623 vput(nd.ni_dvp); 1624 if (nd.ni_vp) 1625 vrele(nd.ni_vp); 1626 if ((error = vn_start_write(NULL, &mp, 1627 V_WAIT | V_SLEEPONLY | V_PCATCH)) != 0) 1628 return (error); 1629 goto restart; 1630 } 1631 VATTR_NULL(&vattr); 1632 vattr.va_type = VFIFO; 1633 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_cwdi->cwdi_cmask; 1634 VOP_LEASE(nd.ni_dvp, l, p->p_cred, LEASE_WRITE); 1635 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 1636 if (error == 0) 1637 vput(nd.ni_vp); 1638 vn_finished_write(mp, 0); 1639 return (error); 1640 } 1641 1642 /* 1643 * Make a hard file link. 1644 */ 1645 /* ARGSUSED */ 1646 int 1647 sys_link(struct lwp *l, void *v, register_t *retval) 1648 { 1649 struct sys_link_args /* { 1650 syscallarg(const char *) path; 1651 syscallarg(const char *) link; 1652 } */ *uap = v; 1653 struct proc *p = l->l_proc; 1654 struct vnode *vp; 1655 struct mount *mp; 1656 struct nameidata nd; 1657 int error; 1658 1659 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), l); 1660 if ((error = namei(&nd)) != 0) 1661 return (error); 1662 vp = nd.ni_vp; 1663 if ((error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) != 0) { 1664 vrele(vp); 1665 return (error); 1666 } 1667 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), l); 1668 if ((error = namei(&nd)) != 0) 1669 goto out; 1670 if (nd.ni_vp) { 1671 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1672 if (nd.ni_dvp == nd.ni_vp) 1673 vrele(nd.ni_dvp); 1674 else 1675 vput(nd.ni_dvp); 1676 vrele(nd.ni_vp); 1677 error = EEXIST; 1678 goto out; 1679 } 1680 VOP_LEASE(nd.ni_dvp, l, p->p_cred, LEASE_WRITE); 1681 VOP_LEASE(vp, l, p->p_cred, LEASE_WRITE); 1682 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); 1683 out: 1684 vrele(vp); 1685 vn_finished_write(mp, 0); 1686 return (error); 1687 } 1688 1689 /* 1690 * Make a symbolic link. 1691 */ 1692 /* ARGSUSED */ 1693 int 1694 sys_symlink(struct lwp *l, void *v, register_t *retval) 1695 { 1696 struct sys_symlink_args /* { 1697 syscallarg(const char *) path; 1698 syscallarg(const char *) link; 1699 } */ *uap = v; 1700 struct proc *p = l->l_proc; 1701 struct mount *mp; 1702 struct vattr vattr; 1703 char *path; 1704 int error; 1705 struct nameidata nd; 1706 1707 path = PNBUF_GET(); 1708 error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL); 1709 if (error) 1710 goto out; 1711 restart: 1712 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), l); 1713 if ((error = namei(&nd)) != 0) 1714 goto out; 1715 if (nd.ni_vp) { 1716 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1717 if (nd.ni_dvp == nd.ni_vp) 1718 vrele(nd.ni_dvp); 1719 else 1720 vput(nd.ni_dvp); 1721 vrele(nd.ni_vp); 1722 error = EEXIST; 1723 goto out; 1724 } 1725 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1726 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1727 if (nd.ni_dvp == nd.ni_vp) 1728 vrele(nd.ni_dvp); 1729 else 1730 vput(nd.ni_dvp); 1731 if ((error = vn_start_write(NULL, &mp, 1732 V_WAIT | V_SLEEPONLY | V_PCATCH)) != 0) 1733 return (error); 1734 goto restart; 1735 } 1736 VATTR_NULL(&vattr); 1737 vattr.va_type = VLNK; 1738 vattr.va_mode = ACCESSPERMS &~ p->p_cwdi->cwdi_cmask; 1739 VOP_LEASE(nd.ni_dvp, l, p->p_cred, LEASE_WRITE); 1740 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path); 1741 if (error == 0) 1742 vput(nd.ni_vp); 1743 vn_finished_write(mp, 0); 1744 out: 1745 PNBUF_PUT(path); 1746 return (error); 1747 } 1748 1749 /* 1750 * Delete a whiteout from the filesystem. 1751 */ 1752 /* ARGSUSED */ 1753 int 1754 sys_undelete(struct lwp *l, void *v, register_t *retval) 1755 { 1756 struct sys_undelete_args /* { 1757 syscallarg(const char *) path; 1758 } */ *uap = v; 1759 struct proc *p = l->l_proc; 1760 int error; 1761 struct mount *mp; 1762 struct nameidata nd; 1763 1764 restart: 1765 NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE, 1766 SCARG(uap, path), l); 1767 error = namei(&nd); 1768 if (error) 1769 return (error); 1770 1771 if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) { 1772 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1773 if (nd.ni_dvp == nd.ni_vp) 1774 vrele(nd.ni_dvp); 1775 else 1776 vput(nd.ni_dvp); 1777 if (nd.ni_vp) 1778 vrele(nd.ni_vp); 1779 return (EEXIST); 1780 } 1781 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1782 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1783 if (nd.ni_dvp == nd.ni_vp) 1784 vrele(nd.ni_dvp); 1785 else 1786 vput(nd.ni_dvp); 1787 if ((error = vn_start_write(NULL, &mp, 1788 V_WAIT | V_SLEEPONLY | V_PCATCH)) != 0) 1789 return (error); 1790 goto restart; 1791 } 1792 VOP_LEASE(nd.ni_dvp, l, p->p_cred, LEASE_WRITE); 1793 if ((error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE)) != 0) 1794 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1795 vput(nd.ni_dvp); 1796 vn_finished_write(mp, 0); 1797 return (error); 1798 } 1799 1800 /* 1801 * Delete a name from the filesystem. 1802 */ 1803 /* ARGSUSED */ 1804 int 1805 sys_unlink(struct lwp *l, void *v, register_t *retval) 1806 { 1807 struct sys_unlink_args /* { 1808 syscallarg(const char *) path; 1809 } */ *uap = v; 1810 struct proc *p = l->l_proc; 1811 struct mount *mp; 1812 struct vnode *vp; 1813 int error; 1814 struct nameidata nd; 1815 1816 restart: 1817 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, 1818 SCARG(uap, path), l); 1819 if ((error = namei(&nd)) != 0) 1820 return (error); 1821 vp = nd.ni_vp; 1822 1823 /* 1824 * The root of a mounted filesystem cannot be deleted. 1825 */ 1826 if (vp->v_flag & VROOT) { 1827 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1828 if (nd.ni_dvp == vp) 1829 vrele(nd.ni_dvp); 1830 else 1831 vput(nd.ni_dvp); 1832 vput(vp); 1833 error = EBUSY; 1834 goto out; 1835 } 1836 1837 #ifdef VERIFIED_EXEC 1838 /* Handle remove requests for veriexec entries. */ 1839 if ((error = veriexec_removechk(l, vp, nd.ni_dirp)) != 0) { 1840 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1841 if (nd.ni_dvp == vp) 1842 vrele(nd.ni_dvp); 1843 else 1844 vput(nd.ni_dvp); 1845 vput(vp); 1846 goto out; 1847 } 1848 #endif /* VERIFIED_EXEC */ 1849 1850 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1851 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1852 if (nd.ni_dvp == vp) 1853 vrele(nd.ni_dvp); 1854 else 1855 vput(nd.ni_dvp); 1856 vput(vp); 1857 if ((error = vn_start_write(NULL, &mp, 1858 V_WAIT | V_SLEEPONLY | V_PCATCH)) != 0) 1859 return (error); 1860 goto restart; 1861 } 1862 VOP_LEASE(nd.ni_dvp, l, p->p_cred, LEASE_WRITE); 1863 VOP_LEASE(vp, l, p->p_cred, LEASE_WRITE); 1864 error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 1865 vn_finished_write(mp, 0); 1866 out: 1867 return (error); 1868 } 1869 1870 /* 1871 * Reposition read/write file offset. 1872 */ 1873 int 1874 sys_lseek(struct lwp *l, void *v, register_t *retval) 1875 { 1876 struct sys_lseek_args /* { 1877 syscallarg(int) fd; 1878 syscallarg(int) pad; 1879 syscallarg(off_t) offset; 1880 syscallarg(int) whence; 1881 } */ *uap = v; 1882 struct proc *p = l->l_proc; 1883 kauth_cred_t cred = p->p_cred; 1884 struct filedesc *fdp = p->p_fd; 1885 struct file *fp; 1886 struct vnode *vp; 1887 struct vattr vattr; 1888 off_t newoff; 1889 int error; 1890 1891 if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL) 1892 return (EBADF); 1893 1894 FILE_USE(fp); 1895 1896 vp = (struct vnode *)fp->f_data; 1897 if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { 1898 error = ESPIPE; 1899 goto out; 1900 } 1901 1902 switch (SCARG(uap, whence)) { 1903 case SEEK_CUR: 1904 newoff = fp->f_offset + SCARG(uap, offset); 1905 break; 1906 case SEEK_END: 1907 error = VOP_GETATTR(vp, &vattr, cred, l); 1908 if (error) 1909 goto out; 1910 newoff = SCARG(uap, offset) + vattr.va_size; 1911 break; 1912 case SEEK_SET: 1913 newoff = SCARG(uap, offset); 1914 break; 1915 default: 1916 error = EINVAL; 1917 goto out; 1918 } 1919 if ((error = VOP_SEEK(vp, fp->f_offset, newoff, cred)) != 0) 1920 goto out; 1921 1922 *(off_t *)retval = fp->f_offset = newoff; 1923 out: 1924 FILE_UNUSE(fp, l); 1925 return (error); 1926 } 1927 1928 /* 1929 * Positional read system call. 1930 */ 1931 int 1932 sys_pread(struct lwp *l, void *v, register_t *retval) 1933 { 1934 struct sys_pread_args /* { 1935 syscallarg(int) fd; 1936 syscallarg(void *) buf; 1937 syscallarg(size_t) nbyte; 1938 syscallarg(off_t) offset; 1939 } */ *uap = v; 1940 struct proc *p = l->l_proc; 1941 struct filedesc *fdp = p->p_fd; 1942 struct file *fp; 1943 struct vnode *vp; 1944 off_t offset; 1945 int error, fd = SCARG(uap, fd); 1946 1947 if ((fp = fd_getfile(fdp, fd)) == NULL) 1948 return (EBADF); 1949 1950 if ((fp->f_flag & FREAD) == 0) { 1951 simple_unlock(&fp->f_slock); 1952 return (EBADF); 1953 } 1954 1955 FILE_USE(fp); 1956 1957 vp = (struct vnode *)fp->f_data; 1958 if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { 1959 error = ESPIPE; 1960 goto out; 1961 } 1962 1963 offset = SCARG(uap, offset); 1964 1965 /* 1966 * XXX This works because no file systems actually 1967 * XXX take any action on the seek operation. 1968 */ 1969 if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0) 1970 goto out; 1971 1972 /* dofileread() will unuse the descriptor for us */ 1973 return (dofileread(l, fd, fp, SCARG(uap, buf), SCARG(uap, nbyte), 1974 &offset, 0, retval)); 1975 1976 out: 1977 FILE_UNUSE(fp, l); 1978 return (error); 1979 } 1980 1981 /* 1982 * Positional scatter read system call. 1983 */ 1984 int 1985 sys_preadv(struct lwp *l, void *v, register_t *retval) 1986 { 1987 struct sys_preadv_args /* { 1988 syscallarg(int) fd; 1989 syscallarg(const struct iovec *) iovp; 1990 syscallarg(int) iovcnt; 1991 syscallarg(off_t) offset; 1992 } */ *uap = v; 1993 struct proc *p = l->l_proc; 1994 struct filedesc *fdp = p->p_fd; 1995 struct file *fp; 1996 struct vnode *vp; 1997 off_t offset; 1998 int error, fd = SCARG(uap, fd); 1999 2000 if ((fp = fd_getfile(fdp, fd)) == NULL) 2001 return (EBADF); 2002 2003 if ((fp->f_flag & FREAD) == 0) { 2004 simple_unlock(&fp->f_slock); 2005 return (EBADF); 2006 } 2007 2008 FILE_USE(fp); 2009 2010 vp = (struct vnode *)fp->f_data; 2011 if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { 2012 error = ESPIPE; 2013 goto out; 2014 } 2015 2016 offset = SCARG(uap, offset); 2017 2018 /* 2019 * XXX This works because no file systems actually 2020 * XXX take any action on the seek operation. 2021 */ 2022 if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0) 2023 goto out; 2024 2025 /* dofilereadv() will unuse the descriptor for us */ 2026 return (dofilereadv(l, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt), 2027 &offset, 0, retval)); 2028 2029 out: 2030 FILE_UNUSE(fp, l); 2031 return (error); 2032 } 2033 2034 /* 2035 * Positional write system call. 2036 */ 2037 int 2038 sys_pwrite(struct lwp *l, void *v, register_t *retval) 2039 { 2040 struct sys_pwrite_args /* { 2041 syscallarg(int) fd; 2042 syscallarg(const void *) buf; 2043 syscallarg(size_t) nbyte; 2044 syscallarg(off_t) offset; 2045 } */ *uap = v; 2046 struct proc *p = l->l_proc; 2047 struct filedesc *fdp = p->p_fd; 2048 struct file *fp; 2049 struct vnode *vp; 2050 off_t offset; 2051 int error, fd = SCARG(uap, fd); 2052 2053 if ((fp = fd_getfile(fdp, fd)) == NULL) 2054 return (EBADF); 2055 2056 if ((fp->f_flag & FWRITE) == 0) { 2057 simple_unlock(&fp->f_slock); 2058 return (EBADF); 2059 } 2060 2061 FILE_USE(fp); 2062 2063 vp = (struct vnode *)fp->f_data; 2064 if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { 2065 error = ESPIPE; 2066 goto out; 2067 } 2068 2069 offset = SCARG(uap, offset); 2070 2071 /* 2072 * XXX This works because no file systems actually 2073 * XXX take any action on the seek operation. 2074 */ 2075 if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0) 2076 goto out; 2077 2078 /* dofilewrite() will unuse the descriptor for us */ 2079 return (dofilewrite(l, fd, fp, SCARG(uap, buf), SCARG(uap, nbyte), 2080 &offset, 0, retval)); 2081 2082 out: 2083 FILE_UNUSE(fp, l); 2084 return (error); 2085 } 2086 2087 /* 2088 * Positional gather write system call. 2089 */ 2090 int 2091 sys_pwritev(struct lwp *l, void *v, register_t *retval) 2092 { 2093 struct sys_pwritev_args /* { 2094 syscallarg(int) fd; 2095 syscallarg(const struct iovec *) iovp; 2096 syscallarg(int) iovcnt; 2097 syscallarg(off_t) offset; 2098 } */ *uap = v; 2099 struct proc *p = l->l_proc; 2100 struct filedesc *fdp = p->p_fd; 2101 struct file *fp; 2102 struct vnode *vp; 2103 off_t offset; 2104 int error, fd = SCARG(uap, fd); 2105 2106 if ((fp = fd_getfile(fdp, fd)) == NULL) 2107 return (EBADF); 2108 2109 if ((fp->f_flag & FWRITE) == 0) { 2110 simple_unlock(&fp->f_slock); 2111 return (EBADF); 2112 } 2113 2114 FILE_USE(fp); 2115 2116 vp = (struct vnode *)fp->f_data; 2117 if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { 2118 error = ESPIPE; 2119 goto out; 2120 } 2121 2122 offset = SCARG(uap, offset); 2123 2124 /* 2125 * XXX This works because no file systems actually 2126 * XXX take any action on the seek operation. 2127 */ 2128 if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0) 2129 goto out; 2130 2131 /* dofilewritev() will unuse the descriptor for us */ 2132 return (dofilewritev(l, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt), 2133 &offset, 0, retval)); 2134 2135 out: 2136 FILE_UNUSE(fp, l); 2137 return (error); 2138 } 2139 2140 /* 2141 * Check access permissions. 2142 */ 2143 int 2144 sys_access(struct lwp *l, void *v, register_t *retval) 2145 { 2146 struct sys_access_args /* { 2147 syscallarg(const char *) path; 2148 syscallarg(int) flags; 2149 } */ *uap = v; 2150 struct proc *p = l->l_proc; 2151 kauth_cred_t cred; 2152 struct vnode *vp; 2153 int error, flags; 2154 struct nameidata nd; 2155 2156 cred = kauth_cred_dup(p->p_cred); 2157 kauth_cred_seteuid(cred, kauth_cred_getuid(p->p_cred)); 2158 kauth_cred_setegid(cred, kauth_cred_getgid(p->p_cred)); 2159 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 2160 SCARG(uap, path), l); 2161 /* Override default credentials */ 2162 nd.ni_cnd.cn_cred = cred; 2163 if ((error = namei(&nd)) != 0) 2164 goto out; 2165 vp = nd.ni_vp; 2166 2167 /* Flags == 0 means only check for existence. */ 2168 if (SCARG(uap, flags)) { 2169 flags = 0; 2170 if (SCARG(uap, flags) & R_OK) 2171 flags |= VREAD; 2172 if (SCARG(uap, flags) & W_OK) 2173 flags |= VWRITE; 2174 if (SCARG(uap, flags) & X_OK) 2175 flags |= VEXEC; 2176 2177 error = VOP_ACCESS(vp, flags, cred, l); 2178 if (!error && (flags & VWRITE)) 2179 error = vn_writechk(vp); 2180 } 2181 vput(vp); 2182 out: 2183 kauth_cred_free(cred); 2184 return (error); 2185 } 2186 2187 /* 2188 * Get file status; this version follows links. 2189 */ 2190 /* ARGSUSED */ 2191 int 2192 sys___stat30(struct lwp *l, void *v, register_t *retval) 2193 { 2194 struct sys___stat30_args /* { 2195 syscallarg(const char *) path; 2196 syscallarg(struct stat *) ub; 2197 } */ *uap = v; 2198 struct stat sb; 2199 int error; 2200 struct nameidata nd; 2201 2202 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 2203 SCARG(uap, path), l); 2204 if ((error = namei(&nd)) != 0) 2205 return (error); 2206 error = vn_stat(nd.ni_vp, &sb, l); 2207 vput(nd.ni_vp); 2208 if (error) 2209 return (error); 2210 error = copyout(&sb, SCARG(uap, ub), sizeof(sb)); 2211 return (error); 2212 } 2213 2214 /* 2215 * Get file status; this version does not follow links. 2216 */ 2217 /* ARGSUSED */ 2218 int 2219 sys___lstat30(struct lwp *l, void *v, register_t *retval) 2220 { 2221 struct sys___lstat30_args /* { 2222 syscallarg(const char *) path; 2223 syscallarg(struct stat *) ub; 2224 } */ *uap = v; 2225 struct stat sb; 2226 int error; 2227 struct nameidata nd; 2228 2229 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, 2230 SCARG(uap, path), l); 2231 if ((error = namei(&nd)) != 0) 2232 return (error); 2233 error = vn_stat(nd.ni_vp, &sb, l); 2234 vput(nd.ni_vp); 2235 if (error) 2236 return (error); 2237 error = copyout(&sb, SCARG(uap, ub), sizeof(sb)); 2238 return (error); 2239 } 2240 2241 /* 2242 * Get configurable pathname variables. 2243 */ 2244 /* ARGSUSED */ 2245 int 2246 sys_pathconf(struct lwp *l, void *v, register_t *retval) 2247 { 2248 struct sys_pathconf_args /* { 2249 syscallarg(const char *) path; 2250 syscallarg(int) name; 2251 } */ *uap = v; 2252 int error; 2253 struct nameidata nd; 2254 2255 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 2256 SCARG(uap, path), l); 2257 if ((error = namei(&nd)) != 0) 2258 return (error); 2259 error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval); 2260 vput(nd.ni_vp); 2261 return (error); 2262 } 2263 2264 /* 2265 * Return target name of a symbolic link. 2266 */ 2267 /* ARGSUSED */ 2268 int 2269 sys_readlink(struct lwp *l, void *v, register_t *retval) 2270 { 2271 struct sys_readlink_args /* { 2272 syscallarg(const char *) path; 2273 syscallarg(char *) buf; 2274 syscallarg(size_t) count; 2275 } */ *uap = v; 2276 struct proc *p = l->l_proc; 2277 struct vnode *vp; 2278 struct iovec aiov; 2279 struct uio auio; 2280 int error; 2281 struct nameidata nd; 2282 2283 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, 2284 SCARG(uap, path), l); 2285 if ((error = namei(&nd)) != 0) 2286 return (error); 2287 vp = nd.ni_vp; 2288 if (vp->v_type != VLNK) 2289 error = EINVAL; 2290 else if (!(vp->v_mount->mnt_flag & MNT_SYMPERM) || 2291 (error = VOP_ACCESS(vp, VREAD, p->p_cred, l)) == 0) { 2292 aiov.iov_base = SCARG(uap, buf); 2293 aiov.iov_len = SCARG(uap, count); 2294 auio.uio_iov = &aiov; 2295 auio.uio_iovcnt = 1; 2296 auio.uio_offset = 0; 2297 auio.uio_rw = UIO_READ; 2298 KASSERT(l == curlwp); 2299 auio.uio_vmspace = l->l_proc->p_vmspace; 2300 auio.uio_resid = SCARG(uap, count); 2301 error = VOP_READLINK(vp, &auio, p->p_cred); 2302 } 2303 vput(vp); 2304 *retval = SCARG(uap, count) - auio.uio_resid; 2305 return (error); 2306 } 2307 2308 /* 2309 * Change flags of a file given a path name. 2310 */ 2311 /* ARGSUSED */ 2312 int 2313 sys_chflags(struct lwp *l, void *v, register_t *retval) 2314 { 2315 struct sys_chflags_args /* { 2316 syscallarg(const char *) path; 2317 syscallarg(u_long) flags; 2318 } */ *uap = v; 2319 struct vnode *vp; 2320 int error; 2321 struct nameidata nd; 2322 2323 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), l); 2324 if ((error = namei(&nd)) != 0) 2325 return (error); 2326 vp = nd.ni_vp; 2327 error = change_flags(vp, SCARG(uap, flags), l); 2328 vput(vp); 2329 return (error); 2330 } 2331 2332 /* 2333 * Change flags of a file given a file descriptor. 2334 */ 2335 /* ARGSUSED */ 2336 int 2337 sys_fchflags(struct lwp *l, void *v, register_t *retval) 2338 { 2339 struct sys_fchflags_args /* { 2340 syscallarg(int) fd; 2341 syscallarg(u_long) flags; 2342 } */ *uap = v; 2343 struct proc *p = l->l_proc; 2344 struct vnode *vp; 2345 struct file *fp; 2346 int error; 2347 2348 /* getvnode() will use the descriptor for us */ 2349 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 2350 return (error); 2351 vp = (struct vnode *)fp->f_data; 2352 error = change_flags(vp, SCARG(uap, flags), l); 2353 VOP_UNLOCK(vp, 0); 2354 FILE_UNUSE(fp, l); 2355 return (error); 2356 } 2357 2358 /* 2359 * Change flags of a file given a path name; this version does 2360 * not follow links. 2361 */ 2362 int 2363 sys_lchflags(struct lwp *l, void *v, register_t *retval) 2364 { 2365 struct sys_lchflags_args /* { 2366 syscallarg(const char *) path; 2367 syscallarg(u_long) flags; 2368 } */ *uap = v; 2369 struct vnode *vp; 2370 int error; 2371 struct nameidata nd; 2372 2373 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), l); 2374 if ((error = namei(&nd)) != 0) 2375 return (error); 2376 vp = nd.ni_vp; 2377 error = change_flags(vp, SCARG(uap, flags), l); 2378 vput(vp); 2379 return (error); 2380 } 2381 2382 /* 2383 * Common routine to change flags of a file. 2384 */ 2385 int 2386 change_flags(struct vnode *vp, u_long flags, struct lwp *l) 2387 { 2388 struct proc *p = l->l_proc; 2389 struct mount *mp; 2390 struct vattr vattr; 2391 int error; 2392 2393 if ((error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) != 0) 2394 return (error); 2395 VOP_LEASE(vp, l, p->p_cred, LEASE_WRITE); 2396 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 2397 /* 2398 * Non-superusers cannot change the flags on devices, even if they 2399 * own them. 2400 */ 2401 if (kauth_authorize_generic(p->p_cred, KAUTH_GENERIC_ISSUSER, 2402 &p->p_acflag) != 0) { 2403 if ((error = VOP_GETATTR(vp, &vattr, p->p_cred, l)) != 0) 2404 goto out; 2405 if (vattr.va_type == VCHR || vattr.va_type == VBLK) { 2406 error = EINVAL; 2407 goto out; 2408 } 2409 } 2410 VATTR_NULL(&vattr); 2411 vattr.va_flags = flags; 2412 error = VOP_SETATTR(vp, &vattr, p->p_cred, l); 2413 out: 2414 vn_finished_write(mp, 0); 2415 return (error); 2416 } 2417 2418 /* 2419 * Change mode of a file given path name; this version follows links. 2420 */ 2421 /* ARGSUSED */ 2422 int 2423 sys_chmod(struct lwp *l, void *v, register_t *retval) 2424 { 2425 struct sys_chmod_args /* { 2426 syscallarg(const char *) path; 2427 syscallarg(int) mode; 2428 } */ *uap = v; 2429 int error; 2430 struct nameidata nd; 2431 2432 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), l); 2433 if ((error = namei(&nd)) != 0) 2434 return (error); 2435 2436 error = change_mode(nd.ni_vp, SCARG(uap, mode), l); 2437 2438 vrele(nd.ni_vp); 2439 return (error); 2440 } 2441 2442 /* 2443 * Change mode of a file given a file descriptor. 2444 */ 2445 /* ARGSUSED */ 2446 int 2447 sys_fchmod(struct lwp *l, void *v, register_t *retval) 2448 { 2449 struct sys_fchmod_args /* { 2450 syscallarg(int) fd; 2451 syscallarg(int) mode; 2452 } */ *uap = v; 2453 struct proc *p = l->l_proc; 2454 struct file *fp; 2455 int error; 2456 2457 /* getvnode() will use the descriptor for us */ 2458 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 2459 return (error); 2460 2461 error = change_mode((struct vnode *)fp->f_data, SCARG(uap, mode), l); 2462 FILE_UNUSE(fp, l); 2463 return (error); 2464 } 2465 2466 /* 2467 * Change mode of a file given path name; this version does not follow links. 2468 */ 2469 /* ARGSUSED */ 2470 int 2471 sys_lchmod(struct lwp *l, void *v, register_t *retval) 2472 { 2473 struct sys_lchmod_args /* { 2474 syscallarg(const char *) path; 2475 syscallarg(int) mode; 2476 } */ *uap = v; 2477 int error; 2478 struct nameidata nd; 2479 2480 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), l); 2481 if ((error = namei(&nd)) != 0) 2482 return (error); 2483 2484 error = change_mode(nd.ni_vp, SCARG(uap, mode), l); 2485 2486 vrele(nd.ni_vp); 2487 return (error); 2488 } 2489 2490 /* 2491 * Common routine to set mode given a vnode. 2492 */ 2493 static int 2494 change_mode(struct vnode *vp, int mode, struct lwp *l) 2495 { 2496 struct proc *p = l->l_proc; 2497 struct mount *mp; 2498 struct vattr vattr; 2499 int error; 2500 2501 if ((error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) != 0) 2502 return (error); 2503 VOP_LEASE(vp, l, p->p_cred, LEASE_WRITE); 2504 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 2505 VATTR_NULL(&vattr); 2506 vattr.va_mode = mode & ALLPERMS; 2507 error = VOP_SETATTR(vp, &vattr, p->p_cred, l); 2508 VOP_UNLOCK(vp, 0); 2509 vn_finished_write(mp, 0); 2510 return (error); 2511 } 2512 2513 /* 2514 * Set ownership given a path name; this version follows links. 2515 */ 2516 /* ARGSUSED */ 2517 int 2518 sys_chown(struct lwp *l, void *v, register_t *retval) 2519 { 2520 struct sys_chown_args /* { 2521 syscallarg(const char *) path; 2522 syscallarg(uid_t) uid; 2523 syscallarg(gid_t) gid; 2524 } */ *uap = v; 2525 int error; 2526 struct nameidata nd; 2527 2528 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), l); 2529 if ((error = namei(&nd)) != 0) 2530 return (error); 2531 2532 error = change_owner(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid), l, 0); 2533 2534 vrele(nd.ni_vp); 2535 return (error); 2536 } 2537 2538 /* 2539 * Set ownership given a path name; this version follows links. 2540 * Provides POSIX semantics. 2541 */ 2542 /* ARGSUSED */ 2543 int 2544 sys___posix_chown(struct lwp *l, void *v, register_t *retval) 2545 { 2546 struct sys_chown_args /* { 2547 syscallarg(const char *) path; 2548 syscallarg(uid_t) uid; 2549 syscallarg(gid_t) gid; 2550 } */ *uap = v; 2551 int error; 2552 struct nameidata nd; 2553 2554 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), l); 2555 if ((error = namei(&nd)) != 0) 2556 return (error); 2557 2558 error = change_owner(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid), l, 1); 2559 2560 vrele(nd.ni_vp); 2561 return (error); 2562 } 2563 2564 /* 2565 * Set ownership given a file descriptor. 2566 */ 2567 /* ARGSUSED */ 2568 int 2569 sys_fchown(struct lwp *l, void *v, register_t *retval) 2570 { 2571 struct sys_fchown_args /* { 2572 syscallarg(int) fd; 2573 syscallarg(uid_t) uid; 2574 syscallarg(gid_t) gid; 2575 } */ *uap = v; 2576 struct proc *p = l->l_proc; 2577 int error; 2578 struct file *fp; 2579 2580 /* getvnode() will use the descriptor for us */ 2581 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 2582 return (error); 2583 2584 error = change_owner((struct vnode *)fp->f_data, SCARG(uap, uid), 2585 SCARG(uap, gid), l, 0); 2586 FILE_UNUSE(fp, l); 2587 return (error); 2588 } 2589 2590 /* 2591 * Set ownership given a file descriptor, providing POSIX/XPG semantics. 2592 */ 2593 /* ARGSUSED */ 2594 int 2595 sys___posix_fchown(struct lwp *l, void *v, register_t *retval) 2596 { 2597 struct sys_fchown_args /* { 2598 syscallarg(int) fd; 2599 syscallarg(uid_t) uid; 2600 syscallarg(gid_t) gid; 2601 } */ *uap = v; 2602 struct proc *p = l->l_proc; 2603 int error; 2604 struct file *fp; 2605 2606 /* getvnode() will use the descriptor for us */ 2607 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 2608 return (error); 2609 2610 error = change_owner((struct vnode *)fp->f_data, SCARG(uap, uid), 2611 SCARG(uap, gid), l, 1); 2612 FILE_UNUSE(fp, l); 2613 return (error); 2614 } 2615 2616 /* 2617 * Set ownership given a path name; this version does not follow links. 2618 */ 2619 /* ARGSUSED */ 2620 int 2621 sys_lchown(struct lwp *l, void *v, register_t *retval) 2622 { 2623 struct sys_lchown_args /* { 2624 syscallarg(const char *) path; 2625 syscallarg(uid_t) uid; 2626 syscallarg(gid_t) gid; 2627 } */ *uap = v; 2628 int error; 2629 struct nameidata nd; 2630 2631 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), l); 2632 if ((error = namei(&nd)) != 0) 2633 return (error); 2634 2635 error = change_owner(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid), l, 0); 2636 2637 vrele(nd.ni_vp); 2638 return (error); 2639 } 2640 2641 /* 2642 * Set ownership given a path name; this version does not follow links. 2643 * Provides POSIX/XPG semantics. 2644 */ 2645 /* ARGSUSED */ 2646 int 2647 sys___posix_lchown(struct lwp *l, void *v, register_t *retval) 2648 { 2649 struct sys_lchown_args /* { 2650 syscallarg(const char *) path; 2651 syscallarg(uid_t) uid; 2652 syscallarg(gid_t) gid; 2653 } */ *uap = v; 2654 int error; 2655 struct nameidata nd; 2656 2657 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), l); 2658 if ((error = namei(&nd)) != 0) 2659 return (error); 2660 2661 error = change_owner(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid), l, 1); 2662 2663 vrele(nd.ni_vp); 2664 return (error); 2665 } 2666 2667 /* 2668 * Common routine to set ownership given a vnode. 2669 */ 2670 static int 2671 change_owner(struct vnode *vp, uid_t uid, gid_t gid, struct lwp *l, 2672 int posix_semantics) 2673 { 2674 struct proc *p = l->l_proc; 2675 struct mount *mp; 2676 struct vattr vattr; 2677 mode_t newmode; 2678 int error; 2679 2680 if ((error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) != 0) 2681 return (error); 2682 VOP_LEASE(vp, l, p->p_cred, LEASE_WRITE); 2683 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 2684 if ((error = VOP_GETATTR(vp, &vattr, p->p_cred, l)) != 0) 2685 goto out; 2686 2687 #define CHANGED(x) ((int)(x) != -1) 2688 newmode = vattr.va_mode; 2689 if (posix_semantics) { 2690 /* 2691 * POSIX/XPG semantics: if the caller is not the super-user, 2692 * clear set-user-id and set-group-id bits. Both POSIX and 2693 * the XPG consider the behaviour for calls by the super-user 2694 * implementation-defined; we leave the set-user-id and set- 2695 * group-id settings intact in that case. 2696 */ 2697 if (kauth_authorize_generic(p->p_cred, KAUTH_GENERIC_ISSUSER, 2698 NULL) != 0) 2699 newmode &= ~(S_ISUID | S_ISGID); 2700 } else { 2701 /* 2702 * NetBSD semantics: when changing owner and/or group, 2703 * clear the respective bit(s). 2704 */ 2705 if (CHANGED(uid)) 2706 newmode &= ~S_ISUID; 2707 if (CHANGED(gid)) 2708 newmode &= ~S_ISGID; 2709 } 2710 /* Update va_mode iff altered. */ 2711 if (vattr.va_mode == newmode) 2712 newmode = VNOVAL; 2713 2714 VATTR_NULL(&vattr); 2715 vattr.va_uid = CHANGED(uid) ? uid : (uid_t)VNOVAL; 2716 vattr.va_gid = CHANGED(gid) ? gid : (gid_t)VNOVAL; 2717 vattr.va_mode = newmode; 2718 error = VOP_SETATTR(vp, &vattr, p->p_cred, l); 2719 #undef CHANGED 2720 2721 out: 2722 VOP_UNLOCK(vp, 0); 2723 vn_finished_write(mp, 0); 2724 return (error); 2725 } 2726 2727 /* 2728 * Set the access and modification times given a path name; this 2729 * version follows links. 2730 */ 2731 /* ARGSUSED */ 2732 int 2733 sys_utimes(struct lwp *l, void *v, register_t *retval) 2734 { 2735 struct sys_utimes_args /* { 2736 syscallarg(const char *) path; 2737 syscallarg(const struct timeval *) tptr; 2738 } */ *uap = v; 2739 int error; 2740 struct nameidata nd; 2741 2742 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), l); 2743 if ((error = namei(&nd)) != 0) 2744 return (error); 2745 2746 error = change_utimes(nd.ni_vp, SCARG(uap, tptr), l); 2747 2748 vrele(nd.ni_vp); 2749 return (error); 2750 } 2751 2752 /* 2753 * Set the access and modification times given a file descriptor. 2754 */ 2755 /* ARGSUSED */ 2756 int 2757 sys_futimes(struct lwp *l, void *v, register_t *retval) 2758 { 2759 struct sys_futimes_args /* { 2760 syscallarg(int) fd; 2761 syscallarg(const struct timeval *) tptr; 2762 } */ *uap = v; 2763 struct proc *p = l->l_proc; 2764 int error; 2765 struct file *fp; 2766 2767 /* getvnode() will use the descriptor for us */ 2768 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 2769 return (error); 2770 2771 error = change_utimes((struct vnode *)fp->f_data, SCARG(uap, tptr), l); 2772 FILE_UNUSE(fp, l); 2773 return (error); 2774 } 2775 2776 /* 2777 * Set the access and modification times given a path name; this 2778 * version does not follow links. 2779 */ 2780 /* ARGSUSED */ 2781 int 2782 sys_lutimes(struct lwp *l, void *v, register_t *retval) 2783 { 2784 struct sys_lutimes_args /* { 2785 syscallarg(const char *) path; 2786 syscallarg(const struct timeval *) tptr; 2787 } */ *uap = v; 2788 int error; 2789 struct nameidata nd; 2790 2791 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), l); 2792 if ((error = namei(&nd)) != 0) 2793 return (error); 2794 2795 error = change_utimes(nd.ni_vp, SCARG(uap, tptr), l); 2796 2797 vrele(nd.ni_vp); 2798 return (error); 2799 } 2800 2801 /* 2802 * Common routine to set access and modification times given a vnode. 2803 */ 2804 static int 2805 change_utimes(struct vnode *vp, const struct timeval *tptr, struct lwp *l) 2806 { 2807 struct proc *p = l->l_proc; 2808 struct mount *mp; 2809 struct vattr vattr; 2810 int error; 2811 2812 if ((error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) != 0) 2813 return (error); 2814 VATTR_NULL(&vattr); 2815 if (tptr == NULL) { 2816 nanotime(&vattr.va_atime); 2817 vattr.va_mtime = vattr.va_atime; 2818 vattr.va_vaflags |= VA_UTIMES_NULL; 2819 } else { 2820 struct timeval tv[2]; 2821 2822 error = copyin(tptr, tv, sizeof(tv)); 2823 if (error) 2824 goto out; 2825 TIMEVAL_TO_TIMESPEC(&tv[0], &vattr.va_atime); 2826 TIMEVAL_TO_TIMESPEC(&tv[1], &vattr.va_mtime); 2827 } 2828 VOP_LEASE(vp, l, p->p_cred, LEASE_WRITE); 2829 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 2830 error = VOP_SETATTR(vp, &vattr, p->p_cred, l); 2831 VOP_UNLOCK(vp, 0); 2832 out: 2833 vn_finished_write(mp, 0); 2834 return (error); 2835 } 2836 2837 /* 2838 * Truncate a file given its path name. 2839 */ 2840 /* ARGSUSED */ 2841 int 2842 sys_truncate(struct lwp *l, void *v, register_t *retval) 2843 { 2844 struct sys_truncate_args /* { 2845 syscallarg(const char *) path; 2846 syscallarg(int) pad; 2847 syscallarg(off_t) length; 2848 } */ *uap = v; 2849 struct proc *p = l->l_proc; 2850 struct vnode *vp; 2851 struct mount *mp; 2852 struct vattr vattr; 2853 int error; 2854 struct nameidata nd; 2855 2856 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), l); 2857 if ((error = namei(&nd)) != 0) 2858 return (error); 2859 vp = nd.ni_vp; 2860 if ((error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) != 0) { 2861 vrele(vp); 2862 return (error); 2863 } 2864 VOP_LEASE(vp, l, p->p_cred, LEASE_WRITE); 2865 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 2866 if (vp->v_type == VDIR) 2867 error = EISDIR; 2868 else if ((error = vn_writechk(vp)) == 0 && 2869 (error = VOP_ACCESS(vp, VWRITE, p->p_cred, l)) == 0) { 2870 VATTR_NULL(&vattr); 2871 vattr.va_size = SCARG(uap, length); 2872 error = VOP_SETATTR(vp, &vattr, p->p_cred, l); 2873 } 2874 vput(vp); 2875 vn_finished_write(mp, 0); 2876 return (error); 2877 } 2878 2879 /* 2880 * Truncate a file given a file descriptor. 2881 */ 2882 /* ARGSUSED */ 2883 int 2884 sys_ftruncate(struct lwp *l, void *v, register_t *retval) 2885 { 2886 struct sys_ftruncate_args /* { 2887 syscallarg(int) fd; 2888 syscallarg(int) pad; 2889 syscallarg(off_t) length; 2890 } */ *uap = v; 2891 struct proc *p = l->l_proc; 2892 struct mount *mp; 2893 struct vattr vattr; 2894 struct vnode *vp; 2895 struct file *fp; 2896 int error; 2897 2898 /* getvnode() will use the descriptor for us */ 2899 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 2900 return (error); 2901 if ((fp->f_flag & FWRITE) == 0) { 2902 error = EINVAL; 2903 goto out; 2904 } 2905 vp = (struct vnode *)fp->f_data; 2906 if ((error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) != 0) { 2907 FILE_UNUSE(fp, l); 2908 return (error); 2909 } 2910 VOP_LEASE(vp, l, p->p_cred, LEASE_WRITE); 2911 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 2912 if (vp->v_type == VDIR) 2913 error = EISDIR; 2914 else if ((error = vn_writechk(vp)) == 0) { 2915 VATTR_NULL(&vattr); 2916 vattr.va_size = SCARG(uap, length); 2917 error = VOP_SETATTR(vp, &vattr, fp->f_cred, l); 2918 } 2919 VOP_UNLOCK(vp, 0); 2920 vn_finished_write(mp, 0); 2921 out: 2922 FILE_UNUSE(fp, l); 2923 return (error); 2924 } 2925 2926 /* 2927 * Sync an open file. 2928 */ 2929 /* ARGSUSED */ 2930 int 2931 sys_fsync(struct lwp *l, void *v, register_t *retval) 2932 { 2933 struct sys_fsync_args /* { 2934 syscallarg(int) fd; 2935 } */ *uap = v; 2936 struct proc *p = l->l_proc; 2937 struct vnode *vp; 2938 struct mount *mp; 2939 struct file *fp; 2940 int error; 2941 2942 /* getvnode() will use the descriptor for us */ 2943 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 2944 return (error); 2945 vp = (struct vnode *)fp->f_data; 2946 if ((error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) != 0) { 2947 FILE_UNUSE(fp, l); 2948 return (error); 2949 } 2950 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 2951 error = VOP_FSYNC(vp, fp->f_cred, FSYNC_WAIT, 0, 0, l); 2952 if (error == 0 && bioops.io_fsync != NULL && 2953 vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP)) 2954 (*bioops.io_fsync)(vp, 0); 2955 VOP_UNLOCK(vp, 0); 2956 vn_finished_write(mp, 0); 2957 FILE_UNUSE(fp, l); 2958 return (error); 2959 } 2960 2961 /* 2962 * Sync a range of file data. API modeled after that found in AIX. 2963 * 2964 * FDATASYNC indicates that we need only save enough metadata to be able 2965 * to re-read the written data. Note we duplicate AIX's requirement that 2966 * the file be open for writing. 2967 */ 2968 /* ARGSUSED */ 2969 int 2970 sys_fsync_range(struct lwp *l, void *v, register_t *retval) 2971 { 2972 struct sys_fsync_range_args /* { 2973 syscallarg(int) fd; 2974 syscallarg(int) flags; 2975 syscallarg(off_t) start; 2976 syscallarg(off_t) length; 2977 } */ *uap = v; 2978 struct proc *p = l->l_proc; 2979 struct vnode *vp; 2980 struct file *fp; 2981 int flags, nflags; 2982 off_t s, e, len; 2983 int error; 2984 2985 /* getvnode() will use the descriptor for us */ 2986 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 2987 return (error); 2988 2989 if ((fp->f_flag & FWRITE) == 0) { 2990 FILE_UNUSE(fp, l); 2991 return (EBADF); 2992 } 2993 2994 flags = SCARG(uap, flags); 2995 if (((flags & (FDATASYNC | FFILESYNC)) == 0) || 2996 ((~flags & (FDATASYNC | FFILESYNC)) == 0)) { 2997 return (EINVAL); 2998 } 2999 /* Now set up the flags for value(s) to pass to VOP_FSYNC() */ 3000 if (flags & FDATASYNC) 3001 nflags = FSYNC_DATAONLY | FSYNC_WAIT; 3002 else 3003 nflags = FSYNC_WAIT; 3004 if (flags & FDISKSYNC) 3005 nflags |= FSYNC_CACHE; 3006 3007 len = SCARG(uap, length); 3008 /* If length == 0, we do the whole file, and s = l = 0 will do that */ 3009 if (len) { 3010 s = SCARG(uap, start); 3011 e = s + len; 3012 if (e < s) { 3013 FILE_UNUSE(fp, l); 3014 return (EINVAL); 3015 } 3016 } else { 3017 e = 0; 3018 s = 0; 3019 } 3020 3021 vp = (struct vnode *)fp->f_data; 3022 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 3023 error = VOP_FSYNC(vp, fp->f_cred, nflags, s, e, l); 3024 3025 if (error == 0 && bioops.io_fsync != NULL && 3026 vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP)) 3027 (*bioops.io_fsync)(vp, nflags); 3028 3029 VOP_UNLOCK(vp, 0); 3030 FILE_UNUSE(fp, l); 3031 return (error); 3032 } 3033 3034 /* 3035 * Sync the data of an open file. 3036 */ 3037 /* ARGSUSED */ 3038 int 3039 sys_fdatasync(struct lwp *l, void *v, register_t *retval) 3040 { 3041 struct sys_fdatasync_args /* { 3042 syscallarg(int) fd; 3043 } */ *uap = v; 3044 struct proc *p = l->l_proc; 3045 struct vnode *vp; 3046 struct file *fp; 3047 int error; 3048 3049 /* getvnode() will use the descriptor for us */ 3050 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 3051 return (error); 3052 if ((fp->f_flag & FWRITE) == 0) { 3053 FILE_UNUSE(fp, l); 3054 return (EBADF); 3055 } 3056 vp = (struct vnode *)fp->f_data; 3057 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 3058 error = VOP_FSYNC(vp, fp->f_cred, FSYNC_WAIT|FSYNC_DATAONLY, 0, 0, l); 3059 VOP_UNLOCK(vp, 0); 3060 FILE_UNUSE(fp, l); 3061 return (error); 3062 } 3063 3064 /* 3065 * Rename files, (standard) BSD semantics frontend. 3066 */ 3067 /* ARGSUSED */ 3068 int 3069 sys_rename(struct lwp *l, void *v, register_t *retval) 3070 { 3071 struct sys_rename_args /* { 3072 syscallarg(const char *) from; 3073 syscallarg(const char *) to; 3074 } */ *uap = v; 3075 3076 return (rename_files(SCARG(uap, from), SCARG(uap, to), l, 0)); 3077 } 3078 3079 /* 3080 * Rename files, POSIX semantics frontend. 3081 */ 3082 /* ARGSUSED */ 3083 int 3084 sys___posix_rename(struct lwp *l, void *v, register_t *retval) 3085 { 3086 struct sys___posix_rename_args /* { 3087 syscallarg(const char *) from; 3088 syscallarg(const char *) to; 3089 } */ *uap = v; 3090 3091 return (rename_files(SCARG(uap, from), SCARG(uap, to), l, 1)); 3092 } 3093 3094 /* 3095 * Rename files. Source and destination must either both be directories, 3096 * or both not be directories. If target is a directory, it must be empty. 3097 * If `from' and `to' refer to the same object, the value of the `retain' 3098 * argument is used to determine whether `from' will be 3099 * 3100 * (retain == 0) deleted unless `from' and `to' refer to the same 3101 * object in the file system's name space (BSD). 3102 * (retain == 1) always retained (POSIX). 3103 */ 3104 static int 3105 rename_files(const char *from, const char *to, struct lwp *l, int retain) 3106 { 3107 struct mount *mp = NULL; 3108 struct vnode *tvp, *fvp, *tdvp; 3109 struct nameidata fromnd, tond; 3110 struct proc *p; 3111 int error; 3112 3113 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE, 3114 from, l); 3115 if ((error = namei(&fromnd)) != 0) 3116 return (error); 3117 fvp = fromnd.ni_vp; 3118 error = vn_start_write(fvp, &mp, V_WAIT | V_PCATCH); 3119 if (error != 0) { 3120 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 3121 vrele(fromnd.ni_dvp); 3122 vrele(fvp); 3123 if (fromnd.ni_startdir) 3124 vrele(fromnd.ni_startdir); 3125 PNBUF_PUT(fromnd.ni_cnd.cn_pnbuf); 3126 return (error); 3127 } 3128 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | 3129 (fvp->v_type == VDIR ? CREATEDIR : 0), UIO_USERSPACE, to, l); 3130 if ((error = namei(&tond)) != 0) { 3131 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 3132 vrele(fromnd.ni_dvp); 3133 vrele(fvp); 3134 goto out1; 3135 } 3136 tdvp = tond.ni_dvp; 3137 tvp = tond.ni_vp; 3138 3139 if (tvp != NULL) { 3140 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 3141 error = ENOTDIR; 3142 goto out; 3143 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 3144 error = EISDIR; 3145 goto out; 3146 } 3147 } 3148 3149 if (fvp == tdvp) 3150 error = EINVAL; 3151 3152 /* 3153 * Source and destination refer to the same object. 3154 */ 3155 if (fvp == tvp) { 3156 if (retain) 3157 error = -1; 3158 else if (fromnd.ni_dvp == tdvp && 3159 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen && 3160 !memcmp(fromnd.ni_cnd.cn_nameptr, 3161 tond.ni_cnd.cn_nameptr, 3162 fromnd.ni_cnd.cn_namelen)) 3163 error = -1; 3164 } 3165 3166 #ifdef VERIFIED_EXEC 3167 if (!error) 3168 error = veriexec_renamechk(fvp, fromnd.ni_dirp, tond.ni_dirp, l); 3169 #endif /* VERIFIED_EXEC */ 3170 3171 out: 3172 p = l->l_proc; 3173 if (!error) { 3174 VOP_LEASE(tdvp, l, p->p_cred, LEASE_WRITE); 3175 if (fromnd.ni_dvp != tdvp) 3176 VOP_LEASE(fromnd.ni_dvp, l, p->p_cred, LEASE_WRITE); 3177 if (tvp) { 3178 VOP_LEASE(tvp, l, p->p_cred, LEASE_WRITE); 3179 } 3180 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 3181 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 3182 } else { 3183 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd); 3184 if (tdvp == tvp) 3185 vrele(tdvp); 3186 else 3187 vput(tdvp); 3188 if (tvp) 3189 vput(tvp); 3190 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 3191 vrele(fromnd.ni_dvp); 3192 vrele(fvp); 3193 } 3194 vrele(tond.ni_startdir); 3195 PNBUF_PUT(tond.ni_cnd.cn_pnbuf); 3196 out1: 3197 vn_finished_write(mp, 0); 3198 if (fromnd.ni_startdir) 3199 vrele(fromnd.ni_startdir); 3200 PNBUF_PUT(fromnd.ni_cnd.cn_pnbuf); 3201 return (error == -1 ? 0 : error); 3202 } 3203 3204 /* 3205 * Make a directory file. 3206 */ 3207 /* ARGSUSED */ 3208 int 3209 sys_mkdir(struct lwp *l, void *v, register_t *retval) 3210 { 3211 struct sys_mkdir_args /* { 3212 syscallarg(const char *) path; 3213 syscallarg(int) mode; 3214 } */ *uap = v; 3215 struct proc *p = l->l_proc; 3216 struct mount *mp; 3217 struct vnode *vp; 3218 struct vattr vattr; 3219 int error; 3220 struct nameidata nd; 3221 3222 restart: 3223 NDINIT(&nd, CREATE, LOCKPARENT | CREATEDIR, UIO_USERSPACE, 3224 SCARG(uap, path), l); 3225 if ((error = namei(&nd)) != 0) 3226 return (error); 3227 vp = nd.ni_vp; 3228 if (vp != NULL) { 3229 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 3230 if (nd.ni_dvp == vp) 3231 vrele(nd.ni_dvp); 3232 else 3233 vput(nd.ni_dvp); 3234 vrele(vp); 3235 return (EEXIST); 3236 } 3237 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 3238 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 3239 if (nd.ni_dvp == vp) 3240 vrele(nd.ni_dvp); 3241 else 3242 vput(nd.ni_dvp); 3243 if ((error = vn_start_write(NULL, &mp, 3244 V_WAIT | V_SLEEPONLY | V_PCATCH)) != 0) 3245 return (error); 3246 goto restart; 3247 } 3248 VATTR_NULL(&vattr); 3249 vattr.va_type = VDIR; 3250 vattr.va_mode = 3251 (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_cwdi->cwdi_cmask; 3252 VOP_LEASE(nd.ni_dvp, l, p->p_cred, LEASE_WRITE); 3253 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 3254 if (!error) 3255 vput(nd.ni_vp); 3256 vn_finished_write(mp, 0); 3257 return (error); 3258 } 3259 3260 /* 3261 * Remove a directory file. 3262 */ 3263 /* ARGSUSED */ 3264 int 3265 sys_rmdir(struct lwp *l, void *v, register_t *retval) 3266 { 3267 struct sys_rmdir_args /* { 3268 syscallarg(const char *) path; 3269 } */ *uap = v; 3270 struct proc *p = l->l_proc; 3271 struct mount *mp; 3272 struct vnode *vp; 3273 int error; 3274 struct nameidata nd; 3275 3276 restart: 3277 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, 3278 SCARG(uap, path), l); 3279 if ((error = namei(&nd)) != 0) 3280 return (error); 3281 vp = nd.ni_vp; 3282 if (vp->v_type != VDIR) { 3283 error = ENOTDIR; 3284 goto out; 3285 } 3286 /* 3287 * No rmdir "." please. 3288 */ 3289 if (nd.ni_dvp == vp) { 3290 error = EINVAL; 3291 goto out; 3292 } 3293 /* 3294 * The root of a mounted filesystem cannot be deleted. 3295 */ 3296 if (vp->v_flag & VROOT) { 3297 error = EBUSY; 3298 goto out; 3299 } 3300 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 3301 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 3302 if (nd.ni_dvp == vp) 3303 vrele(nd.ni_dvp); 3304 else 3305 vput(nd.ni_dvp); 3306 vput(vp); 3307 if ((error = vn_start_write(NULL, &mp, 3308 V_WAIT | V_SLEEPONLY | V_PCATCH)) != 0) 3309 return (error); 3310 goto restart; 3311 } 3312 VOP_LEASE(nd.ni_dvp, l, p->p_cred, LEASE_WRITE); 3313 VOP_LEASE(vp, l, p->p_cred, LEASE_WRITE); 3314 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 3315 vn_finished_write(mp, 0); 3316 return (error); 3317 3318 out: 3319 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 3320 if (nd.ni_dvp == vp) 3321 vrele(nd.ni_dvp); 3322 else 3323 vput(nd.ni_dvp); 3324 vput(vp); 3325 return (error); 3326 } 3327 3328 /* 3329 * Read a block of directory entries in a file system independent format. 3330 */ 3331 int 3332 sys___getdents30(struct lwp *l, void *v, register_t *retval) 3333 { 3334 struct sys___getdents30_args /* { 3335 syscallarg(int) fd; 3336 syscallarg(char *) buf; 3337 syscallarg(size_t) count; 3338 } */ *uap = v; 3339 struct proc *p = l->l_proc; 3340 struct file *fp; 3341 int error, done; 3342 3343 /* getvnode() will use the descriptor for us */ 3344 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 3345 return (error); 3346 if ((fp->f_flag & FREAD) == 0) { 3347 error = EBADF; 3348 goto out; 3349 } 3350 error = vn_readdir(fp, SCARG(uap, buf), UIO_USERSPACE, 3351 SCARG(uap, count), &done, l, 0, 0); 3352 #ifdef KTRACE 3353 if (!error && KTRPOINT(p, KTR_GENIO)) { 3354 struct iovec iov; 3355 iov.iov_base = SCARG(uap, buf); 3356 iov.iov_len = done; 3357 ktrgenio(l, SCARG(uap, fd), UIO_READ, &iov, done, 0); 3358 } 3359 #endif 3360 *retval = done; 3361 out: 3362 FILE_UNUSE(fp, l); 3363 return (error); 3364 } 3365 3366 /* 3367 * Set the mode mask for creation of filesystem nodes. 3368 */ 3369 int 3370 sys_umask(struct lwp *l, void *v, register_t *retval) 3371 { 3372 struct sys_umask_args /* { 3373 syscallarg(mode_t) newmask; 3374 } */ *uap = v; 3375 struct proc *p = l->l_proc; 3376 struct cwdinfo *cwdi; 3377 3378 cwdi = p->p_cwdi; 3379 *retval = cwdi->cwdi_cmask; 3380 cwdi->cwdi_cmask = SCARG(uap, newmask) & ALLPERMS; 3381 return (0); 3382 } 3383 3384 /* 3385 * Void all references to file by ripping underlying filesystem 3386 * away from vnode. 3387 */ 3388 /* ARGSUSED */ 3389 int 3390 sys_revoke(struct lwp *l, void *v, register_t *retval) 3391 { 3392 struct sys_revoke_args /* { 3393 syscallarg(const char *) path; 3394 } */ *uap = v; 3395 struct proc *p = l->l_proc; 3396 struct mount *mp; 3397 struct vnode *vp; 3398 struct vattr vattr; 3399 int error; 3400 struct nameidata nd; 3401 3402 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), l); 3403 if ((error = namei(&nd)) != 0) 3404 return (error); 3405 vp = nd.ni_vp; 3406 if ((error = VOP_GETATTR(vp, &vattr, p->p_cred, l)) != 0) 3407 goto out; 3408 if (kauth_cred_geteuid(p->p_cred) != vattr.va_uid && 3409 (error = kauth_authorize_generic(p->p_cred, KAUTH_GENERIC_ISSUSER, 3410 &p->p_acflag)) != 0) 3411 goto out; 3412 if ((error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) != 0) 3413 goto out; 3414 if (vp->v_usecount > 1 || (vp->v_flag & (VALIASED | VLAYER))) 3415 VOP_REVOKE(vp, REVOKEALL); 3416 vn_finished_write(mp, 0); 3417 out: 3418 vrele(vp); 3419 return (error); 3420 } 3421 3422 /* 3423 * Convert a user file descriptor to a kernel file entry. 3424 */ 3425 int 3426 getvnode(struct filedesc *fdp, int fd, struct file **fpp) 3427 { 3428 struct vnode *vp; 3429 struct file *fp; 3430 3431 if ((fp = fd_getfile(fdp, fd)) == NULL) 3432 return (EBADF); 3433 3434 FILE_USE(fp); 3435 3436 if (fp->f_type != DTYPE_VNODE) { 3437 FILE_UNUSE(fp, NULL); 3438 return (EINVAL); 3439 } 3440 3441 vp = (struct vnode *)fp->f_data; 3442 if (vp->v_type == VBAD) { 3443 FILE_UNUSE(fp, NULL); 3444 return (EBADF); 3445 } 3446 3447 *fpp = fp; 3448 return (0); 3449 } 3450