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