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