1 /* $NetBSD: vfs_syscalls.c,v 1.450 2012/03/13 18:40:56 elad Exp $ */ 2 3 /*- 4 * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Andrew Doran. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Copyright (c) 1989, 1993 34 * The Regents of the University of California. All rights reserved. 35 * (c) UNIX System Laboratories, Inc. 36 * All or some portions of this file are derived from material licensed 37 * to the University of California by American Telephone and Telegraph 38 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 39 * the permission of UNIX System Laboratories, Inc. 40 * 41 * Redistribution and use in source and binary forms, with or without 42 * modification, are permitted provided that the following conditions 43 * are met: 44 * 1. Redistributions of source code must retain the above copyright 45 * notice, this list of conditions and the following disclaimer. 46 * 2. Redistributions in binary form must reproduce the above copyright 47 * notice, this list of conditions and the following disclaimer in the 48 * documentation and/or other materials provided with the distribution. 49 * 3. Neither the name of the University nor the names of its contributors 50 * may be used to endorse or promote products derived from this software 51 * without specific prior written permission. 52 * 53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 63 * SUCH DAMAGE. 64 * 65 * @(#)vfs_syscalls.c 8.42 (Berkeley) 7/31/95 66 */ 67 68 /* 69 * Virtual File System System Calls 70 */ 71 72 #include <sys/cdefs.h> 73 __KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.450 2012/03/13 18:40:56 elad Exp $"); 74 75 #ifdef _KERNEL_OPT 76 #include "opt_fileassoc.h" 77 #include "veriexec.h" 78 #endif 79 80 #include <sys/param.h> 81 #include <sys/systm.h> 82 #include <sys/namei.h> 83 #include <sys/filedesc.h> 84 #include <sys/kernel.h> 85 #include <sys/file.h> 86 #include <sys/fcntl.h> 87 #include <sys/stat.h> 88 #include <sys/vnode.h> 89 #include <sys/mount.h> 90 #include <sys/proc.h> 91 #include <sys/uio.h> 92 #include <sys/kmem.h> 93 #include <sys/dirent.h> 94 #include <sys/sysctl.h> 95 #include <sys/syscallargs.h> 96 #include <sys/vfs_syscalls.h> 97 #include <sys/quota.h> 98 #include <sys/quotactl.h> 99 #include <sys/ktrace.h> 100 #ifdef FILEASSOC 101 #include <sys/fileassoc.h> 102 #endif /* FILEASSOC */ 103 #include <sys/extattr.h> 104 #include <sys/verified_exec.h> 105 #include <sys/kauth.h> 106 #include <sys/atomic.h> 107 #include <sys/module.h> 108 #include <sys/buf.h> 109 110 #include <miscfs/genfs/genfs.h> 111 #include <miscfs/syncfs/syncfs.h> 112 #include <miscfs/specfs/specdev.h> 113 114 #include <nfs/rpcv2.h> 115 #include <nfs/nfsproto.h> 116 #include <nfs/nfs.h> 117 #include <nfs/nfs_var.h> 118 119 static int change_flags(struct vnode *, u_long, struct lwp *); 120 static int change_mode(struct vnode *, int, struct lwp *l); 121 static int change_owner(struct vnode *, uid_t, gid_t, struct lwp *, int); 122 static int do_open(lwp_t *, struct pathbuf *, int, int, int *); 123 124 /* 125 * This table is used to maintain compatibility with 4.3BSD 126 * and NetBSD 0.9 mount syscalls - and possibly other systems. 127 * Note, the order is important! 128 * 129 * Do not modify this table. It should only contain filesystems 130 * supported by NetBSD 0.9 and 4.3BSD. 131 */ 132 const char * const mountcompatnames[] = { 133 NULL, /* 0 = MOUNT_NONE */ 134 MOUNT_FFS, /* 1 = MOUNT_UFS */ 135 MOUNT_NFS, /* 2 */ 136 MOUNT_MFS, /* 3 */ 137 MOUNT_MSDOS, /* 4 */ 138 MOUNT_CD9660, /* 5 = MOUNT_ISOFS */ 139 MOUNT_FDESC, /* 6 */ 140 MOUNT_KERNFS, /* 7 */ 141 NULL, /* 8 = MOUNT_DEVFS */ 142 MOUNT_AFS, /* 9 */ 143 }; 144 145 const int nmountcompatnames = __arraycount(mountcompatnames); 146 147 static int 148 open_setfp(struct lwp *l, file_t *fp, struct vnode *vp, int indx, int flags) 149 { 150 int error; 151 152 fp->f_flag = flags & FMASK; 153 fp->f_type = DTYPE_VNODE; 154 fp->f_ops = &vnops; 155 fp->f_data = vp; 156 157 if (flags & (O_EXLOCK | O_SHLOCK)) { 158 struct flock lf; 159 int type; 160 161 lf.l_whence = SEEK_SET; 162 lf.l_start = 0; 163 lf.l_len = 0; 164 if (flags & O_EXLOCK) 165 lf.l_type = F_WRLCK; 166 else 167 lf.l_type = F_RDLCK; 168 type = F_FLOCK; 169 if ((flags & FNONBLOCK) == 0) 170 type |= F_WAIT; 171 VOP_UNLOCK(vp); 172 error = VOP_ADVLOCK(vp, fp, F_SETLK, &lf, type); 173 if (error) { 174 (void) vn_close(vp, fp->f_flag, fp->f_cred); 175 fd_abort(l->l_proc, fp, indx); 176 return error; 177 } 178 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 179 atomic_or_uint(&fp->f_flag, FHASLOCK); 180 } 181 if (flags & O_CLOEXEC) 182 fd_set_exclose(l, indx, true); 183 return 0; 184 } 185 186 static int 187 mount_update(struct lwp *l, struct vnode *vp, const char *path, int flags, 188 void *data, size_t *data_len) 189 { 190 struct mount *mp; 191 int error = 0, saved_flags; 192 193 mp = vp->v_mount; 194 saved_flags = mp->mnt_flag; 195 196 /* We can operate only on VV_ROOT nodes. */ 197 if ((vp->v_vflag & VV_ROOT) == 0) { 198 error = EINVAL; 199 goto out; 200 } 201 202 /* 203 * We only allow the filesystem to be reloaded if it 204 * is currently mounted read-only. Additionally, we 205 * prevent read-write to read-only downgrades. 206 */ 207 if ((flags & (MNT_RELOAD | MNT_RDONLY)) != 0 && 208 (mp->mnt_flag & MNT_RDONLY) == 0 && 209 (mp->mnt_iflag & IMNT_CAN_RWTORO) == 0) { 210 error = EOPNOTSUPP; /* Needs translation */ 211 goto out; 212 } 213 214 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT, 215 KAUTH_REQ_SYSTEM_MOUNT_UPDATE, mp, KAUTH_ARG(flags), data); 216 if (error) 217 goto out; 218 219 if (vfs_busy(mp, NULL)) { 220 error = EPERM; 221 goto out; 222 } 223 224 mutex_enter(&mp->mnt_updating); 225 226 mp->mnt_flag &= ~MNT_OP_FLAGS; 227 mp->mnt_flag |= flags & MNT_OP_FLAGS; 228 229 /* 230 * Set the mount level flags. 231 */ 232 if (flags & MNT_RDONLY) 233 mp->mnt_flag |= MNT_RDONLY; 234 else if (mp->mnt_flag & MNT_RDONLY) 235 mp->mnt_iflag |= IMNT_WANTRDWR; 236 mp->mnt_flag &= ~MNT_BASIC_FLAGS; 237 mp->mnt_flag |= flags & MNT_BASIC_FLAGS; 238 error = VFS_MOUNT(mp, path, data, data_len); 239 240 if (error && data != NULL) { 241 int error2; 242 243 /* 244 * Update failed; let's try and see if it was an 245 * export request. For compat with 3.0 and earlier. 246 */ 247 error2 = vfs_hooks_reexport(mp, path, data); 248 249 /* 250 * Only update error code if the export request was 251 * understood but some problem occurred while 252 * processing it. 253 */ 254 if (error2 != EJUSTRETURN) 255 error = error2; 256 } 257 258 if (mp->mnt_iflag & IMNT_WANTRDWR) 259 mp->mnt_flag &= ~MNT_RDONLY; 260 if (error) 261 mp->mnt_flag = saved_flags; 262 mp->mnt_flag &= ~MNT_OP_FLAGS; 263 mp->mnt_iflag &= ~IMNT_WANTRDWR; 264 if ((mp->mnt_flag & (MNT_RDONLY | MNT_ASYNC)) == 0) { 265 if (mp->mnt_syncer == NULL) 266 error = vfs_allocate_syncvnode(mp); 267 } else { 268 if (mp->mnt_syncer != NULL) 269 vfs_deallocate_syncvnode(mp); 270 } 271 mutex_exit(&mp->mnt_updating); 272 vfs_unbusy(mp, false, NULL); 273 274 if ((error == 0) && !(saved_flags & MNT_EXTATTR) && 275 (flags & MNT_EXTATTR)) { 276 if (VFS_EXTATTRCTL(vp->v_mount, EXTATTR_CMD_START, 277 NULL, 0, NULL) != 0) { 278 printf("%s: failed to start extattr, error = %d", 279 vp->v_mount->mnt_stat.f_mntonname, error); 280 mp->mnt_flag &= ~MNT_EXTATTR; 281 } 282 } 283 284 if ((error == 0) && (saved_flags & MNT_EXTATTR) && 285 !(flags & MNT_EXTATTR)) { 286 if (VFS_EXTATTRCTL(vp->v_mount, EXTATTR_CMD_STOP, 287 NULL, 0, NULL) != 0) { 288 printf("%s: failed to stop extattr, error = %d", 289 vp->v_mount->mnt_stat.f_mntonname, error); 290 mp->mnt_flag |= MNT_RDONLY; 291 } 292 } 293 out: 294 return (error); 295 } 296 297 static int 298 mount_get_vfsops(const char *fstype, struct vfsops **vfsops) 299 { 300 char fstypename[sizeof(((struct statvfs *)NULL)->f_fstypename)]; 301 int error; 302 303 /* Copy file-system type from userspace. */ 304 error = copyinstr(fstype, fstypename, sizeof(fstypename), NULL); 305 if (error) { 306 /* 307 * Historically, filesystem types were identified by numbers. 308 * If we get an integer for the filesystem type instead of a 309 * string, we check to see if it matches one of the historic 310 * filesystem types. 311 */ 312 u_long fsindex = (u_long)fstype; 313 if (fsindex >= nmountcompatnames || 314 mountcompatnames[fsindex] == NULL) 315 return ENODEV; 316 strlcpy(fstypename, mountcompatnames[fsindex], 317 sizeof(fstypename)); 318 } 319 320 /* Accept `ufs' as an alias for `ffs', for compatibility. */ 321 if (strcmp(fstypename, "ufs") == 0) 322 fstypename[0] = 'f'; 323 324 if ((*vfsops = vfs_getopsbyname(fstypename)) != NULL) 325 return 0; 326 327 /* If we can autoload a vfs module, try again */ 328 (void)module_autoload(fstypename, MODULE_CLASS_VFS); 329 330 if ((*vfsops = vfs_getopsbyname(fstypename)) != NULL) 331 return 0; 332 333 return ENODEV; 334 } 335 336 static int 337 mount_getargs(struct lwp *l, struct vnode *vp, const char *path, int flags, 338 void *data, size_t *data_len) 339 { 340 struct mount *mp; 341 int error; 342 343 /* If MNT_GETARGS is specified, it should be the only flag. */ 344 if (flags & ~MNT_GETARGS) 345 return EINVAL; 346 347 mp = vp->v_mount; 348 349 /* XXX: probably some notion of "can see" here if we want isolation. */ 350 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT, 351 KAUTH_REQ_SYSTEM_MOUNT_GET, mp, data, NULL); 352 if (error) 353 return error; 354 355 if ((vp->v_vflag & VV_ROOT) == 0) 356 return EINVAL; 357 358 if (vfs_busy(mp, NULL)) 359 return EPERM; 360 361 mutex_enter(&mp->mnt_updating); 362 mp->mnt_flag &= ~MNT_OP_FLAGS; 363 mp->mnt_flag |= MNT_GETARGS; 364 error = VFS_MOUNT(mp, path, data, data_len); 365 mp->mnt_flag &= ~MNT_OP_FLAGS; 366 mutex_exit(&mp->mnt_updating); 367 368 vfs_unbusy(mp, false, NULL); 369 return (error); 370 } 371 372 int 373 sys___mount50(struct lwp *l, const struct sys___mount50_args *uap, register_t *retval) 374 { 375 /* { 376 syscallarg(const char *) type; 377 syscallarg(const char *) path; 378 syscallarg(int) flags; 379 syscallarg(void *) data; 380 syscallarg(size_t) data_len; 381 } */ 382 383 return do_sys_mount(l, NULL, SCARG(uap, type), SCARG(uap, path), 384 SCARG(uap, flags), SCARG(uap, data), UIO_USERSPACE, 385 SCARG(uap, data_len), retval); 386 } 387 388 int 389 do_sys_mount(struct lwp *l, struct vfsops *vfsops, const char *type, 390 const char *path, int flags, void *data, enum uio_seg data_seg, 391 size_t data_len, register_t *retval) 392 { 393 struct vnode *vp; 394 void *data_buf = data; 395 bool vfsopsrele = false; 396 int error; 397 398 /* XXX: The calling convention of this routine is totally bizarre */ 399 if (vfsops) 400 vfsopsrele = true; 401 402 /* 403 * Get vnode to be covered 404 */ 405 error = namei_simple_user(path, NSM_FOLLOW_TRYEMULROOT, &vp); 406 if (error != 0) { 407 vp = NULL; 408 goto done; 409 } 410 411 if (vfsops == NULL) { 412 if (flags & (MNT_GETARGS | MNT_UPDATE)) { 413 vfsops = vp->v_mount->mnt_op; 414 } else { 415 /* 'type' is userspace */ 416 error = mount_get_vfsops(type, &vfsops); 417 if (error != 0) 418 goto done; 419 vfsopsrele = true; 420 } 421 } 422 423 if (data != NULL && data_seg == UIO_USERSPACE) { 424 if (data_len == 0) { 425 /* No length supplied, use default for filesystem */ 426 data_len = vfsops->vfs_min_mount_data; 427 if (data_len > VFS_MAX_MOUNT_DATA) { 428 error = EINVAL; 429 goto done; 430 } 431 /* 432 * Hopefully a longer buffer won't make copyin() fail. 433 * For compatibility with 3.0 and earlier. 434 */ 435 if (flags & MNT_UPDATE 436 && data_len < sizeof (struct mnt_export_args30)) 437 data_len = sizeof (struct mnt_export_args30); 438 } 439 data_buf = kmem_alloc(data_len, KM_SLEEP); 440 441 /* NFS needs the buffer even for mnt_getargs .... */ 442 error = copyin(data, data_buf, data_len); 443 if (error != 0) 444 goto done; 445 } 446 447 if (flags & MNT_GETARGS) { 448 if (data_len == 0) { 449 error = EINVAL; 450 goto done; 451 } 452 error = mount_getargs(l, vp, path, flags, data_buf, &data_len); 453 if (error != 0) 454 goto done; 455 if (data_seg == UIO_USERSPACE) 456 error = copyout(data_buf, data, data_len); 457 *retval = data_len; 458 } else if (flags & MNT_UPDATE) { 459 error = mount_update(l, vp, path, flags, data_buf, &data_len); 460 } else { 461 /* Locking is handled internally in mount_domount(). */ 462 KASSERT(vfsopsrele == true); 463 error = mount_domount(l, &vp, vfsops, path, flags, data_buf, 464 &data_len); 465 vfsopsrele = false; 466 467 if ((error == 0) && (flags & MNT_EXTATTR)) { 468 if (VFS_EXTATTRCTL(vp->v_mount, EXTATTR_CMD_START, 469 NULL, 0, NULL) != 0) 470 printf("%s: failed to start extattr", 471 vp->v_mount->mnt_stat.f_mntonname); 472 /* XXX remove flag */ 473 } 474 } 475 476 done: 477 if (vfsopsrele) 478 vfs_delref(vfsops); 479 if (vp != NULL) { 480 vrele(vp); 481 } 482 if (data_buf != data) 483 kmem_free(data_buf, data_len); 484 return (error); 485 } 486 487 /* 488 * Unmount a file system. 489 * 490 * Note: unmount takes a path to the vnode mounted on as argument, 491 * not special file (as before). 492 */ 493 /* ARGSUSED */ 494 int 495 sys_unmount(struct lwp *l, const struct sys_unmount_args *uap, register_t *retval) 496 { 497 /* { 498 syscallarg(const char *) path; 499 syscallarg(int) flags; 500 } */ 501 struct vnode *vp; 502 struct mount *mp; 503 int error; 504 struct pathbuf *pb; 505 struct nameidata nd; 506 507 error = pathbuf_copyin(SCARG(uap, path), &pb); 508 if (error) { 509 return error; 510 } 511 512 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT, pb); 513 if ((error = namei(&nd)) != 0) { 514 pathbuf_destroy(pb); 515 return error; 516 } 517 vp = nd.ni_vp; 518 pathbuf_destroy(pb); 519 520 mp = vp->v_mount; 521 atomic_inc_uint(&mp->mnt_refcnt); 522 VOP_UNLOCK(vp); 523 524 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT, 525 KAUTH_REQ_SYSTEM_MOUNT_UNMOUNT, mp, NULL, NULL); 526 if (error) { 527 vrele(vp); 528 vfs_destroy(mp); 529 return (error); 530 } 531 532 /* 533 * Don't allow unmounting the root file system. 534 */ 535 if (mp->mnt_flag & MNT_ROOTFS) { 536 vrele(vp); 537 vfs_destroy(mp); 538 return (EINVAL); 539 } 540 541 /* 542 * Must be the root of the filesystem 543 */ 544 if ((vp->v_vflag & VV_ROOT) == 0) { 545 vrele(vp); 546 vfs_destroy(mp); 547 return (EINVAL); 548 } 549 550 vrele(vp); 551 error = dounmount(mp, SCARG(uap, flags), l); 552 vfs_destroy(mp); 553 return error; 554 } 555 556 /* 557 * Sync each mounted filesystem. 558 */ 559 #ifdef DEBUG 560 int syncprt = 0; 561 struct ctldebug debug0 = { "syncprt", &syncprt }; 562 #endif 563 564 void 565 do_sys_sync(struct lwp *l) 566 { 567 struct mount *mp, *nmp; 568 int asyncflag; 569 570 mutex_enter(&mountlist_lock); 571 for (mp = CIRCLEQ_FIRST(&mountlist); mp != (void *)&mountlist; 572 mp = nmp) { 573 if (vfs_busy(mp, &nmp)) { 574 continue; 575 } 576 mutex_enter(&mp->mnt_updating); 577 if ((mp->mnt_flag & MNT_RDONLY) == 0) { 578 asyncflag = mp->mnt_flag & MNT_ASYNC; 579 mp->mnt_flag &= ~MNT_ASYNC; 580 VFS_SYNC(mp, MNT_NOWAIT, l->l_cred); 581 if (asyncflag) 582 mp->mnt_flag |= MNT_ASYNC; 583 } 584 mutex_exit(&mp->mnt_updating); 585 vfs_unbusy(mp, false, &nmp); 586 } 587 mutex_exit(&mountlist_lock); 588 #ifdef DEBUG 589 if (syncprt) 590 vfs_bufstats(); 591 #endif /* DEBUG */ 592 } 593 594 /* ARGSUSED */ 595 int 596 sys_sync(struct lwp *l, const void *v, register_t *retval) 597 { 598 do_sys_sync(l); 599 return (0); 600 } 601 602 603 /* 604 * Access or change filesystem quotas. 605 * 606 * (this is really 14 different calls bundled into one) 607 */ 608 609 static int 610 do_sys_quotactl_stat(struct mount *mp, struct quotastat *info_u) 611 { 612 struct quotastat info_k; 613 int error; 614 615 /* ensure any padding bytes are cleared */ 616 memset(&info_k, 0, sizeof(info_k)); 617 618 error = vfs_quotactl_stat(mp, &info_k); 619 if (error) { 620 return error; 621 } 622 623 return copyout(&info_k, info_u, sizeof(info_k)); 624 } 625 626 static int 627 do_sys_quotactl_idtypestat(struct mount *mp, int idtype, 628 struct quotaidtypestat *info_u) 629 { 630 struct quotaidtypestat info_k; 631 int error; 632 633 /* ensure any padding bytes are cleared */ 634 memset(&info_k, 0, sizeof(info_k)); 635 636 error = vfs_quotactl_idtypestat(mp, idtype, &info_k); 637 if (error) { 638 return error; 639 } 640 641 return copyout(&info_k, info_u, sizeof(info_k)); 642 } 643 644 static int 645 do_sys_quotactl_objtypestat(struct mount *mp, int objtype, 646 struct quotaobjtypestat *info_u) 647 { 648 struct quotaobjtypestat info_k; 649 int error; 650 651 /* ensure any padding bytes are cleared */ 652 memset(&info_k, 0, sizeof(info_k)); 653 654 error = vfs_quotactl_objtypestat(mp, objtype, &info_k); 655 if (error) { 656 return error; 657 } 658 659 return copyout(&info_k, info_u, sizeof(info_k)); 660 } 661 662 static int 663 do_sys_quotactl_get(struct mount *mp, const struct quotakey *key_u, 664 struct quotaval *val_u) 665 { 666 struct quotakey key_k; 667 struct quotaval val_k; 668 int error; 669 670 /* ensure any padding bytes are cleared */ 671 memset(&val_k, 0, sizeof(val_k)); 672 673 error = copyin(key_u, &key_k, sizeof(key_k)); 674 if (error) { 675 return error; 676 } 677 678 error = vfs_quotactl_get(mp, &key_k, &val_k); 679 if (error) { 680 return error; 681 } 682 683 return copyout(&val_k, val_u, sizeof(val_k)); 684 } 685 686 static int 687 do_sys_quotactl_put(struct mount *mp, const struct quotakey *key_u, 688 const struct quotaval *val_u) 689 { 690 struct quotakey key_k; 691 struct quotaval val_k; 692 int error; 693 694 error = copyin(key_u, &key_k, sizeof(key_k)); 695 if (error) { 696 return error; 697 } 698 699 error = copyin(val_u, &val_k, sizeof(val_k)); 700 if (error) { 701 return error; 702 } 703 704 return vfs_quotactl_put(mp, &key_k, &val_k); 705 } 706 707 static int 708 do_sys_quotactl_delete(struct mount *mp, const struct quotakey *key_u) 709 { 710 struct quotakey key_k; 711 int error; 712 713 error = copyin(key_u, &key_k, sizeof(key_k)); 714 if (error) { 715 return error; 716 } 717 718 return vfs_quotactl_delete(mp, &key_k); 719 } 720 721 static int 722 do_sys_quotactl_cursoropen(struct mount *mp, struct quotakcursor *cursor_u) 723 { 724 struct quotakcursor cursor_k; 725 int error; 726 727 /* ensure any padding bytes are cleared */ 728 memset(&cursor_k, 0, sizeof(cursor_k)); 729 730 error = vfs_quotactl_cursoropen(mp, &cursor_k); 731 if (error) { 732 return error; 733 } 734 735 return copyout(&cursor_k, cursor_u, sizeof(cursor_k)); 736 } 737 738 static int 739 do_sys_quotactl_cursorclose(struct mount *mp, struct quotakcursor *cursor_u) 740 { 741 struct quotakcursor cursor_k; 742 int error; 743 744 error = copyin(cursor_u, &cursor_k, sizeof(cursor_k)); 745 if (error) { 746 return error; 747 } 748 749 return vfs_quotactl_cursorclose(mp, &cursor_k); 750 } 751 752 static int 753 do_sys_quotactl_cursorskipidtype(struct mount *mp, 754 struct quotakcursor *cursor_u, int idtype) 755 { 756 struct quotakcursor cursor_k; 757 int error; 758 759 error = copyin(cursor_u, &cursor_k, sizeof(cursor_k)); 760 if (error) { 761 return error; 762 } 763 764 error = vfs_quotactl_cursorskipidtype(mp, &cursor_k, idtype); 765 if (error) { 766 return error; 767 } 768 769 return copyout(&cursor_k, cursor_u, sizeof(cursor_k)); 770 } 771 772 static int 773 do_sys_quotactl_cursorget(struct mount *mp, struct quotakcursor *cursor_u, 774 struct quotakey *keys_u, struct quotaval *vals_u, unsigned maxnum, 775 unsigned *ret_u) 776 { 777 #define CGET_STACK_MAX 8 778 struct quotakcursor cursor_k; 779 struct quotakey stackkeys[CGET_STACK_MAX]; 780 struct quotaval stackvals[CGET_STACK_MAX]; 781 struct quotakey *keys_k; 782 struct quotaval *vals_k; 783 unsigned ret_k; 784 int error; 785 786 if (maxnum > 128) { 787 maxnum = 128; 788 } 789 790 error = copyin(cursor_u, &cursor_k, sizeof(cursor_k)); 791 if (error) { 792 return error; 793 } 794 795 if (maxnum <= CGET_STACK_MAX) { 796 keys_k = stackkeys; 797 vals_k = stackvals; 798 /* ensure any padding bytes are cleared */ 799 memset(keys_k, 0, maxnum * sizeof(keys_k[0])); 800 memset(vals_k, 0, maxnum * sizeof(vals_k[0])); 801 } else { 802 keys_k = kmem_zalloc(maxnum * sizeof(keys_k[0]), KM_SLEEP); 803 vals_k = kmem_zalloc(maxnum * sizeof(vals_k[0]), KM_SLEEP); 804 } 805 806 error = vfs_quotactl_cursorget(mp, &cursor_k, keys_k, vals_k, maxnum, 807 &ret_k); 808 if (error) { 809 goto fail; 810 } 811 812 error = copyout(keys_k, keys_u, ret_k * sizeof(keys_k[0])); 813 if (error) { 814 goto fail; 815 } 816 817 error = copyout(vals_k, vals_u, ret_k * sizeof(vals_k[0])); 818 if (error) { 819 goto fail; 820 } 821 822 error = copyout(&ret_k, ret_u, sizeof(ret_k)); 823 if (error) { 824 goto fail; 825 } 826 827 /* do last to maximize the chance of being able to recover a failure */ 828 error = copyout(&cursor_k, cursor_u, sizeof(cursor_k)); 829 830 fail: 831 if (keys_k != stackkeys) { 832 kmem_free(keys_k, maxnum * sizeof(keys_k[0])); 833 } 834 if (vals_k != stackvals) { 835 kmem_free(vals_k, maxnum * sizeof(vals_k[0])); 836 } 837 return error; 838 } 839 840 static int 841 do_sys_quotactl_cursoratend(struct mount *mp, struct quotakcursor *cursor_u, 842 int *ret_u) 843 { 844 struct quotakcursor cursor_k; 845 int ret_k; 846 int error; 847 848 error = copyin(cursor_u, &cursor_k, sizeof(cursor_k)); 849 if (error) { 850 return error; 851 } 852 853 error = vfs_quotactl_cursoratend(mp, &cursor_k, &ret_k); 854 if (error) { 855 return error; 856 } 857 858 error = copyout(&ret_k, ret_u, sizeof(ret_k)); 859 if (error) { 860 return error; 861 } 862 863 return copyout(&cursor_k, cursor_u, sizeof(cursor_k)); 864 } 865 866 static int 867 do_sys_quotactl_cursorrewind(struct mount *mp, struct quotakcursor *cursor_u) 868 { 869 struct quotakcursor cursor_k; 870 int error; 871 872 error = copyin(cursor_u, &cursor_k, sizeof(cursor_k)); 873 if (error) { 874 return error; 875 } 876 877 error = vfs_quotactl_cursorrewind(mp, &cursor_k); 878 if (error) { 879 return error; 880 } 881 882 return copyout(&cursor_k, cursor_u, sizeof(cursor_k)); 883 } 884 885 static int 886 do_sys_quotactl_quotaon(struct mount *mp, int idtype, const char *path_u) 887 { 888 char *path_k; 889 int error; 890 891 /* XXX this should probably be a struct pathbuf */ 892 path_k = PNBUF_GET(); 893 error = copyin(path_u, path_k, PATH_MAX); 894 if (error) { 895 PNBUF_PUT(path_k); 896 return error; 897 } 898 899 error = vfs_quotactl_quotaon(mp, idtype, path_k); 900 901 PNBUF_PUT(path_k); 902 return error; 903 } 904 905 static int 906 do_sys_quotactl_quotaoff(struct mount *mp, int idtype) 907 { 908 return vfs_quotactl_quotaoff(mp, idtype); 909 } 910 911 int 912 do_sys_quotactl(const char *path_u, const struct quotactl_args *args) 913 { 914 struct mount *mp; 915 struct vnode *vp; 916 int error; 917 918 error = namei_simple_user(path_u, NSM_FOLLOW_TRYEMULROOT, &vp); 919 if (error != 0) 920 return (error); 921 mp = vp->v_mount; 922 923 switch (args->qc_op) { 924 case QUOTACTL_STAT: 925 error = do_sys_quotactl_stat(mp, args->u.stat.qc_info); 926 break; 927 case QUOTACTL_IDTYPESTAT: 928 error = do_sys_quotactl_idtypestat(mp, 929 args->u.idtypestat.qc_idtype, 930 args->u.idtypestat.qc_info); 931 break; 932 case QUOTACTL_OBJTYPESTAT: 933 error = do_sys_quotactl_objtypestat(mp, 934 args->u.objtypestat.qc_objtype, 935 args->u.objtypestat.qc_info); 936 break; 937 case QUOTACTL_GET: 938 error = do_sys_quotactl_get(mp, 939 args->u.get.qc_key, 940 args->u.get.qc_val); 941 break; 942 case QUOTACTL_PUT: 943 error = do_sys_quotactl_put(mp, 944 args->u.put.qc_key, 945 args->u.put.qc_val); 946 break; 947 case QUOTACTL_DELETE: 948 error = do_sys_quotactl_delete(mp, args->u.delete.qc_key); 949 break; 950 case QUOTACTL_CURSOROPEN: 951 error = do_sys_quotactl_cursoropen(mp, 952 args->u.cursoropen.qc_cursor); 953 break; 954 case QUOTACTL_CURSORCLOSE: 955 error = do_sys_quotactl_cursorclose(mp, 956 args->u.cursorclose.qc_cursor); 957 break; 958 case QUOTACTL_CURSORSKIPIDTYPE: 959 error = do_sys_quotactl_cursorskipidtype(mp, 960 args->u.cursorskipidtype.qc_cursor, 961 args->u.cursorskipidtype.qc_idtype); 962 break; 963 case QUOTACTL_CURSORGET: 964 error = do_sys_quotactl_cursorget(mp, 965 args->u.cursorget.qc_cursor, 966 args->u.cursorget.qc_keys, 967 args->u.cursorget.qc_vals, 968 args->u.cursorget.qc_maxnum, 969 args->u.cursorget.qc_ret); 970 break; 971 case QUOTACTL_CURSORATEND: 972 error = do_sys_quotactl_cursoratend(mp, 973 args->u.cursoratend.qc_cursor, 974 args->u.cursoratend.qc_ret); 975 break; 976 case QUOTACTL_CURSORREWIND: 977 error = do_sys_quotactl_cursorrewind(mp, 978 args->u.cursorrewind.qc_cursor); 979 break; 980 case QUOTACTL_QUOTAON: 981 error = do_sys_quotactl_quotaon(mp, 982 args->u.quotaon.qc_idtype, 983 args->u.quotaon.qc_quotafile); 984 break; 985 case QUOTACTL_QUOTAOFF: 986 error = do_sys_quotactl_quotaoff(mp, 987 args->u.quotaoff.qc_idtype); 988 break; 989 default: 990 error = EINVAL; 991 break; 992 } 993 994 vrele(vp); 995 return error; 996 } 997 998 /* ARGSUSED */ 999 int 1000 sys___quotactl(struct lwp *l, const struct sys___quotactl_args *uap, 1001 register_t *retval) 1002 { 1003 /* { 1004 syscallarg(const char *) path; 1005 syscallarg(struct quotactl_args *) args; 1006 } */ 1007 struct quotactl_args args; 1008 int error; 1009 1010 error = copyin(SCARG(uap, args), &args, sizeof(args)); 1011 if (error) { 1012 return error; 1013 } 1014 1015 return do_sys_quotactl(SCARG(uap, path), &args); 1016 } 1017 1018 int 1019 dostatvfs(struct mount *mp, struct statvfs *sp, struct lwp *l, int flags, 1020 int root) 1021 { 1022 struct cwdinfo *cwdi = l->l_proc->p_cwdi; 1023 int error = 0; 1024 1025 /* 1026 * If MNT_NOWAIT or MNT_LAZY is specified, do not 1027 * refresh the fsstat cache. MNT_WAIT or MNT_LAZY 1028 * overrides MNT_NOWAIT. 1029 */ 1030 if (flags == MNT_NOWAIT || flags == MNT_LAZY || 1031 (flags != MNT_WAIT && flags != 0)) { 1032 memcpy(sp, &mp->mnt_stat, sizeof(*sp)); 1033 goto done; 1034 } 1035 1036 /* Get the filesystem stats now */ 1037 memset(sp, 0, sizeof(*sp)); 1038 if ((error = VFS_STATVFS(mp, sp)) != 0) { 1039 return error; 1040 } 1041 1042 if (cwdi->cwdi_rdir == NULL) 1043 (void)memcpy(&mp->mnt_stat, sp, sizeof(mp->mnt_stat)); 1044 done: 1045 if (cwdi->cwdi_rdir != NULL) { 1046 size_t len; 1047 char *bp; 1048 char c; 1049 char *path = PNBUF_GET(); 1050 1051 bp = path + MAXPATHLEN; 1052 *--bp = '\0'; 1053 rw_enter(&cwdi->cwdi_lock, RW_READER); 1054 error = getcwd_common(cwdi->cwdi_rdir, rootvnode, &bp, path, 1055 MAXPATHLEN / 2, 0, l); 1056 rw_exit(&cwdi->cwdi_lock); 1057 if (error) { 1058 PNBUF_PUT(path); 1059 return error; 1060 } 1061 len = strlen(bp); 1062 if (len != 1) { 1063 /* 1064 * for mount points that are below our root, we can see 1065 * them, so we fix up the pathname and return them. The 1066 * rest we cannot see, so we don't allow viewing the 1067 * data. 1068 */ 1069 if (strncmp(bp, sp->f_mntonname, len) == 0 && 1070 ((c = sp->f_mntonname[len]) == '/' || c == '\0')) { 1071 (void)strlcpy(sp->f_mntonname, 1072 c == '\0' ? "/" : &sp->f_mntonname[len], 1073 sizeof(sp->f_mntonname)); 1074 } else { 1075 if (root) 1076 (void)strlcpy(sp->f_mntonname, "/", 1077 sizeof(sp->f_mntonname)); 1078 else 1079 error = EPERM; 1080 } 1081 } 1082 PNBUF_PUT(path); 1083 } 1084 sp->f_flag = mp->mnt_flag & MNT_VISFLAGMASK; 1085 return error; 1086 } 1087 1088 /* 1089 * Get filesystem statistics by path. 1090 */ 1091 int 1092 do_sys_pstatvfs(struct lwp *l, const char *path, int flags, struct statvfs *sb) 1093 { 1094 struct mount *mp; 1095 int error; 1096 struct vnode *vp; 1097 1098 error = namei_simple_user(path, NSM_FOLLOW_TRYEMULROOT, &vp); 1099 if (error != 0) 1100 return error; 1101 mp = vp->v_mount; 1102 error = dostatvfs(mp, sb, l, flags, 1); 1103 vrele(vp); 1104 return error; 1105 } 1106 1107 /* ARGSUSED */ 1108 int 1109 sys_statvfs1(struct lwp *l, const struct sys_statvfs1_args *uap, register_t *retval) 1110 { 1111 /* { 1112 syscallarg(const char *) path; 1113 syscallarg(struct statvfs *) buf; 1114 syscallarg(int) flags; 1115 } */ 1116 struct statvfs *sb; 1117 int error; 1118 1119 sb = STATVFSBUF_GET(); 1120 error = do_sys_pstatvfs(l, SCARG(uap, path), SCARG(uap, flags), sb); 1121 if (error == 0) 1122 error = copyout(sb, SCARG(uap, buf), sizeof(*sb)); 1123 STATVFSBUF_PUT(sb); 1124 return error; 1125 } 1126 1127 /* 1128 * Get filesystem statistics by fd. 1129 */ 1130 int 1131 do_sys_fstatvfs(struct lwp *l, int fd, int flags, struct statvfs *sb) 1132 { 1133 file_t *fp; 1134 struct mount *mp; 1135 int error; 1136 1137 /* fd_getvnode() will use the descriptor for us */ 1138 if ((error = fd_getvnode(fd, &fp)) != 0) 1139 return (error); 1140 mp = ((struct vnode *)fp->f_data)->v_mount; 1141 error = dostatvfs(mp, sb, curlwp, flags, 1); 1142 fd_putfile(fd); 1143 return error; 1144 } 1145 1146 /* ARGSUSED */ 1147 int 1148 sys_fstatvfs1(struct lwp *l, const struct sys_fstatvfs1_args *uap, register_t *retval) 1149 { 1150 /* { 1151 syscallarg(int) fd; 1152 syscallarg(struct statvfs *) buf; 1153 syscallarg(int) flags; 1154 } */ 1155 struct statvfs *sb; 1156 int error; 1157 1158 sb = STATVFSBUF_GET(); 1159 error = do_sys_fstatvfs(l, SCARG(uap, fd), SCARG(uap, flags), sb); 1160 if (error == 0) 1161 error = copyout(sb, SCARG(uap, buf), sizeof(*sb)); 1162 STATVFSBUF_PUT(sb); 1163 return error; 1164 } 1165 1166 1167 /* 1168 * Get statistics on all filesystems. 1169 */ 1170 int 1171 do_sys_getvfsstat(struct lwp *l, void *sfsp, size_t bufsize, int flags, 1172 int (*copyfn)(const void *, void *, size_t), size_t entry_sz, 1173 register_t *retval) 1174 { 1175 int root = 0; 1176 struct proc *p = l->l_proc; 1177 struct mount *mp, *nmp; 1178 struct statvfs *sb; 1179 size_t count, maxcount; 1180 int error = 0; 1181 1182 sb = STATVFSBUF_GET(); 1183 maxcount = bufsize / entry_sz; 1184 mutex_enter(&mountlist_lock); 1185 count = 0; 1186 for (mp = CIRCLEQ_FIRST(&mountlist); mp != (void *)&mountlist; 1187 mp = nmp) { 1188 if (vfs_busy(mp, &nmp)) { 1189 continue; 1190 } 1191 if (sfsp && count < maxcount) { 1192 error = dostatvfs(mp, sb, l, flags, 0); 1193 if (error) { 1194 vfs_unbusy(mp, false, &nmp); 1195 error = 0; 1196 continue; 1197 } 1198 error = copyfn(sb, sfsp, entry_sz); 1199 if (error) { 1200 vfs_unbusy(mp, false, NULL); 1201 goto out; 1202 } 1203 sfsp = (char *)sfsp + entry_sz; 1204 root |= strcmp(sb->f_mntonname, "/") == 0; 1205 } 1206 count++; 1207 vfs_unbusy(mp, false, &nmp); 1208 } 1209 mutex_exit(&mountlist_lock); 1210 1211 if (root == 0 && p->p_cwdi->cwdi_rdir) { 1212 /* 1213 * fake a root entry 1214 */ 1215 error = dostatvfs(p->p_cwdi->cwdi_rdir->v_mount, 1216 sb, l, flags, 1); 1217 if (error != 0) 1218 goto out; 1219 if (sfsp) { 1220 error = copyfn(sb, sfsp, entry_sz); 1221 if (error != 0) 1222 goto out; 1223 } 1224 count++; 1225 } 1226 if (sfsp && count > maxcount) 1227 *retval = maxcount; 1228 else 1229 *retval = count; 1230 out: 1231 STATVFSBUF_PUT(sb); 1232 return error; 1233 } 1234 1235 int 1236 sys_getvfsstat(struct lwp *l, const struct sys_getvfsstat_args *uap, register_t *retval) 1237 { 1238 /* { 1239 syscallarg(struct statvfs *) buf; 1240 syscallarg(size_t) bufsize; 1241 syscallarg(int) flags; 1242 } */ 1243 1244 return do_sys_getvfsstat(l, SCARG(uap, buf), SCARG(uap, bufsize), 1245 SCARG(uap, flags), copyout, sizeof (struct statvfs), retval); 1246 } 1247 1248 /* 1249 * Change current working directory to a given file descriptor. 1250 */ 1251 /* ARGSUSED */ 1252 int 1253 sys_fchdir(struct lwp *l, const struct sys_fchdir_args *uap, register_t *retval) 1254 { 1255 /* { 1256 syscallarg(int) fd; 1257 } */ 1258 struct proc *p = l->l_proc; 1259 struct cwdinfo *cwdi; 1260 struct vnode *vp, *tdp; 1261 struct mount *mp; 1262 file_t *fp; 1263 int error, fd; 1264 1265 /* fd_getvnode() will use the descriptor for us */ 1266 fd = SCARG(uap, fd); 1267 if ((error = fd_getvnode(fd, &fp)) != 0) 1268 return (error); 1269 vp = fp->f_data; 1270 1271 vref(vp); 1272 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 1273 if (vp->v_type != VDIR) 1274 error = ENOTDIR; 1275 else 1276 error = VOP_ACCESS(vp, VEXEC, l->l_cred); 1277 if (error) { 1278 vput(vp); 1279 goto out; 1280 } 1281 while ((mp = vp->v_mountedhere) != NULL) { 1282 error = vfs_busy(mp, NULL); 1283 vput(vp); 1284 if (error != 0) 1285 goto out; 1286 error = VFS_ROOT(mp, &tdp); 1287 vfs_unbusy(mp, false, NULL); 1288 if (error) 1289 goto out; 1290 vp = tdp; 1291 } 1292 VOP_UNLOCK(vp); 1293 1294 /* 1295 * Disallow changing to a directory not under the process's 1296 * current root directory (if there is one). 1297 */ 1298 cwdi = p->p_cwdi; 1299 rw_enter(&cwdi->cwdi_lock, RW_WRITER); 1300 if (cwdi->cwdi_rdir && !vn_isunder(vp, NULL, l)) { 1301 vrele(vp); 1302 error = EPERM; /* operation not permitted */ 1303 } else { 1304 vrele(cwdi->cwdi_cdir); 1305 cwdi->cwdi_cdir = vp; 1306 } 1307 rw_exit(&cwdi->cwdi_lock); 1308 1309 out: 1310 fd_putfile(fd); 1311 return (error); 1312 } 1313 1314 /* 1315 * Change this process's notion of the root directory to a given file 1316 * descriptor. 1317 */ 1318 int 1319 sys_fchroot(struct lwp *l, const struct sys_fchroot_args *uap, register_t *retval) 1320 { 1321 struct proc *p = l->l_proc; 1322 struct vnode *vp; 1323 file_t *fp; 1324 int error, fd = SCARG(uap, fd); 1325 1326 if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_CHROOT, 1327 KAUTH_REQ_SYSTEM_CHROOT_FCHROOT, NULL, NULL, NULL)) != 0) 1328 return error; 1329 /* fd_getvnode() will use the descriptor for us */ 1330 if ((error = fd_getvnode(fd, &fp)) != 0) 1331 return error; 1332 vp = fp->f_data; 1333 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 1334 if (vp->v_type != VDIR) 1335 error = ENOTDIR; 1336 else 1337 error = VOP_ACCESS(vp, VEXEC, l->l_cred); 1338 VOP_UNLOCK(vp); 1339 if (error) 1340 goto out; 1341 vref(vp); 1342 1343 change_root(p->p_cwdi, vp, l); 1344 1345 out: 1346 fd_putfile(fd); 1347 return (error); 1348 } 1349 1350 /* 1351 * Change current working directory (``.''). 1352 */ 1353 /* ARGSUSED */ 1354 int 1355 sys_chdir(struct lwp *l, const struct sys_chdir_args *uap, register_t *retval) 1356 { 1357 /* { 1358 syscallarg(const char *) path; 1359 } */ 1360 struct proc *p = l->l_proc; 1361 struct cwdinfo *cwdi; 1362 int error; 1363 struct vnode *vp; 1364 1365 if ((error = chdir_lookup(SCARG(uap, path), UIO_USERSPACE, 1366 &vp, l)) != 0) 1367 return (error); 1368 cwdi = p->p_cwdi; 1369 rw_enter(&cwdi->cwdi_lock, RW_WRITER); 1370 vrele(cwdi->cwdi_cdir); 1371 cwdi->cwdi_cdir = vp; 1372 rw_exit(&cwdi->cwdi_lock); 1373 return (0); 1374 } 1375 1376 /* 1377 * Change notion of root (``/'') directory. 1378 */ 1379 /* ARGSUSED */ 1380 int 1381 sys_chroot(struct lwp *l, const struct sys_chroot_args *uap, register_t *retval) 1382 { 1383 /* { 1384 syscallarg(const char *) path; 1385 } */ 1386 struct proc *p = l->l_proc; 1387 int error; 1388 struct vnode *vp; 1389 1390 if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_CHROOT, 1391 KAUTH_REQ_SYSTEM_CHROOT_CHROOT, NULL, NULL, NULL)) != 0) 1392 return (error); 1393 if ((error = chdir_lookup(SCARG(uap, path), UIO_USERSPACE, 1394 &vp, l)) != 0) 1395 return (error); 1396 1397 change_root(p->p_cwdi, vp, l); 1398 1399 return (0); 1400 } 1401 1402 /* 1403 * Common routine for chroot and fchroot. 1404 * NB: callers need to properly authorize the change root operation. 1405 */ 1406 void 1407 change_root(struct cwdinfo *cwdi, struct vnode *vp, struct lwp *l) 1408 { 1409 1410 rw_enter(&cwdi->cwdi_lock, RW_WRITER); 1411 if (cwdi->cwdi_rdir != NULL) 1412 vrele(cwdi->cwdi_rdir); 1413 cwdi->cwdi_rdir = vp; 1414 1415 /* 1416 * Prevent escaping from chroot by putting the root under 1417 * the working directory. Silently chdir to / if we aren't 1418 * already there. 1419 */ 1420 if (!vn_isunder(cwdi->cwdi_cdir, vp, l)) { 1421 /* 1422 * XXX would be more failsafe to change directory to a 1423 * deadfs node here instead 1424 */ 1425 vrele(cwdi->cwdi_cdir); 1426 vref(vp); 1427 cwdi->cwdi_cdir = vp; 1428 } 1429 rw_exit(&cwdi->cwdi_lock); 1430 } 1431 1432 /* 1433 * Common routine for chroot and chdir. 1434 * XXX "where" should be enum uio_seg 1435 */ 1436 int 1437 chdir_lookup(const char *path, int where, struct vnode **vpp, struct lwp *l) 1438 { 1439 struct pathbuf *pb; 1440 struct nameidata nd; 1441 int error; 1442 1443 error = pathbuf_maybe_copyin(path, where, &pb); 1444 if (error) { 1445 return error; 1446 } 1447 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT, pb); 1448 if ((error = namei(&nd)) != 0) { 1449 pathbuf_destroy(pb); 1450 return error; 1451 } 1452 *vpp = nd.ni_vp; 1453 pathbuf_destroy(pb); 1454 1455 if ((*vpp)->v_type != VDIR) 1456 error = ENOTDIR; 1457 else 1458 error = VOP_ACCESS(*vpp, VEXEC, l->l_cred); 1459 1460 if (error) 1461 vput(*vpp); 1462 else 1463 VOP_UNLOCK(*vpp); 1464 return (error); 1465 } 1466 1467 /* 1468 * Internals of sys_open - path has already been converted into a pathbuf 1469 * (so we can easily reuse this function from other parts of the kernel, 1470 * like posix_spawn post-processing). 1471 */ 1472 static int 1473 do_open(lwp_t *l, struct pathbuf *pb, int open_flags, int open_mode, int *fd) 1474 { 1475 struct proc *p = l->l_proc; 1476 struct cwdinfo *cwdi = p->p_cwdi; 1477 file_t *fp; 1478 struct vnode *vp; 1479 int flags, cmode; 1480 int indx, error; 1481 struct nameidata nd; 1482 1483 flags = FFLAGS(open_flags); 1484 if ((flags & (FREAD | FWRITE)) == 0) 1485 return EINVAL; 1486 1487 if ((error = fd_allocfile(&fp, &indx)) != 0) { 1488 pathbuf_destroy(pb); 1489 return error; 1490 } 1491 /* We're going to read cwdi->cwdi_cmask unlocked here. */ 1492 cmode = ((open_mode &~ cwdi->cwdi_cmask) & ALLPERMS) &~ S_ISTXT; 1493 NDINIT(&nd, LOOKUP, FOLLOW | TRYEMULROOT, pb); 1494 l->l_dupfd = -indx - 1; /* XXX check for fdopen */ 1495 if ((error = vn_open(&nd, flags, cmode)) != 0) { 1496 fd_abort(p, fp, indx); 1497 if ((error == EDUPFD || error == EMOVEFD) && 1498 l->l_dupfd >= 0 && /* XXX from fdopen */ 1499 (error = 1500 fd_dupopen(l->l_dupfd, &indx, flags, error)) == 0) { 1501 *fd = indx; 1502 pathbuf_destroy(pb); 1503 return (0); 1504 } 1505 if (error == ERESTART) 1506 error = EINTR; 1507 pathbuf_destroy(pb); 1508 return error; 1509 } 1510 1511 l->l_dupfd = 0; 1512 vp = nd.ni_vp; 1513 pathbuf_destroy(pb); 1514 1515 if ((error = open_setfp(l, fp, vp, indx, flags))) 1516 return error; 1517 1518 VOP_UNLOCK(vp); 1519 *fd = indx; 1520 fd_affix(p, fp, indx); 1521 return 0; 1522 } 1523 1524 int 1525 fd_open(const char *path, int open_flags, int open_mode, int *fd) 1526 { 1527 struct pathbuf *pb; 1528 int oflags; 1529 1530 oflags = FFLAGS(open_flags); 1531 if ((oflags & (FREAD | FWRITE)) == 0) 1532 return EINVAL; 1533 1534 pb = pathbuf_create(path); 1535 if (pb == NULL) 1536 return ENOMEM; 1537 1538 return do_open(curlwp, pb, open_flags, open_mode, fd); 1539 } 1540 1541 /* 1542 * Check permissions, allocate an open file structure, 1543 * and call the device open routine if any. 1544 */ 1545 int 1546 sys_open(struct lwp *l, const struct sys_open_args *uap, register_t *retval) 1547 { 1548 /* { 1549 syscallarg(const char *) path; 1550 syscallarg(int) flags; 1551 syscallarg(int) mode; 1552 } */ 1553 struct pathbuf *pb; 1554 int result, flags, error; 1555 1556 flags = FFLAGS(SCARG(uap, flags)); 1557 if ((flags & (FREAD | FWRITE)) == 0) 1558 return (EINVAL); 1559 1560 error = pathbuf_copyin(SCARG(uap, path), &pb); 1561 if (error) 1562 return error; 1563 1564 error = do_open(l, pb, SCARG(uap, flags), SCARG(uap, mode), &result); 1565 if (error) 1566 return error; 1567 1568 *retval = result; 1569 return 0; 1570 } 1571 1572 int 1573 sys_openat(struct lwp *l, const struct sys_openat_args *uap, register_t *retval) 1574 { 1575 /* { 1576 syscallarg(int) fd; 1577 syscallarg(const char *) path; 1578 syscallarg(int) flags; 1579 syscallarg(int) mode; 1580 } */ 1581 1582 return ENOSYS; 1583 } 1584 1585 static void 1586 vfs__fhfree(fhandle_t *fhp) 1587 { 1588 size_t fhsize; 1589 1590 if (fhp == NULL) { 1591 return; 1592 } 1593 fhsize = FHANDLE_SIZE(fhp); 1594 kmem_free(fhp, fhsize); 1595 } 1596 1597 /* 1598 * vfs_composefh: compose a filehandle. 1599 */ 1600 1601 int 1602 vfs_composefh(struct vnode *vp, fhandle_t *fhp, size_t *fh_size) 1603 { 1604 struct mount *mp; 1605 struct fid *fidp; 1606 int error; 1607 size_t needfhsize; 1608 size_t fidsize; 1609 1610 mp = vp->v_mount; 1611 fidp = NULL; 1612 if (*fh_size < FHANDLE_SIZE_MIN) { 1613 fidsize = 0; 1614 } else { 1615 fidsize = *fh_size - offsetof(fhandle_t, fh_fid); 1616 if (fhp != NULL) { 1617 memset(fhp, 0, *fh_size); 1618 fhp->fh_fsid = mp->mnt_stat.f_fsidx; 1619 fidp = &fhp->fh_fid; 1620 } 1621 } 1622 error = VFS_VPTOFH(vp, fidp, &fidsize); 1623 needfhsize = FHANDLE_SIZE_FROM_FILEID_SIZE(fidsize); 1624 if (error == 0 && *fh_size < needfhsize) { 1625 error = E2BIG; 1626 } 1627 *fh_size = needfhsize; 1628 return error; 1629 } 1630 1631 int 1632 vfs_composefh_alloc(struct vnode *vp, fhandle_t **fhpp) 1633 { 1634 struct mount *mp; 1635 fhandle_t *fhp; 1636 size_t fhsize; 1637 size_t fidsize; 1638 int error; 1639 1640 *fhpp = NULL; 1641 mp = vp->v_mount; 1642 fidsize = 0; 1643 error = VFS_VPTOFH(vp, NULL, &fidsize); 1644 KASSERT(error != 0); 1645 if (error != E2BIG) { 1646 goto out; 1647 } 1648 fhsize = FHANDLE_SIZE_FROM_FILEID_SIZE(fidsize); 1649 fhp = kmem_zalloc(fhsize, KM_SLEEP); 1650 if (fhp == NULL) { 1651 error = ENOMEM; 1652 goto out; 1653 } 1654 fhp->fh_fsid = mp->mnt_stat.f_fsidx; 1655 error = VFS_VPTOFH(vp, &fhp->fh_fid, &fidsize); 1656 if (error == 0) { 1657 KASSERT((FHANDLE_SIZE(fhp) == fhsize && 1658 FHANDLE_FILEID(fhp)->fid_len == fidsize)); 1659 *fhpp = fhp; 1660 } else { 1661 kmem_free(fhp, fhsize); 1662 } 1663 out: 1664 return error; 1665 } 1666 1667 void 1668 vfs_composefh_free(fhandle_t *fhp) 1669 { 1670 1671 vfs__fhfree(fhp); 1672 } 1673 1674 /* 1675 * vfs_fhtovp: lookup a vnode by a filehandle. 1676 */ 1677 1678 int 1679 vfs_fhtovp(fhandle_t *fhp, struct vnode **vpp) 1680 { 1681 struct mount *mp; 1682 int error; 1683 1684 *vpp = NULL; 1685 mp = vfs_getvfs(FHANDLE_FSID(fhp)); 1686 if (mp == NULL) { 1687 error = ESTALE; 1688 goto out; 1689 } 1690 if (mp->mnt_op->vfs_fhtovp == NULL) { 1691 error = EOPNOTSUPP; 1692 goto out; 1693 } 1694 error = VFS_FHTOVP(mp, FHANDLE_FILEID(fhp), vpp); 1695 out: 1696 return error; 1697 } 1698 1699 /* 1700 * vfs_copyinfh_alloc: allocate and copyin a filehandle, given 1701 * the needed size. 1702 */ 1703 1704 int 1705 vfs_copyinfh_alloc(const void *ufhp, size_t fhsize, fhandle_t **fhpp) 1706 { 1707 fhandle_t *fhp; 1708 int error; 1709 1710 *fhpp = NULL; 1711 if (fhsize > FHANDLE_SIZE_MAX) { 1712 return EINVAL; 1713 } 1714 if (fhsize < FHANDLE_SIZE_MIN) { 1715 return EINVAL; 1716 } 1717 again: 1718 fhp = kmem_alloc(fhsize, KM_SLEEP); 1719 if (fhp == NULL) { 1720 return ENOMEM; 1721 } 1722 error = copyin(ufhp, fhp, fhsize); 1723 if (error == 0) { 1724 /* XXX this check shouldn't be here */ 1725 if (FHANDLE_SIZE(fhp) == fhsize) { 1726 *fhpp = fhp; 1727 return 0; 1728 } else if (fhsize == NFSX_V2FH && FHANDLE_SIZE(fhp) < fhsize) { 1729 /* 1730 * a kludge for nfsv2 padded handles. 1731 */ 1732 size_t sz; 1733 1734 sz = FHANDLE_SIZE(fhp); 1735 kmem_free(fhp, fhsize); 1736 fhsize = sz; 1737 goto again; 1738 } else { 1739 /* 1740 * userland told us wrong size. 1741 */ 1742 error = EINVAL; 1743 } 1744 } 1745 kmem_free(fhp, fhsize); 1746 return error; 1747 } 1748 1749 void 1750 vfs_copyinfh_free(fhandle_t *fhp) 1751 { 1752 1753 vfs__fhfree(fhp); 1754 } 1755 1756 /* 1757 * Get file handle system call 1758 */ 1759 int 1760 sys___getfh30(struct lwp *l, const struct sys___getfh30_args *uap, register_t *retval) 1761 { 1762 /* { 1763 syscallarg(char *) fname; 1764 syscallarg(fhandle_t *) fhp; 1765 syscallarg(size_t *) fh_size; 1766 } */ 1767 struct vnode *vp; 1768 fhandle_t *fh; 1769 int error; 1770 struct pathbuf *pb; 1771 struct nameidata nd; 1772 size_t sz; 1773 size_t usz; 1774 1775 /* 1776 * Must be super user 1777 */ 1778 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FILEHANDLE, 1779 0, NULL, NULL, NULL); 1780 if (error) 1781 return (error); 1782 1783 error = pathbuf_copyin(SCARG(uap, fname), &pb); 1784 if (error) { 1785 return error; 1786 } 1787 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT, pb); 1788 error = namei(&nd); 1789 if (error) { 1790 pathbuf_destroy(pb); 1791 return error; 1792 } 1793 vp = nd.ni_vp; 1794 pathbuf_destroy(pb); 1795 1796 error = vfs_composefh_alloc(vp, &fh); 1797 vput(vp); 1798 if (error != 0) { 1799 goto out; 1800 } 1801 error = copyin(SCARG(uap, fh_size), &usz, sizeof(size_t)); 1802 if (error != 0) { 1803 goto out; 1804 } 1805 sz = FHANDLE_SIZE(fh); 1806 error = copyout(&sz, SCARG(uap, fh_size), sizeof(size_t)); 1807 if (error != 0) { 1808 goto out; 1809 } 1810 if (usz >= sz) { 1811 error = copyout(fh, SCARG(uap, fhp), sz); 1812 } else { 1813 error = E2BIG; 1814 } 1815 out: 1816 vfs_composefh_free(fh); 1817 return (error); 1818 } 1819 1820 /* 1821 * Open a file given a file handle. 1822 * 1823 * Check permissions, allocate an open file structure, 1824 * and call the device open routine if any. 1825 */ 1826 1827 int 1828 dofhopen(struct lwp *l, const void *ufhp, size_t fhsize, int oflags, 1829 register_t *retval) 1830 { 1831 file_t *fp; 1832 struct vnode *vp = NULL; 1833 kauth_cred_t cred = l->l_cred; 1834 file_t *nfp; 1835 int indx, error = 0; 1836 struct vattr va; 1837 fhandle_t *fh; 1838 int flags; 1839 proc_t *p; 1840 1841 p = curproc; 1842 1843 /* 1844 * Must be super user 1845 */ 1846 if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FILEHANDLE, 1847 0, NULL, NULL, NULL))) 1848 return (error); 1849 1850 flags = FFLAGS(oflags); 1851 if ((flags & (FREAD | FWRITE)) == 0) 1852 return (EINVAL); 1853 if ((flags & O_CREAT)) 1854 return (EINVAL); 1855 if ((error = fd_allocfile(&nfp, &indx)) != 0) 1856 return (error); 1857 fp = nfp; 1858 error = vfs_copyinfh_alloc(ufhp, fhsize, &fh); 1859 if (error != 0) { 1860 goto bad; 1861 } 1862 error = vfs_fhtovp(fh, &vp); 1863 if (error != 0) { 1864 goto bad; 1865 } 1866 1867 /* Now do an effective vn_open */ 1868 1869 if (vp->v_type == VSOCK) { 1870 error = EOPNOTSUPP; 1871 goto bad; 1872 } 1873 error = vn_openchk(vp, cred, flags); 1874 if (error != 0) 1875 goto bad; 1876 if (flags & O_TRUNC) { 1877 VOP_UNLOCK(vp); /* XXX */ 1878 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); /* XXX */ 1879 vattr_null(&va); 1880 va.va_size = 0; 1881 error = VOP_SETATTR(vp, &va, cred); 1882 if (error) 1883 goto bad; 1884 } 1885 if ((error = VOP_OPEN(vp, flags, cred)) != 0) 1886 goto bad; 1887 if (flags & FWRITE) { 1888 mutex_enter(vp->v_interlock); 1889 vp->v_writecount++; 1890 mutex_exit(vp->v_interlock); 1891 } 1892 1893 /* done with modified vn_open, now finish what sys_open does. */ 1894 if ((error = open_setfp(l, fp, vp, indx, flags))) 1895 return error; 1896 1897 VOP_UNLOCK(vp); 1898 *retval = indx; 1899 fd_affix(p, fp, indx); 1900 vfs_copyinfh_free(fh); 1901 return (0); 1902 1903 bad: 1904 fd_abort(p, fp, indx); 1905 if (vp != NULL) 1906 vput(vp); 1907 vfs_copyinfh_free(fh); 1908 return (error); 1909 } 1910 1911 int 1912 sys___fhopen40(struct lwp *l, const struct sys___fhopen40_args *uap, register_t *retval) 1913 { 1914 /* { 1915 syscallarg(const void *) fhp; 1916 syscallarg(size_t) fh_size; 1917 syscallarg(int) flags; 1918 } */ 1919 1920 return dofhopen(l, SCARG(uap, fhp), SCARG(uap, fh_size), 1921 SCARG(uap, flags), retval); 1922 } 1923 1924 int 1925 do_fhstat(struct lwp *l, const void *ufhp, size_t fhsize, struct stat *sb) 1926 { 1927 int error; 1928 fhandle_t *fh; 1929 struct vnode *vp; 1930 1931 /* 1932 * Must be super user 1933 */ 1934 if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FILEHANDLE, 1935 0, NULL, NULL, NULL))) 1936 return (error); 1937 1938 error = vfs_copyinfh_alloc(ufhp, fhsize, &fh); 1939 if (error != 0) 1940 return error; 1941 1942 error = vfs_fhtovp(fh, &vp); 1943 vfs_copyinfh_free(fh); 1944 if (error != 0) 1945 return error; 1946 1947 error = vn_stat(vp, sb); 1948 vput(vp); 1949 return error; 1950 } 1951 1952 1953 /* ARGSUSED */ 1954 int 1955 sys___fhstat50(struct lwp *l, const struct sys___fhstat50_args *uap, register_t *retval) 1956 { 1957 /* { 1958 syscallarg(const void *) fhp; 1959 syscallarg(size_t) fh_size; 1960 syscallarg(struct stat *) sb; 1961 } */ 1962 struct stat sb; 1963 int error; 1964 1965 error = do_fhstat(l, SCARG(uap, fhp), SCARG(uap, fh_size), &sb); 1966 if (error) 1967 return error; 1968 return copyout(&sb, SCARG(uap, sb), sizeof(sb)); 1969 } 1970 1971 int 1972 do_fhstatvfs(struct lwp *l, const void *ufhp, size_t fhsize, struct statvfs *sb, 1973 int flags) 1974 { 1975 fhandle_t *fh; 1976 struct mount *mp; 1977 struct vnode *vp; 1978 int error; 1979 1980 /* 1981 * Must be super user 1982 */ 1983 if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FILEHANDLE, 1984 0, NULL, NULL, NULL))) 1985 return error; 1986 1987 error = vfs_copyinfh_alloc(ufhp, fhsize, &fh); 1988 if (error != 0) 1989 return error; 1990 1991 error = vfs_fhtovp(fh, &vp); 1992 vfs_copyinfh_free(fh); 1993 if (error != 0) 1994 return error; 1995 1996 mp = vp->v_mount; 1997 error = dostatvfs(mp, sb, l, flags, 1); 1998 vput(vp); 1999 return error; 2000 } 2001 2002 /* ARGSUSED */ 2003 int 2004 sys___fhstatvfs140(struct lwp *l, const struct sys___fhstatvfs140_args *uap, register_t *retval) 2005 { 2006 /* { 2007 syscallarg(const void *) fhp; 2008 syscallarg(size_t) fh_size; 2009 syscallarg(struct statvfs *) buf; 2010 syscallarg(int) flags; 2011 } */ 2012 struct statvfs *sb = STATVFSBUF_GET(); 2013 int error; 2014 2015 error = do_fhstatvfs(l, SCARG(uap, fhp), SCARG(uap, fh_size), sb, 2016 SCARG(uap, flags)); 2017 if (error == 0) 2018 error = copyout(sb, SCARG(uap, buf), sizeof(*sb)); 2019 STATVFSBUF_PUT(sb); 2020 return error; 2021 } 2022 2023 /* 2024 * Create a special file. 2025 */ 2026 /* ARGSUSED */ 2027 int 2028 sys___mknod50(struct lwp *l, const struct sys___mknod50_args *uap, 2029 register_t *retval) 2030 { 2031 /* { 2032 syscallarg(const char *) path; 2033 syscallarg(mode_t) mode; 2034 syscallarg(dev_t) dev; 2035 } */ 2036 return do_sys_mknod(l, SCARG(uap, path), SCARG(uap, mode), 2037 SCARG(uap, dev), retval, UIO_USERSPACE); 2038 } 2039 2040 int 2041 sys_mknodat(struct lwp *l, const struct sys_mknodat_args *uap, 2042 register_t *retval) 2043 { 2044 /* { 2045 syscallarg(int) fd; 2046 syscallarg(const char *) path; 2047 syscallarg(mode_t) mode; 2048 syscallarg(uint32_t) dev; 2049 } */ 2050 2051 return ENOSYS; 2052 } 2053 2054 int 2055 do_sys_mknod(struct lwp *l, const char *pathname, mode_t mode, dev_t dev, 2056 register_t *retval, enum uio_seg seg) 2057 { 2058 struct proc *p = l->l_proc; 2059 struct vnode *vp; 2060 struct vattr vattr; 2061 int error, optype; 2062 struct pathbuf *pb; 2063 struct nameidata nd; 2064 const char *pathstring; 2065 2066 if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MKNOD, 2067 0, NULL, NULL, NULL)) != 0) 2068 return (error); 2069 2070 optype = VOP_MKNOD_DESCOFFSET; 2071 2072 error = pathbuf_maybe_copyin(pathname, seg, &pb); 2073 if (error) { 2074 return error; 2075 } 2076 pathstring = pathbuf_stringcopy_get(pb); 2077 if (pathstring == NULL) { 2078 pathbuf_destroy(pb); 2079 return ENOMEM; 2080 } 2081 2082 NDINIT(&nd, CREATE, LOCKPARENT | TRYEMULROOT, pb); 2083 if ((error = namei(&nd)) != 0) 2084 goto out; 2085 vp = nd.ni_vp; 2086 2087 if (vp != NULL) 2088 error = EEXIST; 2089 else { 2090 vattr_null(&vattr); 2091 /* We will read cwdi->cwdi_cmask unlocked. */ 2092 vattr.va_mode = (mode & ALLPERMS) &~ p->p_cwdi->cwdi_cmask; 2093 vattr.va_rdev = dev; 2094 2095 switch (mode & S_IFMT) { 2096 case S_IFMT: /* used by badsect to flag bad sectors */ 2097 vattr.va_type = VBAD; 2098 break; 2099 case S_IFCHR: 2100 vattr.va_type = VCHR; 2101 break; 2102 case S_IFBLK: 2103 vattr.va_type = VBLK; 2104 break; 2105 case S_IFWHT: 2106 optype = VOP_WHITEOUT_DESCOFFSET; 2107 break; 2108 case S_IFREG: 2109 #if NVERIEXEC > 0 2110 error = veriexec_openchk(l, nd.ni_vp, pathstring, 2111 O_CREAT); 2112 #endif /* NVERIEXEC > 0 */ 2113 vattr.va_type = VREG; 2114 vattr.va_rdev = VNOVAL; 2115 optype = VOP_CREATE_DESCOFFSET; 2116 break; 2117 default: 2118 error = EINVAL; 2119 break; 2120 } 2121 } 2122 if (error == 0 && optype == VOP_MKNOD_DESCOFFSET 2123 && vattr.va_rdev == VNOVAL) 2124 error = EINVAL; 2125 if (!error) { 2126 switch (optype) { 2127 case VOP_WHITEOUT_DESCOFFSET: 2128 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE); 2129 if (error) 2130 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2131 vput(nd.ni_dvp); 2132 break; 2133 2134 case VOP_MKNOD_DESCOFFSET: 2135 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, 2136 &nd.ni_cnd, &vattr); 2137 if (error == 0) 2138 vput(nd.ni_vp); 2139 break; 2140 2141 case VOP_CREATE_DESCOFFSET: 2142 error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, 2143 &nd.ni_cnd, &vattr); 2144 if (error == 0) 2145 vput(nd.ni_vp); 2146 break; 2147 } 2148 } else { 2149 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2150 if (nd.ni_dvp == vp) 2151 vrele(nd.ni_dvp); 2152 else 2153 vput(nd.ni_dvp); 2154 if (vp) 2155 vrele(vp); 2156 } 2157 out: 2158 pathbuf_stringcopy_put(pb, pathstring); 2159 pathbuf_destroy(pb); 2160 return (error); 2161 } 2162 2163 /* 2164 * Create a named pipe. 2165 */ 2166 /* ARGSUSED */ 2167 int 2168 sys_mkfifo(struct lwp *l, const struct sys_mkfifo_args *uap, register_t *retval) 2169 { 2170 /* { 2171 syscallarg(const char *) path; 2172 syscallarg(int) mode; 2173 } */ 2174 struct proc *p = l->l_proc; 2175 struct vattr vattr; 2176 int error; 2177 struct pathbuf *pb; 2178 struct nameidata nd; 2179 2180 error = pathbuf_copyin(SCARG(uap, path), &pb); 2181 if (error) { 2182 return error; 2183 } 2184 NDINIT(&nd, CREATE, LOCKPARENT | TRYEMULROOT, pb); 2185 if ((error = namei(&nd)) != 0) { 2186 pathbuf_destroy(pb); 2187 return error; 2188 } 2189 if (nd.ni_vp != NULL) { 2190 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2191 if (nd.ni_dvp == nd.ni_vp) 2192 vrele(nd.ni_dvp); 2193 else 2194 vput(nd.ni_dvp); 2195 vrele(nd.ni_vp); 2196 pathbuf_destroy(pb); 2197 return (EEXIST); 2198 } 2199 vattr_null(&vattr); 2200 vattr.va_type = VFIFO; 2201 /* We will read cwdi->cwdi_cmask unlocked. */ 2202 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_cwdi->cwdi_cmask; 2203 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 2204 if (error == 0) 2205 vput(nd.ni_vp); 2206 pathbuf_destroy(pb); 2207 return (error); 2208 } 2209 2210 int 2211 sys_mkfifoat(struct lwp *l, const struct sys_mkfifoat_args *uap, 2212 register_t *retval) 2213 { 2214 /* { 2215 syscallarg(int) fd; 2216 syscallarg(const char *) path; 2217 syscallarg(int) mode; 2218 } */ 2219 2220 return ENOSYS; 2221 } 2222 /* 2223 * Make a hard file link. 2224 */ 2225 /* ARGSUSED */ 2226 static int 2227 do_sys_link(struct lwp *l, const char *path, const char *link, 2228 int follow, register_t *retval) 2229 { 2230 struct vnode *vp; 2231 struct pathbuf *linkpb; 2232 struct nameidata nd; 2233 namei_simple_flags_t namei_simple_flags; 2234 int error; 2235 2236 if (follow) 2237 namei_simple_flags = NSM_FOLLOW_TRYEMULROOT; 2238 else 2239 namei_simple_flags = NSM_NOFOLLOW_TRYEMULROOT; 2240 2241 error = namei_simple_user(path, namei_simple_flags, &vp); 2242 if (error != 0) 2243 return (error); 2244 error = pathbuf_copyin(link, &linkpb); 2245 if (error) { 2246 goto out1; 2247 } 2248 NDINIT(&nd, CREATE, LOCKPARENT | TRYEMULROOT, linkpb); 2249 if ((error = namei(&nd)) != 0) 2250 goto out2; 2251 if (nd.ni_vp) { 2252 error = EEXIST; 2253 goto abortop; 2254 } 2255 /* Prevent hard links on directories. */ 2256 if (vp->v_type == VDIR) { 2257 error = EPERM; 2258 goto abortop; 2259 } 2260 /* Prevent cross-mount operation. */ 2261 if (nd.ni_dvp->v_mount != vp->v_mount) { 2262 error = EXDEV; 2263 goto abortop; 2264 } 2265 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); 2266 out2: 2267 pathbuf_destroy(linkpb); 2268 out1: 2269 vrele(vp); 2270 return (error); 2271 abortop: 2272 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2273 if (nd.ni_dvp == nd.ni_vp) 2274 vrele(nd.ni_dvp); 2275 else 2276 vput(nd.ni_dvp); 2277 if (nd.ni_vp != NULL) 2278 vrele(nd.ni_vp); 2279 goto out2; 2280 } 2281 2282 int 2283 sys_link(struct lwp *l, const struct sys_link_args *uap, register_t *retval) 2284 { 2285 /* { 2286 syscallarg(const char *) path; 2287 syscallarg(const char *) link; 2288 } */ 2289 const char *path = SCARG(uap, path); 2290 const char *link = SCARG(uap, link); 2291 2292 return do_sys_link(l, path, link, 1, retval); 2293 } 2294 2295 int 2296 sys_linkat(struct lwp *l, const struct sys_linkat_args *uap, 2297 register_t *retval) 2298 { 2299 /* { 2300 syscallarg(int) fd1; 2301 syscallarg(const char *) name1; 2302 syscallarg(int) fd2; 2303 syscallarg(const char *) name2; 2304 syscallarg(int) flags; 2305 } */ 2306 const char *name1 = SCARG(uap, name1); 2307 const char *name2 = SCARG(uap, name2); 2308 int follow; 2309 2310 /* 2311 * Specified fd1 and fd2 are not yet implemented 2312 */ 2313 if ((SCARG(uap, fd1) != AT_FDCWD) || (SCARG(uap, fd2) != AT_FDCWD)) 2314 return ENOSYS; 2315 2316 follow = SCARG(uap, flags) & AT_SYMLINK_FOLLOW; 2317 2318 return do_sys_link(l, name1, name2, follow, retval); 2319 } 2320 2321 2322 int 2323 do_sys_symlink(const char *patharg, const char *link, enum uio_seg seg) 2324 { 2325 struct proc *p = curproc; 2326 struct vattr vattr; 2327 char *path; 2328 int error; 2329 struct pathbuf *linkpb; 2330 struct nameidata nd; 2331 2332 path = PNBUF_GET(); 2333 if (seg == UIO_USERSPACE) { 2334 if ((error = copyinstr(patharg, path, MAXPATHLEN, NULL)) != 0) 2335 goto out1; 2336 if ((error = pathbuf_copyin(link, &linkpb)) != 0) 2337 goto out1; 2338 } else { 2339 KASSERT(strlen(patharg) < MAXPATHLEN); 2340 strcpy(path, patharg); 2341 linkpb = pathbuf_create(link); 2342 if (linkpb == NULL) { 2343 error = ENOMEM; 2344 goto out1; 2345 } 2346 } 2347 ktrkuser("symlink-target", path, strlen(path)); 2348 2349 NDINIT(&nd, CREATE, LOCKPARENT | TRYEMULROOT, linkpb); 2350 if ((error = namei(&nd)) != 0) 2351 goto out2; 2352 if (nd.ni_vp) { 2353 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2354 if (nd.ni_dvp == nd.ni_vp) 2355 vrele(nd.ni_dvp); 2356 else 2357 vput(nd.ni_dvp); 2358 vrele(nd.ni_vp); 2359 error = EEXIST; 2360 goto out2; 2361 } 2362 vattr_null(&vattr); 2363 vattr.va_type = VLNK; 2364 /* We will read cwdi->cwdi_cmask unlocked. */ 2365 vattr.va_mode = ACCESSPERMS &~ p->p_cwdi->cwdi_cmask; 2366 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path); 2367 if (error == 0) 2368 vput(nd.ni_vp); 2369 out2: 2370 pathbuf_destroy(linkpb); 2371 out1: 2372 PNBUF_PUT(path); 2373 return (error); 2374 } 2375 2376 /* 2377 * Make a symbolic link. 2378 */ 2379 /* ARGSUSED */ 2380 int 2381 sys_symlink(struct lwp *l, const struct sys_symlink_args *uap, register_t *retval) 2382 { 2383 /* { 2384 syscallarg(const char *) path; 2385 syscallarg(const char *) link; 2386 } */ 2387 2388 return do_sys_symlink(SCARG(uap, path), SCARG(uap, link), 2389 UIO_USERSPACE); 2390 } 2391 2392 int 2393 sys_symlinkat(struct lwp *l, const struct sys_symlinkat_args *uap, 2394 register_t *retval) 2395 { 2396 /* { 2397 syscallarg(int) fd; 2398 syscallarg(const char *) path; 2399 syscallarg(const char *) link; 2400 } */ 2401 2402 return ENOSYS; 2403 } 2404 2405 /* 2406 * Delete a whiteout from the filesystem. 2407 */ 2408 /* ARGSUSED */ 2409 int 2410 sys_undelete(struct lwp *l, const struct sys_undelete_args *uap, register_t *retval) 2411 { 2412 /* { 2413 syscallarg(const char *) path; 2414 } */ 2415 int error; 2416 struct pathbuf *pb; 2417 struct nameidata nd; 2418 2419 error = pathbuf_copyin(SCARG(uap, path), &pb); 2420 if (error) { 2421 return error; 2422 } 2423 2424 NDINIT(&nd, DELETE, LOCKPARENT | DOWHITEOUT | TRYEMULROOT, pb); 2425 error = namei(&nd); 2426 if (error) { 2427 pathbuf_destroy(pb); 2428 return (error); 2429 } 2430 2431 if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) { 2432 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2433 if (nd.ni_dvp == nd.ni_vp) 2434 vrele(nd.ni_dvp); 2435 else 2436 vput(nd.ni_dvp); 2437 if (nd.ni_vp) 2438 vrele(nd.ni_vp); 2439 pathbuf_destroy(pb); 2440 return (EEXIST); 2441 } 2442 if ((error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE)) != 0) 2443 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2444 vput(nd.ni_dvp); 2445 pathbuf_destroy(pb); 2446 return (error); 2447 } 2448 2449 /* 2450 * Delete a name from the filesystem. 2451 */ 2452 /* ARGSUSED */ 2453 int 2454 sys_unlink(struct lwp *l, const struct sys_unlink_args *uap, register_t *retval) 2455 { 2456 /* { 2457 syscallarg(const char *) path; 2458 } */ 2459 2460 return do_sys_unlink(SCARG(uap, path), UIO_USERSPACE); 2461 } 2462 2463 int 2464 sys_unlinkat(struct lwp *l, const struct sys_unlinkat_args *uap, 2465 register_t *retval) 2466 { 2467 /* { 2468 syscallarg(int) fd; 2469 syscallarg(const char *) path; 2470 } */ 2471 2472 return ENOSYS; 2473 } 2474 2475 int 2476 do_sys_unlink(const char *arg, enum uio_seg seg) 2477 { 2478 struct vnode *vp; 2479 int error; 2480 struct pathbuf *pb; 2481 struct nameidata nd; 2482 const char *pathstring; 2483 2484 error = pathbuf_maybe_copyin(arg, seg, &pb); 2485 if (error) { 2486 return error; 2487 } 2488 pathstring = pathbuf_stringcopy_get(pb); 2489 if (pathstring == NULL) { 2490 pathbuf_destroy(pb); 2491 return ENOMEM; 2492 } 2493 2494 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF | TRYEMULROOT, pb); 2495 if ((error = namei(&nd)) != 0) 2496 goto out; 2497 vp = nd.ni_vp; 2498 2499 /* 2500 * The root of a mounted filesystem cannot be deleted. 2501 */ 2502 if (vp->v_vflag & VV_ROOT) { 2503 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2504 if (nd.ni_dvp == vp) 2505 vrele(nd.ni_dvp); 2506 else 2507 vput(nd.ni_dvp); 2508 vput(vp); 2509 error = EBUSY; 2510 goto out; 2511 } 2512 2513 #if NVERIEXEC > 0 2514 /* Handle remove requests for veriexec entries. */ 2515 if ((error = veriexec_removechk(curlwp, nd.ni_vp, pathstring)) != 0) { 2516 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2517 if (nd.ni_dvp == vp) 2518 vrele(nd.ni_dvp); 2519 else 2520 vput(nd.ni_dvp); 2521 vput(vp); 2522 goto out; 2523 } 2524 #endif /* NVERIEXEC > 0 */ 2525 2526 #ifdef FILEASSOC 2527 (void)fileassoc_file_delete(vp); 2528 #endif /* FILEASSOC */ 2529 error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 2530 out: 2531 pathbuf_stringcopy_put(pb, pathstring); 2532 pathbuf_destroy(pb); 2533 return (error); 2534 } 2535 2536 /* 2537 * Reposition read/write file offset. 2538 */ 2539 int 2540 sys_lseek(struct lwp *l, const struct sys_lseek_args *uap, register_t *retval) 2541 { 2542 /* { 2543 syscallarg(int) fd; 2544 syscallarg(int) pad; 2545 syscallarg(off_t) offset; 2546 syscallarg(int) whence; 2547 } */ 2548 kauth_cred_t cred = l->l_cred; 2549 file_t *fp; 2550 struct vnode *vp; 2551 struct vattr vattr; 2552 off_t newoff; 2553 int error, fd; 2554 2555 fd = SCARG(uap, fd); 2556 2557 if ((fp = fd_getfile(fd)) == NULL) 2558 return (EBADF); 2559 2560 vp = fp->f_data; 2561 if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { 2562 error = ESPIPE; 2563 goto out; 2564 } 2565 2566 switch (SCARG(uap, whence)) { 2567 case SEEK_CUR: 2568 newoff = fp->f_offset + SCARG(uap, offset); 2569 break; 2570 case SEEK_END: 2571 vn_lock(vp, LK_SHARED | LK_RETRY); 2572 error = VOP_GETATTR(vp, &vattr, cred); 2573 VOP_UNLOCK(vp); 2574 if (error) { 2575 goto out; 2576 } 2577 newoff = SCARG(uap, offset) + vattr.va_size; 2578 break; 2579 case SEEK_SET: 2580 newoff = SCARG(uap, offset); 2581 break; 2582 default: 2583 error = EINVAL; 2584 goto out; 2585 } 2586 if ((error = VOP_SEEK(vp, fp->f_offset, newoff, cred)) == 0) { 2587 *(off_t *)retval = fp->f_offset = newoff; 2588 } 2589 out: 2590 fd_putfile(fd); 2591 return (error); 2592 } 2593 2594 /* 2595 * Positional read system call. 2596 */ 2597 int 2598 sys_pread(struct lwp *l, const struct sys_pread_args *uap, register_t *retval) 2599 { 2600 /* { 2601 syscallarg(int) fd; 2602 syscallarg(void *) buf; 2603 syscallarg(size_t) nbyte; 2604 syscallarg(off_t) offset; 2605 } */ 2606 file_t *fp; 2607 struct vnode *vp; 2608 off_t offset; 2609 int error, fd = SCARG(uap, fd); 2610 2611 if ((fp = fd_getfile(fd)) == NULL) 2612 return (EBADF); 2613 2614 if ((fp->f_flag & FREAD) == 0) { 2615 fd_putfile(fd); 2616 return (EBADF); 2617 } 2618 2619 vp = fp->f_data; 2620 if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { 2621 error = ESPIPE; 2622 goto out; 2623 } 2624 2625 offset = SCARG(uap, offset); 2626 2627 /* 2628 * XXX This works because no file systems actually 2629 * XXX take any action on the seek operation. 2630 */ 2631 if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0) 2632 goto out; 2633 2634 /* dofileread() will unuse the descriptor for us */ 2635 return (dofileread(fd, fp, SCARG(uap, buf), SCARG(uap, nbyte), 2636 &offset, 0, retval)); 2637 2638 out: 2639 fd_putfile(fd); 2640 return (error); 2641 } 2642 2643 /* 2644 * Positional scatter read system call. 2645 */ 2646 int 2647 sys_preadv(struct lwp *l, const struct sys_preadv_args *uap, register_t *retval) 2648 { 2649 /* { 2650 syscallarg(int) fd; 2651 syscallarg(const struct iovec *) iovp; 2652 syscallarg(int) iovcnt; 2653 syscallarg(off_t) offset; 2654 } */ 2655 off_t offset = SCARG(uap, offset); 2656 2657 return do_filereadv(SCARG(uap, fd), SCARG(uap, iovp), 2658 SCARG(uap, iovcnt), &offset, 0, retval); 2659 } 2660 2661 /* 2662 * Positional write system call. 2663 */ 2664 int 2665 sys_pwrite(struct lwp *l, const struct sys_pwrite_args *uap, register_t *retval) 2666 { 2667 /* { 2668 syscallarg(int) fd; 2669 syscallarg(const void *) buf; 2670 syscallarg(size_t) nbyte; 2671 syscallarg(off_t) offset; 2672 } */ 2673 file_t *fp; 2674 struct vnode *vp; 2675 off_t offset; 2676 int error, fd = SCARG(uap, fd); 2677 2678 if ((fp = fd_getfile(fd)) == NULL) 2679 return (EBADF); 2680 2681 if ((fp->f_flag & FWRITE) == 0) { 2682 fd_putfile(fd); 2683 return (EBADF); 2684 } 2685 2686 vp = fp->f_data; 2687 if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { 2688 error = ESPIPE; 2689 goto out; 2690 } 2691 2692 offset = SCARG(uap, offset); 2693 2694 /* 2695 * XXX This works because no file systems actually 2696 * XXX take any action on the seek operation. 2697 */ 2698 if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0) 2699 goto out; 2700 2701 /* dofilewrite() will unuse the descriptor for us */ 2702 return (dofilewrite(fd, fp, SCARG(uap, buf), SCARG(uap, nbyte), 2703 &offset, 0, retval)); 2704 2705 out: 2706 fd_putfile(fd); 2707 return (error); 2708 } 2709 2710 /* 2711 * Positional gather write system call. 2712 */ 2713 int 2714 sys_pwritev(struct lwp *l, const struct sys_pwritev_args *uap, register_t *retval) 2715 { 2716 /* { 2717 syscallarg(int) fd; 2718 syscallarg(const struct iovec *) iovp; 2719 syscallarg(int) iovcnt; 2720 syscallarg(off_t) offset; 2721 } */ 2722 off_t offset = SCARG(uap, offset); 2723 2724 return do_filewritev(SCARG(uap, fd), SCARG(uap, iovp), 2725 SCARG(uap, iovcnt), &offset, 0, retval); 2726 } 2727 2728 /* 2729 * Check access permissions. 2730 */ 2731 int 2732 sys_access(struct lwp *l, const struct sys_access_args *uap, register_t *retval) 2733 { 2734 /* { 2735 syscallarg(const char *) path; 2736 syscallarg(int) flags; 2737 } */ 2738 kauth_cred_t cred; 2739 struct vnode *vp; 2740 int error, flags; 2741 struct pathbuf *pb; 2742 struct nameidata nd; 2743 2744 CTASSERT(F_OK == 0); 2745 if ((SCARG(uap, flags) & ~(R_OK | W_OK | X_OK)) != 0) { 2746 /* nonsense flags */ 2747 return EINVAL; 2748 } 2749 2750 error = pathbuf_copyin(SCARG(uap, path), &pb); 2751 if (error) { 2752 return error; 2753 } 2754 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT, pb); 2755 2756 /* Override default credentials */ 2757 cred = kauth_cred_dup(l->l_cred); 2758 kauth_cred_seteuid(cred, kauth_cred_getuid(l->l_cred)); 2759 kauth_cred_setegid(cred, kauth_cred_getgid(l->l_cred)); 2760 nd.ni_cnd.cn_cred = cred; 2761 2762 if ((error = namei(&nd)) != 0) { 2763 pathbuf_destroy(pb); 2764 goto out; 2765 } 2766 vp = nd.ni_vp; 2767 pathbuf_destroy(pb); 2768 2769 /* Flags == 0 means only check for existence. */ 2770 if (SCARG(uap, flags)) { 2771 flags = 0; 2772 if (SCARG(uap, flags) & R_OK) 2773 flags |= VREAD; 2774 if (SCARG(uap, flags) & W_OK) 2775 flags |= VWRITE; 2776 if (SCARG(uap, flags) & X_OK) 2777 flags |= VEXEC; 2778 2779 error = VOP_ACCESS(vp, flags, cred); 2780 if (!error && (flags & VWRITE)) 2781 error = vn_writechk(vp); 2782 } 2783 vput(vp); 2784 out: 2785 kauth_cred_free(cred); 2786 return (error); 2787 } 2788 2789 int 2790 sys_faccessat(struct lwp *l, const struct sys_faccessat_args *uap, 2791 register_t *retval) 2792 { 2793 /* { 2794 syscallarg(int) fd; 2795 syscallarg(const char *) path; 2796 syscallarg(int) amode; 2797 syscallarg(int) flag; 2798 } */ 2799 2800 return ENOSYS; 2801 } 2802 2803 /* 2804 * Common code for all sys_stat functions, including compat versions. 2805 */ 2806 int 2807 do_sys_stat(const char *userpath, unsigned int nd_flags, struct stat *sb) 2808 { 2809 int error; 2810 struct pathbuf *pb; 2811 struct nameidata nd; 2812 2813 error = pathbuf_copyin(userpath, &pb); 2814 if (error) { 2815 return error; 2816 } 2817 NDINIT(&nd, LOOKUP, nd_flags | LOCKLEAF | TRYEMULROOT, pb); 2818 error = namei(&nd); 2819 if (error != 0) { 2820 pathbuf_destroy(pb); 2821 return error; 2822 } 2823 error = vn_stat(nd.ni_vp, sb); 2824 vput(nd.ni_vp); 2825 pathbuf_destroy(pb); 2826 return error; 2827 } 2828 2829 /* 2830 * Get file status; this version follows links. 2831 */ 2832 /* ARGSUSED */ 2833 int 2834 sys___stat50(struct lwp *l, const struct sys___stat50_args *uap, register_t *retval) 2835 { 2836 /* { 2837 syscallarg(const char *) path; 2838 syscallarg(struct stat *) ub; 2839 } */ 2840 struct stat sb; 2841 int error; 2842 2843 error = do_sys_stat(SCARG(uap, path), FOLLOW, &sb); 2844 if (error) 2845 return error; 2846 return copyout(&sb, SCARG(uap, ub), sizeof(sb)); 2847 } 2848 2849 /* 2850 * Get file status; this version does not follow links. 2851 */ 2852 /* ARGSUSED */ 2853 int 2854 sys___lstat50(struct lwp *l, const struct sys___lstat50_args *uap, register_t *retval) 2855 { 2856 /* { 2857 syscallarg(const char *) path; 2858 syscallarg(struct stat *) ub; 2859 } */ 2860 struct stat sb; 2861 int error; 2862 2863 error = do_sys_stat(SCARG(uap, path), NOFOLLOW, &sb); 2864 if (error) 2865 return error; 2866 return copyout(&sb, SCARG(uap, ub), sizeof(sb)); 2867 } 2868 2869 int 2870 sys_fstatat(struct lwp *l, const struct sys_fstatat_args *uap, 2871 register_t *retval) 2872 { 2873 /* { 2874 syscallarg(int) fd; 2875 syscallarg(const char *) path; 2876 syscallarg(struct stat *) ub; 2877 syscallarg(int) flag; 2878 } */ 2879 2880 return ENOSYS; 2881 } 2882 /* 2883 * Get configurable pathname variables. 2884 */ 2885 /* ARGSUSED */ 2886 int 2887 sys_pathconf(struct lwp *l, const struct sys_pathconf_args *uap, register_t *retval) 2888 { 2889 /* { 2890 syscallarg(const char *) path; 2891 syscallarg(int) name; 2892 } */ 2893 int error; 2894 struct pathbuf *pb; 2895 struct nameidata nd; 2896 2897 error = pathbuf_copyin(SCARG(uap, path), &pb); 2898 if (error) { 2899 return error; 2900 } 2901 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT, pb); 2902 if ((error = namei(&nd)) != 0) { 2903 pathbuf_destroy(pb); 2904 return (error); 2905 } 2906 error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval); 2907 vput(nd.ni_vp); 2908 pathbuf_destroy(pb); 2909 return (error); 2910 } 2911 2912 /* 2913 * Return target name of a symbolic link. 2914 */ 2915 /* ARGSUSED */ 2916 int 2917 sys_readlink(struct lwp *l, const struct sys_readlink_args *uap, register_t *retval) 2918 { 2919 /* { 2920 syscallarg(const char *) path; 2921 syscallarg(char *) buf; 2922 syscallarg(size_t) count; 2923 } */ 2924 struct vnode *vp; 2925 struct iovec aiov; 2926 struct uio auio; 2927 int error; 2928 struct pathbuf *pb; 2929 struct nameidata nd; 2930 2931 error = pathbuf_copyin(SCARG(uap, path), &pb); 2932 if (error) { 2933 return error; 2934 } 2935 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | TRYEMULROOT, pb); 2936 if ((error = namei(&nd)) != 0) { 2937 pathbuf_destroy(pb); 2938 return error; 2939 } 2940 vp = nd.ni_vp; 2941 pathbuf_destroy(pb); 2942 if (vp->v_type != VLNK) 2943 error = EINVAL; 2944 else if (!(vp->v_mount->mnt_flag & MNT_SYMPERM) || 2945 (error = VOP_ACCESS(vp, VREAD, l->l_cred)) == 0) { 2946 aiov.iov_base = SCARG(uap, buf); 2947 aiov.iov_len = SCARG(uap, count); 2948 auio.uio_iov = &aiov; 2949 auio.uio_iovcnt = 1; 2950 auio.uio_offset = 0; 2951 auio.uio_rw = UIO_READ; 2952 KASSERT(l == curlwp); 2953 auio.uio_vmspace = l->l_proc->p_vmspace; 2954 auio.uio_resid = SCARG(uap, count); 2955 error = VOP_READLINK(vp, &auio, l->l_cred); 2956 } 2957 vput(vp); 2958 *retval = SCARG(uap, count) - auio.uio_resid; 2959 return (error); 2960 } 2961 2962 int 2963 sys_readlinkat(struct lwp *l, const struct sys_readlinkat_args *uap, 2964 register_t *retval) 2965 { 2966 /* { 2967 syscallarg(int) fd; 2968 syscallarg(const char *) path; 2969 syscallarg(char *) buf; 2970 syscallarg(size_t) count; 2971 } */ 2972 2973 return ENOSYS; 2974 } 2975 2976 /* 2977 * Change flags of a file given a path name. 2978 */ 2979 /* ARGSUSED */ 2980 int 2981 sys_chflags(struct lwp *l, const struct sys_chflags_args *uap, register_t *retval) 2982 { 2983 /* { 2984 syscallarg(const char *) path; 2985 syscallarg(u_long) flags; 2986 } */ 2987 struct vnode *vp; 2988 int error; 2989 2990 error = namei_simple_user(SCARG(uap, path), 2991 NSM_FOLLOW_TRYEMULROOT, &vp); 2992 if (error != 0) 2993 return (error); 2994 error = change_flags(vp, SCARG(uap, flags), l); 2995 vput(vp); 2996 return (error); 2997 } 2998 2999 /* 3000 * Change flags of a file given a file descriptor. 3001 */ 3002 /* ARGSUSED */ 3003 int 3004 sys_fchflags(struct lwp *l, const struct sys_fchflags_args *uap, register_t *retval) 3005 { 3006 /* { 3007 syscallarg(int) fd; 3008 syscallarg(u_long) flags; 3009 } */ 3010 struct vnode *vp; 3011 file_t *fp; 3012 int error; 3013 3014 /* fd_getvnode() will use the descriptor for us */ 3015 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 3016 return (error); 3017 vp = fp->f_data; 3018 error = change_flags(vp, SCARG(uap, flags), l); 3019 VOP_UNLOCK(vp); 3020 fd_putfile(SCARG(uap, fd)); 3021 return (error); 3022 } 3023 3024 /* 3025 * Change flags of a file given a path name; this version does 3026 * not follow links. 3027 */ 3028 int 3029 sys_lchflags(struct lwp *l, const struct sys_lchflags_args *uap, register_t *retval) 3030 { 3031 /* { 3032 syscallarg(const char *) path; 3033 syscallarg(u_long) flags; 3034 } */ 3035 struct vnode *vp; 3036 int error; 3037 3038 error = namei_simple_user(SCARG(uap, path), 3039 NSM_NOFOLLOW_TRYEMULROOT, &vp); 3040 if (error != 0) 3041 return (error); 3042 error = change_flags(vp, SCARG(uap, flags), l); 3043 vput(vp); 3044 return (error); 3045 } 3046 3047 /* 3048 * Common routine to change flags of a file. 3049 */ 3050 int 3051 change_flags(struct vnode *vp, u_long flags, struct lwp *l) 3052 { 3053 struct vattr vattr; 3054 int error; 3055 3056 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 3057 3058 vattr_null(&vattr); 3059 vattr.va_flags = flags; 3060 error = VOP_SETATTR(vp, &vattr, l->l_cred); 3061 3062 return (error); 3063 } 3064 3065 /* 3066 * Change mode of a file given path name; this version follows links. 3067 */ 3068 /* ARGSUSED */ 3069 int 3070 sys_chmod(struct lwp *l, const struct sys_chmod_args *uap, register_t *retval) 3071 { 3072 /* { 3073 syscallarg(const char *) path; 3074 syscallarg(int) mode; 3075 } */ 3076 int error; 3077 struct vnode *vp; 3078 3079 error = namei_simple_user(SCARG(uap, path), 3080 NSM_FOLLOW_TRYEMULROOT, &vp); 3081 if (error != 0) 3082 return (error); 3083 3084 error = change_mode(vp, SCARG(uap, mode), l); 3085 3086 vrele(vp); 3087 return (error); 3088 } 3089 3090 /* 3091 * Change mode of a file given a file descriptor. 3092 */ 3093 /* ARGSUSED */ 3094 int 3095 sys_fchmod(struct lwp *l, const struct sys_fchmod_args *uap, register_t *retval) 3096 { 3097 /* { 3098 syscallarg(int) fd; 3099 syscallarg(int) mode; 3100 } */ 3101 file_t *fp; 3102 int error; 3103 3104 /* fd_getvnode() will use the descriptor for us */ 3105 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 3106 return (error); 3107 error = change_mode(fp->f_data, SCARG(uap, mode), l); 3108 fd_putfile(SCARG(uap, fd)); 3109 return (error); 3110 } 3111 3112 int 3113 sys_fchmodat(struct lwp *l, const struct sys_fchmodat_args *uap, 3114 register_t *retval) 3115 { 3116 /* { 3117 syscallarg(int) fd; 3118 syscallarg(const char *) path; 3119 syscallarg(int) mode; 3120 syscallarg(int) flag; 3121 } */ 3122 3123 return ENOSYS; 3124 } 3125 3126 /* 3127 * Change mode of a file given path name; this version does not follow links. 3128 */ 3129 /* ARGSUSED */ 3130 int 3131 sys_lchmod(struct lwp *l, const struct sys_lchmod_args *uap, register_t *retval) 3132 { 3133 /* { 3134 syscallarg(const char *) path; 3135 syscallarg(int) mode; 3136 } */ 3137 int error; 3138 struct vnode *vp; 3139 3140 error = namei_simple_user(SCARG(uap, path), 3141 NSM_NOFOLLOW_TRYEMULROOT, &vp); 3142 if (error != 0) 3143 return (error); 3144 3145 error = change_mode(vp, SCARG(uap, mode), l); 3146 3147 vrele(vp); 3148 return (error); 3149 } 3150 3151 /* 3152 * Common routine to set mode given a vnode. 3153 */ 3154 static int 3155 change_mode(struct vnode *vp, int mode, struct lwp *l) 3156 { 3157 struct vattr vattr; 3158 int error; 3159 3160 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 3161 vattr_null(&vattr); 3162 vattr.va_mode = mode & ALLPERMS; 3163 error = VOP_SETATTR(vp, &vattr, l->l_cred); 3164 VOP_UNLOCK(vp); 3165 return (error); 3166 } 3167 3168 /* 3169 * Set ownership given a path name; this version follows links. 3170 */ 3171 /* ARGSUSED */ 3172 int 3173 sys_chown(struct lwp *l, const struct sys_chown_args *uap, register_t *retval) 3174 { 3175 /* { 3176 syscallarg(const char *) path; 3177 syscallarg(uid_t) uid; 3178 syscallarg(gid_t) gid; 3179 } */ 3180 int error; 3181 struct vnode *vp; 3182 3183 error = namei_simple_user(SCARG(uap, path), 3184 NSM_FOLLOW_TRYEMULROOT, &vp); 3185 if (error != 0) 3186 return (error); 3187 3188 error = change_owner(vp, SCARG(uap, uid), SCARG(uap, gid), l, 0); 3189 3190 vrele(vp); 3191 return (error); 3192 } 3193 3194 /* 3195 * Set ownership given a path name; this version follows links. 3196 * Provides POSIX semantics. 3197 */ 3198 /* ARGSUSED */ 3199 int 3200 sys___posix_chown(struct lwp *l, const struct sys___posix_chown_args *uap, register_t *retval) 3201 { 3202 /* { 3203 syscallarg(const char *) path; 3204 syscallarg(uid_t) uid; 3205 syscallarg(gid_t) gid; 3206 } */ 3207 int error; 3208 struct vnode *vp; 3209 3210 error = namei_simple_user(SCARG(uap, path), 3211 NSM_FOLLOW_TRYEMULROOT, &vp); 3212 if (error != 0) 3213 return (error); 3214 3215 error = change_owner(vp, SCARG(uap, uid), SCARG(uap, gid), l, 1); 3216 3217 vrele(vp); 3218 return (error); 3219 } 3220 3221 /* 3222 * Set ownership given a file descriptor. 3223 */ 3224 /* ARGSUSED */ 3225 int 3226 sys_fchown(struct lwp *l, const struct sys_fchown_args *uap, register_t *retval) 3227 { 3228 /* { 3229 syscallarg(int) fd; 3230 syscallarg(uid_t) uid; 3231 syscallarg(gid_t) gid; 3232 } */ 3233 int error; 3234 file_t *fp; 3235 3236 /* fd_getvnode() will use the descriptor for us */ 3237 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 3238 return (error); 3239 error = change_owner(fp->f_data, SCARG(uap, uid), SCARG(uap, gid), 3240 l, 0); 3241 fd_putfile(SCARG(uap, fd)); 3242 return (error); 3243 } 3244 3245 int 3246 sys_fchownat(struct lwp *l, const struct sys_fchownat_args *uap, 3247 register_t *retval) 3248 { 3249 /* { 3250 syscallarg(int) fd; 3251 syscallarg(const char *) path; 3252 syscallarg(uid_t) uid; 3253 syscallarg(gid_t) gid; 3254 syscallarg(int) flag; 3255 } */ 3256 3257 return ENOSYS; 3258 } 3259 3260 /* 3261 * Set ownership given a file descriptor, providing POSIX/XPG semantics. 3262 */ 3263 /* ARGSUSED */ 3264 int 3265 sys___posix_fchown(struct lwp *l, const struct sys___posix_fchown_args *uap, register_t *retval) 3266 { 3267 /* { 3268 syscallarg(int) fd; 3269 syscallarg(uid_t) uid; 3270 syscallarg(gid_t) gid; 3271 } */ 3272 int error; 3273 file_t *fp; 3274 3275 /* fd_getvnode() will use the descriptor for us */ 3276 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 3277 return (error); 3278 error = change_owner(fp->f_data, SCARG(uap, uid), SCARG(uap, gid), 3279 l, 1); 3280 fd_putfile(SCARG(uap, fd)); 3281 return (error); 3282 } 3283 3284 /* 3285 * Set ownership given a path name; this version does not follow links. 3286 */ 3287 /* ARGSUSED */ 3288 int 3289 sys_lchown(struct lwp *l, const struct sys_lchown_args *uap, register_t *retval) 3290 { 3291 /* { 3292 syscallarg(const char *) path; 3293 syscallarg(uid_t) uid; 3294 syscallarg(gid_t) gid; 3295 } */ 3296 int error; 3297 struct vnode *vp; 3298 3299 error = namei_simple_user(SCARG(uap, path), 3300 NSM_NOFOLLOW_TRYEMULROOT, &vp); 3301 if (error != 0) 3302 return (error); 3303 3304 error = change_owner(vp, SCARG(uap, uid), SCARG(uap, gid), l, 0); 3305 3306 vrele(vp); 3307 return (error); 3308 } 3309 3310 /* 3311 * Set ownership given a path name; this version does not follow links. 3312 * Provides POSIX/XPG semantics. 3313 */ 3314 /* ARGSUSED */ 3315 int 3316 sys___posix_lchown(struct lwp *l, const struct sys___posix_lchown_args *uap, register_t *retval) 3317 { 3318 /* { 3319 syscallarg(const char *) path; 3320 syscallarg(uid_t) uid; 3321 syscallarg(gid_t) gid; 3322 } */ 3323 int error; 3324 struct vnode *vp; 3325 3326 error = namei_simple_user(SCARG(uap, path), 3327 NSM_NOFOLLOW_TRYEMULROOT, &vp); 3328 if (error != 0) 3329 return (error); 3330 3331 error = change_owner(vp, SCARG(uap, uid), SCARG(uap, gid), l, 1); 3332 3333 vrele(vp); 3334 return (error); 3335 } 3336 3337 /* 3338 * Common routine to set ownership given a vnode. 3339 */ 3340 static int 3341 change_owner(struct vnode *vp, uid_t uid, gid_t gid, struct lwp *l, 3342 int posix_semantics) 3343 { 3344 struct vattr vattr; 3345 mode_t newmode; 3346 int error; 3347 3348 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 3349 if ((error = VOP_GETATTR(vp, &vattr, l->l_cred)) != 0) 3350 goto out; 3351 3352 #define CHANGED(x) ((int)(x) != -1) 3353 newmode = vattr.va_mode; 3354 if (posix_semantics) { 3355 /* 3356 * POSIX/XPG semantics: if the caller is not the super-user, 3357 * clear set-user-id and set-group-id bits. Both POSIX and 3358 * the XPG consider the behaviour for calls by the super-user 3359 * implementation-defined; we leave the set-user-id and set- 3360 * group-id settings intact in that case. 3361 */ 3362 if (vattr.va_mode & S_ISUID) { 3363 error = kauth_authorize_vnode(l->l_cred, 3364 KAUTH_VNODE_RETAIN_SUID, vp, NULL, EPERM); 3365 if (error) 3366 newmode &= ~S_ISUID; 3367 } 3368 if (vattr.va_mode & S_ISGID) { 3369 error = kauth_authorize_vnode(l->l_cred, 3370 KAUTH_VNODE_RETAIN_SGID, vp, NULL, EPERM); 3371 if (error) 3372 newmode &= ~S_ISGID; 3373 } 3374 } else { 3375 /* 3376 * NetBSD semantics: when changing owner and/or group, 3377 * clear the respective bit(s). 3378 */ 3379 if (CHANGED(uid)) 3380 newmode &= ~S_ISUID; 3381 if (CHANGED(gid)) 3382 newmode &= ~S_ISGID; 3383 } 3384 /* Update va_mode iff altered. */ 3385 if (vattr.va_mode == newmode) 3386 newmode = VNOVAL; 3387 3388 vattr_null(&vattr); 3389 vattr.va_uid = CHANGED(uid) ? uid : (uid_t)VNOVAL; 3390 vattr.va_gid = CHANGED(gid) ? gid : (gid_t)VNOVAL; 3391 vattr.va_mode = newmode; 3392 error = VOP_SETATTR(vp, &vattr, l->l_cred); 3393 #undef CHANGED 3394 3395 out: 3396 VOP_UNLOCK(vp); 3397 return (error); 3398 } 3399 3400 /* 3401 * Set the access and modification times given a path name; this 3402 * version follows links. 3403 */ 3404 /* ARGSUSED */ 3405 int 3406 sys___utimes50(struct lwp *l, const struct sys___utimes50_args *uap, 3407 register_t *retval) 3408 { 3409 /* { 3410 syscallarg(const char *) path; 3411 syscallarg(const struct timeval *) tptr; 3412 } */ 3413 3414 return do_sys_utimes(l, NULL, SCARG(uap, path), FOLLOW, 3415 SCARG(uap, tptr), UIO_USERSPACE); 3416 } 3417 3418 /* 3419 * Set the access and modification times given a file descriptor. 3420 */ 3421 /* ARGSUSED */ 3422 int 3423 sys___futimes50(struct lwp *l, const struct sys___futimes50_args *uap, 3424 register_t *retval) 3425 { 3426 /* { 3427 syscallarg(int) fd; 3428 syscallarg(const struct timeval *) tptr; 3429 } */ 3430 int error; 3431 file_t *fp; 3432 3433 /* fd_getvnode() will use the descriptor for us */ 3434 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 3435 return (error); 3436 error = do_sys_utimes(l, fp->f_data, NULL, 0, SCARG(uap, tptr), 3437 UIO_USERSPACE); 3438 fd_putfile(SCARG(uap, fd)); 3439 return (error); 3440 } 3441 3442 int 3443 sys_futimens(struct lwp *l, const struct sys_futimens_args *uap, 3444 register_t *retval) 3445 { 3446 /* { 3447 syscallarg(int) fd; 3448 syscallarg(const struct timespec *) tptr; 3449 } */ 3450 int error; 3451 file_t *fp; 3452 3453 /* fd_getvnode() will use the descriptor for us */ 3454 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 3455 return (error); 3456 error = do_sys_utimens(l, fp->f_data, NULL, 0, SCARG(uap, tptr), 3457 UIO_USERSPACE); 3458 fd_putfile(SCARG(uap, fd)); 3459 return (error); 3460 } 3461 3462 /* 3463 * Set the access and modification times given a path name; this 3464 * version does not follow links. 3465 */ 3466 int 3467 sys___lutimes50(struct lwp *l, const struct sys___lutimes50_args *uap, 3468 register_t *retval) 3469 { 3470 /* { 3471 syscallarg(const char *) path; 3472 syscallarg(const struct timeval *) tptr; 3473 } */ 3474 3475 return do_sys_utimes(l, NULL, SCARG(uap, path), NOFOLLOW, 3476 SCARG(uap, tptr), UIO_USERSPACE); 3477 } 3478 3479 int 3480 sys_utimensat(struct lwp *l, const struct sys_utimensat_args *uap, 3481 register_t *retval) 3482 { 3483 /* { 3484 syscallarg(int) fd; 3485 syscallarg(const char *) path; 3486 syscallarg(const struct timespec *) tptr; 3487 syscallarg(int) flag; 3488 } */ 3489 int follow; 3490 const struct timespec *tptr; 3491 3492 /* 3493 * Specified fd is not yet implemented 3494 */ 3495 if (SCARG(uap, fd) != AT_FDCWD) 3496 return ENOSYS; 3497 3498 tptr = SCARG(uap, tptr); 3499 follow = (SCARG(uap, flag) & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW; 3500 3501 return do_sys_utimens(l, NULL, SCARG(uap, path), follow, 3502 tptr, UIO_USERSPACE); 3503 } 3504 3505 /* 3506 * Common routine to set access and modification times given a vnode. 3507 */ 3508 int 3509 do_sys_utimens(struct lwp *l, struct vnode *vp, const char *path, int flag, 3510 const struct timespec *tptr, enum uio_seg seg) 3511 { 3512 struct vattr vattr; 3513 int error, dorele = 0; 3514 namei_simple_flags_t sflags; 3515 3516 bool vanull, setbirthtime; 3517 struct timespec ts[2]; 3518 3519 /* 3520 * I have checked all callers and they pass either FOLLOW, 3521 * NOFOLLOW, or 0 (when they don't pass a path), and NOFOLLOW 3522 * is 0. More to the point, they don't pass anything else. 3523 * Let's keep it that way at least until the namei interfaces 3524 * are fully sanitized. 3525 */ 3526 KASSERT(flag == NOFOLLOW || flag == FOLLOW); 3527 sflags = (flag == FOLLOW) ? 3528 NSM_FOLLOW_TRYEMULROOT : NSM_NOFOLLOW_TRYEMULROOT; 3529 3530 if (tptr == NULL) { 3531 vanull = true; 3532 nanotime(&ts[0]); 3533 ts[1] = ts[0]; 3534 } else { 3535 vanull = false; 3536 if (seg != UIO_SYSSPACE) { 3537 error = copyin(tptr, ts, sizeof (ts)); 3538 if (error != 0) 3539 return error; 3540 } else { 3541 ts[0] = tptr[0]; 3542 ts[1] = tptr[1]; 3543 } 3544 } 3545 3546 if (ts[0].tv_nsec == UTIME_NOW) { 3547 nanotime(&ts[0]); 3548 if (ts[1].tv_nsec == UTIME_NOW) { 3549 vanull = true; 3550 ts[1] = ts[0]; 3551 } 3552 } else if (ts[1].tv_nsec == UTIME_NOW) 3553 nanotime(&ts[1]); 3554 3555 if (vp == NULL) { 3556 /* note: SEG describes TPTR, not PATH; PATH is always user */ 3557 error = namei_simple_user(path, sflags, &vp); 3558 if (error != 0) 3559 return error; 3560 dorele = 1; 3561 } 3562 3563 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 3564 setbirthtime = (VOP_GETATTR(vp, &vattr, l->l_cred) == 0 && 3565 timespeccmp(&ts[1], &vattr.va_birthtime, <)); 3566 vattr_null(&vattr); 3567 3568 if (ts[0].tv_nsec != UTIME_OMIT) 3569 vattr.va_atime = ts[0]; 3570 3571 if (ts[1].tv_nsec != UTIME_OMIT) { 3572 vattr.va_mtime = ts[1]; 3573 if (setbirthtime) 3574 vattr.va_birthtime = ts[1]; 3575 } 3576 3577 if (vanull) 3578 vattr.va_vaflags |= VA_UTIMES_NULL; 3579 error = VOP_SETATTR(vp, &vattr, l->l_cred); 3580 VOP_UNLOCK(vp); 3581 3582 if (dorele != 0) 3583 vrele(vp); 3584 3585 return error; 3586 } 3587 3588 int 3589 do_sys_utimes(struct lwp *l, struct vnode *vp, const char *path, int flag, 3590 const struct timeval *tptr, enum uio_seg seg) 3591 { 3592 struct timespec ts[2]; 3593 struct timespec *tsptr = NULL; 3594 int error; 3595 3596 if (tptr != NULL) { 3597 struct timeval tv[2]; 3598 3599 if (seg != UIO_SYSSPACE) { 3600 error = copyin(tptr, tv, sizeof (tv)); 3601 if (error != 0) 3602 return error; 3603 tptr = tv; 3604 } 3605 3606 if ((tv[0].tv_usec == UTIME_NOW) || 3607 (tv[0].tv_usec == UTIME_OMIT)) 3608 ts[0].tv_nsec = tv[0].tv_usec; 3609 else 3610 TIMEVAL_TO_TIMESPEC(&tptr[0], &ts[0]); 3611 3612 if ((tv[1].tv_usec == UTIME_NOW) || 3613 (tv[1].tv_usec == UTIME_OMIT)) 3614 ts[1].tv_nsec = tv[1].tv_usec; 3615 else 3616 TIMEVAL_TO_TIMESPEC(&tptr[1], &ts[1]); 3617 3618 tsptr = &ts[0]; 3619 } 3620 3621 return do_sys_utimens(l, vp, path, flag, tsptr, UIO_SYSSPACE); 3622 } 3623 3624 /* 3625 * Truncate a file given its path name. 3626 */ 3627 /* ARGSUSED */ 3628 int 3629 sys_truncate(struct lwp *l, const struct sys_truncate_args *uap, register_t *retval) 3630 { 3631 /* { 3632 syscallarg(const char *) path; 3633 syscallarg(int) pad; 3634 syscallarg(off_t) length; 3635 } */ 3636 struct vnode *vp; 3637 struct vattr vattr; 3638 int error; 3639 3640 error = namei_simple_user(SCARG(uap, path), 3641 NSM_FOLLOW_TRYEMULROOT, &vp); 3642 if (error != 0) 3643 return (error); 3644 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 3645 if (vp->v_type == VDIR) 3646 error = EISDIR; 3647 else if ((error = vn_writechk(vp)) == 0 && 3648 (error = VOP_ACCESS(vp, VWRITE, l->l_cred)) == 0) { 3649 vattr_null(&vattr); 3650 vattr.va_size = SCARG(uap, length); 3651 error = VOP_SETATTR(vp, &vattr, l->l_cred); 3652 } 3653 vput(vp); 3654 return (error); 3655 } 3656 3657 /* 3658 * Truncate a file given a file descriptor. 3659 */ 3660 /* ARGSUSED */ 3661 int 3662 sys_ftruncate(struct lwp *l, const struct sys_ftruncate_args *uap, register_t *retval) 3663 { 3664 /* { 3665 syscallarg(int) fd; 3666 syscallarg(int) pad; 3667 syscallarg(off_t) length; 3668 } */ 3669 struct vattr vattr; 3670 struct vnode *vp; 3671 file_t *fp; 3672 int error; 3673 3674 /* fd_getvnode() will use the descriptor for us */ 3675 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 3676 return (error); 3677 if ((fp->f_flag & FWRITE) == 0) { 3678 error = EINVAL; 3679 goto out; 3680 } 3681 vp = fp->f_data; 3682 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 3683 if (vp->v_type == VDIR) 3684 error = EISDIR; 3685 else if ((error = vn_writechk(vp)) == 0) { 3686 vattr_null(&vattr); 3687 vattr.va_size = SCARG(uap, length); 3688 error = VOP_SETATTR(vp, &vattr, fp->f_cred); 3689 } 3690 VOP_UNLOCK(vp); 3691 out: 3692 fd_putfile(SCARG(uap, fd)); 3693 return (error); 3694 } 3695 3696 /* 3697 * Sync an open file. 3698 */ 3699 /* ARGSUSED */ 3700 int 3701 sys_fsync(struct lwp *l, const struct sys_fsync_args *uap, register_t *retval) 3702 { 3703 /* { 3704 syscallarg(int) fd; 3705 } */ 3706 struct vnode *vp; 3707 file_t *fp; 3708 int error; 3709 3710 /* fd_getvnode() will use the descriptor for us */ 3711 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 3712 return (error); 3713 vp = fp->f_data; 3714 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 3715 error = VOP_FSYNC(vp, fp->f_cred, FSYNC_WAIT, 0, 0); 3716 VOP_UNLOCK(vp); 3717 fd_putfile(SCARG(uap, fd)); 3718 return (error); 3719 } 3720 3721 /* 3722 * Sync a range of file data. API modeled after that found in AIX. 3723 * 3724 * FDATASYNC indicates that we need only save enough metadata to be able 3725 * to re-read the written data. Note we duplicate AIX's requirement that 3726 * the file be open for writing. 3727 */ 3728 /* ARGSUSED */ 3729 int 3730 sys_fsync_range(struct lwp *l, const struct sys_fsync_range_args *uap, register_t *retval) 3731 { 3732 /* { 3733 syscallarg(int) fd; 3734 syscallarg(int) flags; 3735 syscallarg(off_t) start; 3736 syscallarg(off_t) length; 3737 } */ 3738 struct vnode *vp; 3739 file_t *fp; 3740 int flags, nflags; 3741 off_t s, e, len; 3742 int error; 3743 3744 /* fd_getvnode() will use the descriptor for us */ 3745 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 3746 return (error); 3747 3748 if ((fp->f_flag & FWRITE) == 0) { 3749 error = EBADF; 3750 goto out; 3751 } 3752 3753 flags = SCARG(uap, flags); 3754 if (((flags & (FDATASYNC | FFILESYNC)) == 0) || 3755 ((~flags & (FDATASYNC | FFILESYNC)) == 0)) { 3756 error = EINVAL; 3757 goto out; 3758 } 3759 /* Now set up the flags for value(s) to pass to VOP_FSYNC() */ 3760 if (flags & FDATASYNC) 3761 nflags = FSYNC_DATAONLY | FSYNC_WAIT; 3762 else 3763 nflags = FSYNC_WAIT; 3764 if (flags & FDISKSYNC) 3765 nflags |= FSYNC_CACHE; 3766 3767 len = SCARG(uap, length); 3768 /* If length == 0, we do the whole file, and s = e = 0 will do that */ 3769 if (len) { 3770 s = SCARG(uap, start); 3771 e = s + len; 3772 if (e < s) { 3773 error = EINVAL; 3774 goto out; 3775 } 3776 } else { 3777 e = 0; 3778 s = 0; 3779 } 3780 3781 vp = fp->f_data; 3782 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 3783 error = VOP_FSYNC(vp, fp->f_cred, nflags, s, e); 3784 VOP_UNLOCK(vp); 3785 out: 3786 fd_putfile(SCARG(uap, fd)); 3787 return (error); 3788 } 3789 3790 /* 3791 * Sync the data of an open file. 3792 */ 3793 /* ARGSUSED */ 3794 int 3795 sys_fdatasync(struct lwp *l, const struct sys_fdatasync_args *uap, register_t *retval) 3796 { 3797 /* { 3798 syscallarg(int) fd; 3799 } */ 3800 struct vnode *vp; 3801 file_t *fp; 3802 int error; 3803 3804 /* fd_getvnode() will use the descriptor for us */ 3805 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 3806 return (error); 3807 if ((fp->f_flag & FWRITE) == 0) { 3808 fd_putfile(SCARG(uap, fd)); 3809 return (EBADF); 3810 } 3811 vp = fp->f_data; 3812 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 3813 error = VOP_FSYNC(vp, fp->f_cred, FSYNC_WAIT|FSYNC_DATAONLY, 0, 0); 3814 VOP_UNLOCK(vp); 3815 fd_putfile(SCARG(uap, fd)); 3816 return (error); 3817 } 3818 3819 /* 3820 * Rename files, (standard) BSD semantics frontend. 3821 */ 3822 /* ARGSUSED */ 3823 int 3824 sys_rename(struct lwp *l, const struct sys_rename_args *uap, register_t *retval) 3825 { 3826 /* { 3827 syscallarg(const char *) from; 3828 syscallarg(const char *) to; 3829 } */ 3830 3831 return (do_sys_rename(SCARG(uap, from), SCARG(uap, to), UIO_USERSPACE, 0)); 3832 } 3833 3834 int 3835 sys_renameat(struct lwp *l, const struct sys_renameat_args *uap, 3836 register_t *retval) 3837 { 3838 /* { 3839 syscallarg(int) fromfd; 3840 syscallarg(const char *) from; 3841 syscallarg(int) tofd; 3842 syscallarg(const char *) to; 3843 } */ 3844 3845 return ENOSYS; 3846 } 3847 3848 /* 3849 * Rename files, POSIX semantics frontend. 3850 */ 3851 /* ARGSUSED */ 3852 int 3853 sys___posix_rename(struct lwp *l, const struct sys___posix_rename_args *uap, register_t *retval) 3854 { 3855 /* { 3856 syscallarg(const char *) from; 3857 syscallarg(const char *) to; 3858 } */ 3859 3860 return (do_sys_rename(SCARG(uap, from), SCARG(uap, to), UIO_USERSPACE, 1)); 3861 } 3862 3863 /* 3864 * Rename files. Source and destination must either both be directories, 3865 * or both not be directories. If target is a directory, it must be empty. 3866 * If `from' and `to' refer to the same object, the value of the `retain' 3867 * argument is used to determine whether `from' will be 3868 * 3869 * (retain == 0) deleted unless `from' and `to' refer to the same 3870 * object in the file system's name space (BSD). 3871 * (retain == 1) always retained (POSIX). 3872 */ 3873 int 3874 do_sys_rename(const char *from, const char *to, enum uio_seg seg, int retain) 3875 { 3876 struct vnode *tvp, *fvp, *tdvp; 3877 struct pathbuf *frompb, *topb; 3878 struct nameidata fromnd, tond; 3879 struct mount *fs; 3880 int error; 3881 3882 error = pathbuf_maybe_copyin(from, seg, &frompb); 3883 if (error) { 3884 return error; 3885 } 3886 error = pathbuf_maybe_copyin(to, seg, &topb); 3887 if (error) { 3888 pathbuf_destroy(frompb); 3889 return error; 3890 } 3891 3892 NDINIT(&fromnd, DELETE, LOCKPARENT | TRYEMULROOT | INRENAME, 3893 frompb); 3894 if ((error = namei(&fromnd)) != 0) { 3895 pathbuf_destroy(frompb); 3896 pathbuf_destroy(topb); 3897 return (error); 3898 } 3899 if (fromnd.ni_dvp != fromnd.ni_vp) 3900 VOP_UNLOCK(fromnd.ni_dvp); 3901 fvp = fromnd.ni_vp; 3902 3903 fs = fvp->v_mount; 3904 error = VFS_RENAMELOCK_ENTER(fs); 3905 if (error) { 3906 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 3907 vrele(fromnd.ni_dvp); 3908 vrele(fvp); 3909 goto out1; 3910 } 3911 3912 /* 3913 * close, partially, yet another race - ideally we should only 3914 * go as far as getting fromnd.ni_dvp before getting the per-fs 3915 * lock, and then continue to get fromnd.ni_vp, but we can't do 3916 * that with namei as it stands. 3917 * 3918 * This still won't prevent rmdir from nuking fromnd.ni_vp 3919 * under us. The real fix is to get the locks in the right 3920 * order and do the lookups in the right places, but that's a 3921 * major rototill. 3922 * 3923 * Note: this logic (as well as this whole function) is cloned 3924 * in nfs_serv.c. Proceed accordingly. 3925 */ 3926 vrele(fvp); 3927 if ((fromnd.ni_cnd.cn_namelen == 1 && 3928 fromnd.ni_cnd.cn_nameptr[0] == '.') || 3929 (fromnd.ni_cnd.cn_namelen == 2 && 3930 fromnd.ni_cnd.cn_nameptr[0] == '.' && 3931 fromnd.ni_cnd.cn_nameptr[1] == '.')) { 3932 error = EINVAL; 3933 VFS_RENAMELOCK_EXIT(fs); 3934 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 3935 vrele(fromnd.ni_dvp); 3936 goto out1; 3937 } 3938 vn_lock(fromnd.ni_dvp, LK_EXCLUSIVE | LK_RETRY); 3939 error = relookup(fromnd.ni_dvp, &fromnd.ni_vp, &fromnd.ni_cnd, 0); 3940 if (error) { 3941 VOP_UNLOCK(fromnd.ni_dvp); 3942 VFS_RENAMELOCK_EXIT(fs); 3943 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 3944 vrele(fromnd.ni_dvp); 3945 goto out1; 3946 } 3947 VOP_UNLOCK(fromnd.ni_vp); 3948 if (fromnd.ni_dvp != fromnd.ni_vp) 3949 VOP_UNLOCK(fromnd.ni_dvp); 3950 fvp = fromnd.ni_vp; 3951 3952 NDINIT(&tond, RENAME, 3953 LOCKPARENT | LOCKLEAF | NOCACHE | TRYEMULROOT 3954 | INRENAME | (fvp->v_type == VDIR ? CREATEDIR : 0), 3955 topb); 3956 if ((error = namei(&tond)) != 0) { 3957 VFS_RENAMELOCK_EXIT(fs); 3958 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 3959 vrele(fromnd.ni_dvp); 3960 vrele(fvp); 3961 goto out1; 3962 } 3963 tdvp = tond.ni_dvp; 3964 tvp = tond.ni_vp; 3965 3966 if (tvp != NULL) { 3967 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 3968 error = ENOTDIR; 3969 goto out; 3970 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 3971 error = EISDIR; 3972 goto out; 3973 } 3974 } 3975 3976 if (fvp == tdvp) 3977 error = EINVAL; 3978 3979 /* 3980 * Source and destination refer to the same object. 3981 */ 3982 if (fvp == tvp) { 3983 if (retain) 3984 error = -1; 3985 else if (fromnd.ni_dvp == tdvp && 3986 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen && 3987 !memcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr, 3988 fromnd.ni_cnd.cn_namelen)) 3989 error = -1; 3990 } 3991 /* 3992 * Prevent cross-mount operation. 3993 */ 3994 if (error == 0) { 3995 if (tond.ni_dvp->v_mount != fromnd.ni_dvp->v_mount) { 3996 error = EXDEV; 3997 } 3998 } 3999 #if NVERIEXEC > 0 4000 if (!error) { 4001 char *f1, *f2; 4002 size_t f1_len; 4003 size_t f2_len; 4004 4005 f1_len = fromnd.ni_cnd.cn_namelen + 1; 4006 f1 = kmem_alloc(f1_len, KM_SLEEP); 4007 strlcpy(f1, fromnd.ni_cnd.cn_nameptr, f1_len); 4008 4009 f2_len = tond.ni_cnd.cn_namelen + 1; 4010 f2 = kmem_alloc(f2_len, KM_SLEEP); 4011 strlcpy(f2, tond.ni_cnd.cn_nameptr, f2_len); 4012 4013 error = veriexec_renamechk(curlwp, fvp, f1, tvp, f2); 4014 4015 kmem_free(f1, f1_len); 4016 kmem_free(f2, f2_len); 4017 } 4018 #endif /* NVERIEXEC > 0 */ 4019 4020 out: 4021 if (!error) { 4022 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 4023 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 4024 VFS_RENAMELOCK_EXIT(fs); 4025 } else { 4026 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd); 4027 if (tdvp == tvp) 4028 vrele(tdvp); 4029 else 4030 vput(tdvp); 4031 if (tvp) 4032 vput(tvp); 4033 VFS_RENAMELOCK_EXIT(fs); 4034 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 4035 vrele(fromnd.ni_dvp); 4036 vrele(fvp); 4037 } 4038 out1: 4039 pathbuf_destroy(frompb); 4040 pathbuf_destroy(topb); 4041 return (error == -1 ? 0 : error); 4042 } 4043 4044 /* 4045 * Make a directory file. 4046 */ 4047 /* ARGSUSED */ 4048 int 4049 sys_mkdir(struct lwp *l, const struct sys_mkdir_args *uap, register_t *retval) 4050 { 4051 /* { 4052 syscallarg(const char *) path; 4053 syscallarg(int) mode; 4054 } */ 4055 4056 return do_sys_mkdir(SCARG(uap, path), SCARG(uap, mode), UIO_USERSPACE); 4057 } 4058 4059 int 4060 sys_mkdirat(struct lwp *l, const struct sys_mkdirat_args *uap, 4061 register_t *retval) 4062 { 4063 /* { 4064 syscallarg(int) fd; 4065 syscallarg(const char *) path; 4066 syscallarg(int) mode; 4067 } */ 4068 4069 return ENOSYS; 4070 } 4071 4072 4073 int 4074 do_sys_mkdir(const char *path, mode_t mode, enum uio_seg seg) 4075 { 4076 struct proc *p = curlwp->l_proc; 4077 struct vnode *vp; 4078 struct vattr vattr; 4079 int error; 4080 struct pathbuf *pb; 4081 struct nameidata nd; 4082 4083 /* XXX bollocks, should pass in a pathbuf */ 4084 error = pathbuf_maybe_copyin(path, seg, &pb); 4085 if (error) { 4086 return error; 4087 } 4088 4089 NDINIT(&nd, CREATE, LOCKPARENT | CREATEDIR | TRYEMULROOT, pb); 4090 if ((error = namei(&nd)) != 0) { 4091 pathbuf_destroy(pb); 4092 return (error); 4093 } 4094 vp = nd.ni_vp; 4095 if (vp != NULL) { 4096 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 4097 if (nd.ni_dvp == vp) 4098 vrele(nd.ni_dvp); 4099 else 4100 vput(nd.ni_dvp); 4101 vrele(vp); 4102 pathbuf_destroy(pb); 4103 return (EEXIST); 4104 } 4105 vattr_null(&vattr); 4106 vattr.va_type = VDIR; 4107 /* We will read cwdi->cwdi_cmask unlocked. */ 4108 vattr.va_mode = (mode & ACCESSPERMS) &~ p->p_cwdi->cwdi_cmask; 4109 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 4110 if (!error) 4111 vput(nd.ni_vp); 4112 pathbuf_destroy(pb); 4113 return (error); 4114 } 4115 4116 /* 4117 * Remove a directory file. 4118 */ 4119 /* ARGSUSED */ 4120 int 4121 sys_rmdir(struct lwp *l, const struct sys_rmdir_args *uap, register_t *retval) 4122 { 4123 /* { 4124 syscallarg(const char *) path; 4125 } */ 4126 struct vnode *vp; 4127 int error; 4128 struct pathbuf *pb; 4129 struct nameidata nd; 4130 4131 error = pathbuf_copyin(SCARG(uap, path), &pb); 4132 if (error) { 4133 return error; 4134 } 4135 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF | TRYEMULROOT, pb); 4136 if ((error = namei(&nd)) != 0) { 4137 pathbuf_destroy(pb); 4138 return error; 4139 } 4140 vp = nd.ni_vp; 4141 if (vp->v_type != VDIR) { 4142 error = ENOTDIR; 4143 goto out; 4144 } 4145 /* 4146 * No rmdir "." please. 4147 */ 4148 if (nd.ni_dvp == vp) { 4149 error = EINVAL; 4150 goto out; 4151 } 4152 /* 4153 * The root of a mounted filesystem cannot be deleted. 4154 */ 4155 if ((vp->v_vflag & VV_ROOT) != 0 || vp->v_mountedhere != NULL) { 4156 error = EBUSY; 4157 goto out; 4158 } 4159 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 4160 pathbuf_destroy(pb); 4161 return (error); 4162 4163 out: 4164 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 4165 if (nd.ni_dvp == vp) 4166 vrele(nd.ni_dvp); 4167 else 4168 vput(nd.ni_dvp); 4169 vput(vp); 4170 pathbuf_destroy(pb); 4171 return (error); 4172 } 4173 4174 /* 4175 * Read a block of directory entries in a file system independent format. 4176 */ 4177 int 4178 sys___getdents30(struct lwp *l, const struct sys___getdents30_args *uap, register_t *retval) 4179 { 4180 /* { 4181 syscallarg(int) fd; 4182 syscallarg(char *) buf; 4183 syscallarg(size_t) count; 4184 } */ 4185 file_t *fp; 4186 int error, done; 4187 4188 /* fd_getvnode() will use the descriptor for us */ 4189 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 4190 return (error); 4191 if ((fp->f_flag & FREAD) == 0) { 4192 error = EBADF; 4193 goto out; 4194 } 4195 error = vn_readdir(fp, SCARG(uap, buf), UIO_USERSPACE, 4196 SCARG(uap, count), &done, l, 0, 0); 4197 ktrgenio(SCARG(uap, fd), UIO_READ, SCARG(uap, buf), done, error); 4198 *retval = done; 4199 out: 4200 fd_putfile(SCARG(uap, fd)); 4201 return (error); 4202 } 4203 4204 /* 4205 * Set the mode mask for creation of filesystem nodes. 4206 */ 4207 int 4208 sys_umask(struct lwp *l, const struct sys_umask_args *uap, register_t *retval) 4209 { 4210 /* { 4211 syscallarg(mode_t) newmask; 4212 } */ 4213 struct proc *p = l->l_proc; 4214 struct cwdinfo *cwdi; 4215 4216 /* 4217 * cwdi->cwdi_cmask will be read unlocked elsewhere. What's 4218 * important is that we serialize changes to the mask. The 4219 * rw_exit() will issue a write memory barrier on our behalf, 4220 * and force the changes out to other CPUs (as it must use an 4221 * atomic operation, draining the local CPU's store buffers). 4222 */ 4223 cwdi = p->p_cwdi; 4224 rw_enter(&cwdi->cwdi_lock, RW_WRITER); 4225 *retval = cwdi->cwdi_cmask; 4226 cwdi->cwdi_cmask = SCARG(uap, newmask) & ALLPERMS; 4227 rw_exit(&cwdi->cwdi_lock); 4228 4229 return (0); 4230 } 4231 4232 int 4233 dorevoke(struct vnode *vp, kauth_cred_t cred) 4234 { 4235 struct vattr vattr; 4236 int error, fs_decision; 4237 4238 vn_lock(vp, LK_SHARED | LK_RETRY); 4239 error = VOP_GETATTR(vp, &vattr, cred); 4240 VOP_UNLOCK(vp); 4241 if (error != 0) 4242 return error; 4243 fs_decision = (kauth_cred_geteuid(cred) == vattr.va_uid) ? 0 : EPERM; 4244 error = kauth_authorize_vnode(cred, KAUTH_VNODE_REVOKE, vp, NULL, 4245 fs_decision); 4246 if (!error) 4247 VOP_REVOKE(vp, REVOKEALL); 4248 return (error); 4249 } 4250 4251 /* 4252 * Void all references to file by ripping underlying filesystem 4253 * away from vnode. 4254 */ 4255 /* ARGSUSED */ 4256 int 4257 sys_revoke(struct lwp *l, const struct sys_revoke_args *uap, register_t *retval) 4258 { 4259 /* { 4260 syscallarg(const char *) path; 4261 } */ 4262 struct vnode *vp; 4263 int error; 4264 4265 error = namei_simple_user(SCARG(uap, path), 4266 NSM_FOLLOW_TRYEMULROOT, &vp); 4267 if (error != 0) 4268 return (error); 4269 error = dorevoke(vp, l->l_cred); 4270 vrele(vp); 4271 return (error); 4272 } 4273