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