1 /*- 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 4. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94 35 */ 36 37 #include <sys/cdefs.h> 38 __FBSDID("$FreeBSD$"); 39 40 #include "opt_compat.h" 41 #include "opt_mac.h" 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/bio.h> 46 #include <sys/buf.h> 47 #include <sys/sysent.h> 48 #include <sys/malloc.h> 49 #include <sys/mount.h> 50 #include <sys/mutex.h> 51 #include <sys/sysproto.h> 52 #include <sys/namei.h> 53 #include <sys/filedesc.h> 54 #include <sys/kernel.h> 55 #include <sys/fcntl.h> 56 #include <sys/file.h> 57 #include <sys/filio.h> 58 #include <sys/limits.h> 59 #include <sys/linker.h> 60 #include <sys/stat.h> 61 #include <sys/sx.h> 62 #include <sys/unistd.h> 63 #include <sys/vnode.h> 64 #include <sys/priv.h> 65 #include <sys/proc.h> 66 #include <sys/dirent.h> 67 #include <sys/jail.h> 68 #include <sys/syscallsubr.h> 69 #include <sys/sysctl.h> 70 71 #include <machine/stdarg.h> 72 73 #include <security/audit/audit.h> 74 #include <security/mac/mac_framework.h> 75 76 #include <vm/vm.h> 77 #include <vm/vm_object.h> 78 #include <vm/vm_page.h> 79 #include <vm/uma.h> 80 81 static int chroot_refuse_vdir_fds(struct filedesc *fdp); 82 static int getutimes(const struct timeval *, enum uio_seg, struct timespec *); 83 static int setfown(struct thread *td, struct vnode *, uid_t, gid_t); 84 static int setfmode(struct thread *td, struct vnode *, int); 85 static int setfflags(struct thread *td, struct vnode *, int); 86 static int setutimes(struct thread *td, struct vnode *, 87 const struct timespec *, int, int); 88 static int vn_access(struct vnode *vp, int user_flags, struct ucred *cred, 89 struct thread *td); 90 91 /* 92 * The module initialization routine for POSIX asynchronous I/O will 93 * set this to the version of AIO that it implements. (Zero means 94 * that it is not implemented.) This value is used here by pathconf() 95 * and in kern_descrip.c by fpathconf(). 96 */ 97 int async_io_version; 98 99 #ifdef DEBUG 100 static int syncprt = 0; 101 SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, ""); 102 #endif 103 104 /* 105 * Sync each mounted filesystem. 106 */ 107 #ifndef _SYS_SYSPROTO_H_ 108 struct sync_args { 109 int dummy; 110 }; 111 #endif 112 /* ARGSUSED */ 113 int 114 sync(td, uap) 115 struct thread *td; 116 struct sync_args *uap; 117 { 118 struct mount *mp, *nmp; 119 int vfslocked; 120 121 mtx_lock(&mountlist_mtx); 122 for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) { 123 if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) { 124 nmp = TAILQ_NEXT(mp, mnt_list); 125 continue; 126 } 127 vfslocked = VFS_LOCK_GIANT(mp); 128 if ((mp->mnt_flag & MNT_RDONLY) == 0 && 129 vn_start_write(NULL, &mp, V_NOWAIT) == 0) { 130 MNT_ILOCK(mp); 131 mp->mnt_noasync++; 132 mp->mnt_kern_flag &= ~MNTK_ASYNC; 133 MNT_IUNLOCK(mp); 134 vfs_msync(mp, MNT_NOWAIT); 135 VFS_SYNC(mp, MNT_NOWAIT, td); 136 MNT_ILOCK(mp); 137 mp->mnt_noasync--; 138 if ((mp->mnt_flag & MNT_ASYNC) != 0 && 139 mp->mnt_noasync == 0) 140 mp->mnt_kern_flag |= MNTK_ASYNC; 141 MNT_IUNLOCK(mp); 142 vn_finished_write(mp); 143 } 144 VFS_UNLOCK_GIANT(vfslocked); 145 mtx_lock(&mountlist_mtx); 146 nmp = TAILQ_NEXT(mp, mnt_list); 147 vfs_unbusy(mp, td); 148 } 149 mtx_unlock(&mountlist_mtx); 150 return (0); 151 } 152 153 /* XXX PRISON: could be per prison flag */ 154 static int prison_quotas; 155 #if 0 156 SYSCTL_INT(_kern_prison, OID_AUTO, quotas, CTLFLAG_RW, &prison_quotas, 0, ""); 157 #endif 158 159 /* 160 * Change filesystem quotas. 161 */ 162 #ifndef _SYS_SYSPROTO_H_ 163 struct quotactl_args { 164 char *path; 165 int cmd; 166 int uid; 167 caddr_t arg; 168 }; 169 #endif 170 int 171 quotactl(td, uap) 172 struct thread *td; 173 register struct quotactl_args /* { 174 char *path; 175 int cmd; 176 int uid; 177 caddr_t arg; 178 } */ *uap; 179 { 180 struct mount *mp; 181 int vfslocked; 182 int error; 183 struct nameidata nd; 184 185 AUDIT_ARG(cmd, uap->cmd); 186 AUDIT_ARG(uid, uap->uid); 187 if (jailed(td->td_ucred) && !prison_quotas) 188 return (EPERM); 189 NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, 190 UIO_USERSPACE, uap->path, td); 191 if ((error = namei(&nd)) != 0) 192 return (error); 193 vfslocked = NDHASGIANT(&nd); 194 NDFREE(&nd, NDF_ONLY_PNBUF); 195 mp = nd.ni_vp->v_mount; 196 if ((error = vfs_busy(mp, 0, NULL, td))) { 197 vrele(nd.ni_vp); 198 VFS_UNLOCK_GIANT(vfslocked); 199 return (error); 200 } 201 vrele(nd.ni_vp); 202 error = VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, td); 203 vfs_unbusy(mp, td); 204 VFS_UNLOCK_GIANT(vfslocked); 205 return (error); 206 } 207 208 /* 209 * Get filesystem statistics. 210 */ 211 #ifndef _SYS_SYSPROTO_H_ 212 struct statfs_args { 213 char *path; 214 struct statfs *buf; 215 }; 216 #endif 217 int 218 statfs(td, uap) 219 struct thread *td; 220 register struct statfs_args /* { 221 char *path; 222 struct statfs *buf; 223 } */ *uap; 224 { 225 struct statfs sf; 226 int error; 227 228 error = kern_statfs(td, uap->path, UIO_USERSPACE, &sf); 229 if (error == 0) 230 error = copyout(&sf, uap->buf, sizeof(sf)); 231 return (error); 232 } 233 234 int 235 kern_statfs(struct thread *td, char *path, enum uio_seg pathseg, 236 struct statfs *buf) 237 { 238 struct mount *mp; 239 struct statfs *sp, sb; 240 int vfslocked; 241 int error; 242 struct nameidata nd; 243 244 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, 245 pathseg, path, td); 246 error = namei(&nd); 247 if (error) 248 return (error); 249 vfslocked = NDHASGIANT(&nd); 250 mp = nd.ni_vp->v_mount; 251 vfs_ref(mp); 252 NDFREE(&nd, NDF_ONLY_PNBUF); 253 vput(nd.ni_vp); 254 #ifdef MAC 255 error = mac_check_mount_stat(td->td_ucred, mp); 256 if (error) 257 goto out; 258 #endif 259 /* 260 * Set these in case the underlying filesystem fails to do so. 261 */ 262 sp = &mp->mnt_stat; 263 sp->f_version = STATFS_VERSION; 264 sp->f_namemax = NAME_MAX; 265 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 266 error = VFS_STATFS(mp, sp, td); 267 if (error) 268 goto out; 269 if (priv_check(td, PRIV_VFS_GENERATION)) { 270 bcopy(sp, &sb, sizeof(sb)); 271 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; 272 prison_enforce_statfs(td->td_ucred, mp, &sb); 273 sp = &sb; 274 } 275 *buf = *sp; 276 out: 277 vfs_rel(mp); 278 VFS_UNLOCK_GIANT(vfslocked); 279 if (mtx_owned(&Giant)) 280 printf("statfs(%d): %s: %d\n", vfslocked, path, error); 281 return (error); 282 } 283 284 /* 285 * Get filesystem statistics. 286 */ 287 #ifndef _SYS_SYSPROTO_H_ 288 struct fstatfs_args { 289 int fd; 290 struct statfs *buf; 291 }; 292 #endif 293 int 294 fstatfs(td, uap) 295 struct thread *td; 296 register struct fstatfs_args /* { 297 int fd; 298 struct statfs *buf; 299 } */ *uap; 300 { 301 struct statfs sf; 302 int error; 303 304 error = kern_fstatfs(td, uap->fd, &sf); 305 if (error == 0) 306 error = copyout(&sf, uap->buf, sizeof(sf)); 307 return (error); 308 } 309 310 int 311 kern_fstatfs(struct thread *td, int fd, struct statfs *buf) 312 { 313 struct file *fp; 314 struct mount *mp; 315 struct statfs *sp, sb; 316 int vfslocked; 317 struct vnode *vp; 318 int error; 319 320 AUDIT_ARG(fd, fd); 321 error = getvnode(td->td_proc->p_fd, fd, &fp); 322 if (error) 323 return (error); 324 vp = fp->f_vnode; 325 vfslocked = VFS_LOCK_GIANT(vp->v_mount); 326 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 327 #ifdef AUDIT 328 AUDIT_ARG(vnode, vp, ARG_VNODE1); 329 #endif 330 mp = vp->v_mount; 331 if (mp) 332 vfs_ref(mp); 333 VOP_UNLOCK(vp, 0, td); 334 fdrop(fp, td); 335 if (vp->v_iflag & VI_DOOMED) { 336 error = EBADF; 337 goto out; 338 } 339 #ifdef MAC 340 error = mac_check_mount_stat(td->td_ucred, mp); 341 if (error) 342 goto out; 343 #endif 344 /* 345 * Set these in case the underlying filesystem fails to do so. 346 */ 347 sp = &mp->mnt_stat; 348 sp->f_version = STATFS_VERSION; 349 sp->f_namemax = NAME_MAX; 350 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 351 error = VFS_STATFS(mp, sp, td); 352 if (error) 353 goto out; 354 if (priv_check(td, PRIV_VFS_GENERATION)) { 355 bcopy(sp, &sb, sizeof(sb)); 356 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; 357 prison_enforce_statfs(td->td_ucred, mp, &sb); 358 sp = &sb; 359 } 360 *buf = *sp; 361 out: 362 if (mp) 363 vfs_rel(mp); 364 VFS_UNLOCK_GIANT(vfslocked); 365 return (error); 366 } 367 368 /* 369 * Get statistics on all filesystems. 370 */ 371 #ifndef _SYS_SYSPROTO_H_ 372 struct getfsstat_args { 373 struct statfs *buf; 374 long bufsize; 375 int flags; 376 }; 377 #endif 378 int 379 getfsstat(td, uap) 380 struct thread *td; 381 register struct getfsstat_args /* { 382 struct statfs *buf; 383 long bufsize; 384 int flags; 385 } */ *uap; 386 { 387 388 return (kern_getfsstat(td, &uap->buf, uap->bufsize, UIO_USERSPACE, 389 uap->flags)); 390 } 391 392 /* 393 * If (bufsize > 0 && bufseg == UIO_SYSSPACE) 394 * The caller is responsible for freeing memory which will be allocated 395 * in '*buf'. 396 */ 397 int 398 kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize, 399 enum uio_seg bufseg, int flags) 400 { 401 struct mount *mp, *nmp; 402 struct statfs *sfsp, *sp, sb; 403 size_t count, maxcount; 404 int vfslocked; 405 int error; 406 407 maxcount = bufsize / sizeof(struct statfs); 408 if (bufsize == 0) 409 sfsp = NULL; 410 else if (bufseg == UIO_USERSPACE) 411 sfsp = *buf; 412 else /* if (bufseg == UIO_SYSSPACE) */ { 413 count = 0; 414 mtx_lock(&mountlist_mtx); 415 TAILQ_FOREACH(mp, &mountlist, mnt_list) { 416 count++; 417 } 418 mtx_unlock(&mountlist_mtx); 419 if (maxcount > count) 420 maxcount = count; 421 sfsp = *buf = malloc(maxcount * sizeof(struct statfs), M_TEMP, 422 M_WAITOK); 423 } 424 count = 0; 425 mtx_lock(&mountlist_mtx); 426 for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) { 427 if (prison_canseemount(td->td_ucred, mp) != 0) { 428 nmp = TAILQ_NEXT(mp, mnt_list); 429 continue; 430 } 431 #ifdef MAC 432 if (mac_check_mount_stat(td->td_ucred, mp) != 0) { 433 nmp = TAILQ_NEXT(mp, mnt_list); 434 continue; 435 } 436 #endif 437 if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) { 438 nmp = TAILQ_NEXT(mp, mnt_list); 439 continue; 440 } 441 vfslocked = VFS_LOCK_GIANT(mp); 442 if (sfsp && count < maxcount) { 443 sp = &mp->mnt_stat; 444 /* 445 * Set these in case the underlying filesystem 446 * fails to do so. 447 */ 448 sp->f_version = STATFS_VERSION; 449 sp->f_namemax = NAME_MAX; 450 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 451 /* 452 * If MNT_NOWAIT or MNT_LAZY is specified, do not 453 * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY 454 * overrides MNT_WAIT. 455 */ 456 if (((flags & (MNT_LAZY|MNT_NOWAIT)) == 0 || 457 (flags & MNT_WAIT)) && 458 (error = VFS_STATFS(mp, sp, td))) { 459 VFS_UNLOCK_GIANT(vfslocked); 460 mtx_lock(&mountlist_mtx); 461 nmp = TAILQ_NEXT(mp, mnt_list); 462 vfs_unbusy(mp, td); 463 continue; 464 } 465 if (priv_check(td, PRIV_VFS_GENERATION)) { 466 bcopy(sp, &sb, sizeof(sb)); 467 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; 468 prison_enforce_statfs(td->td_ucred, mp, &sb); 469 sp = &sb; 470 } 471 if (bufseg == UIO_SYSSPACE) 472 bcopy(sp, sfsp, sizeof(*sp)); 473 else /* if (bufseg == UIO_USERSPACE) */ { 474 error = copyout(sp, sfsp, sizeof(*sp)); 475 if (error) { 476 vfs_unbusy(mp, td); 477 VFS_UNLOCK_GIANT(vfslocked); 478 return (error); 479 } 480 } 481 sfsp++; 482 } 483 VFS_UNLOCK_GIANT(vfslocked); 484 count++; 485 mtx_lock(&mountlist_mtx); 486 nmp = TAILQ_NEXT(mp, mnt_list); 487 vfs_unbusy(mp, td); 488 } 489 mtx_unlock(&mountlist_mtx); 490 if (sfsp && count > maxcount) 491 td->td_retval[0] = maxcount; 492 else 493 td->td_retval[0] = count; 494 return (0); 495 } 496 497 #ifdef COMPAT_FREEBSD4 498 /* 499 * Get old format filesystem statistics. 500 */ 501 static void cvtstatfs(struct statfs *, struct ostatfs *); 502 503 #ifndef _SYS_SYSPROTO_H_ 504 struct freebsd4_statfs_args { 505 char *path; 506 struct ostatfs *buf; 507 }; 508 #endif 509 int 510 freebsd4_statfs(td, uap) 511 struct thread *td; 512 struct freebsd4_statfs_args /* { 513 char *path; 514 struct ostatfs *buf; 515 } */ *uap; 516 { 517 struct ostatfs osb; 518 struct statfs sf; 519 int error; 520 521 error = kern_statfs(td, uap->path, UIO_USERSPACE, &sf); 522 if (error) 523 return (error); 524 cvtstatfs(&sf, &osb); 525 return (copyout(&osb, uap->buf, sizeof(osb))); 526 } 527 528 /* 529 * Get filesystem statistics. 530 */ 531 #ifndef _SYS_SYSPROTO_H_ 532 struct freebsd4_fstatfs_args { 533 int fd; 534 struct ostatfs *buf; 535 }; 536 #endif 537 int 538 freebsd4_fstatfs(td, uap) 539 struct thread *td; 540 struct freebsd4_fstatfs_args /* { 541 int fd; 542 struct ostatfs *buf; 543 } */ *uap; 544 { 545 struct ostatfs osb; 546 struct statfs sf; 547 int error; 548 549 error = kern_fstatfs(td, uap->fd, &sf); 550 if (error) 551 return (error); 552 cvtstatfs(&sf, &osb); 553 return (copyout(&osb, uap->buf, sizeof(osb))); 554 } 555 556 /* 557 * Get statistics on all filesystems. 558 */ 559 #ifndef _SYS_SYSPROTO_H_ 560 struct freebsd4_getfsstat_args { 561 struct ostatfs *buf; 562 long bufsize; 563 int flags; 564 }; 565 #endif 566 int 567 freebsd4_getfsstat(td, uap) 568 struct thread *td; 569 register struct freebsd4_getfsstat_args /* { 570 struct ostatfs *buf; 571 long bufsize; 572 int flags; 573 } */ *uap; 574 { 575 struct statfs *buf, *sp; 576 struct ostatfs osb; 577 size_t count, size; 578 int error; 579 580 count = uap->bufsize / sizeof(struct ostatfs); 581 size = count * sizeof(struct statfs); 582 error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags); 583 if (size > 0) { 584 count = td->td_retval[0]; 585 sp = buf; 586 while (count > 0 && error == 0) { 587 cvtstatfs(sp, &osb); 588 error = copyout(&osb, uap->buf, sizeof(osb)); 589 sp++; 590 uap->buf++; 591 count--; 592 } 593 free(buf, M_TEMP); 594 } 595 return (error); 596 } 597 598 /* 599 * Implement fstatfs() for (NFS) file handles. 600 */ 601 #ifndef _SYS_SYSPROTO_H_ 602 struct freebsd4_fhstatfs_args { 603 struct fhandle *u_fhp; 604 struct ostatfs *buf; 605 }; 606 #endif 607 int 608 freebsd4_fhstatfs(td, uap) 609 struct thread *td; 610 struct freebsd4_fhstatfs_args /* { 611 struct fhandle *u_fhp; 612 struct ostatfs *buf; 613 } */ *uap; 614 { 615 struct ostatfs osb; 616 struct statfs sf; 617 fhandle_t fh; 618 int error; 619 620 error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t)); 621 if (error) 622 return (error); 623 error = kern_fhstatfs(td, fh, &sf); 624 if (error) 625 return (error); 626 cvtstatfs(&sf, &osb); 627 return (copyout(&osb, uap->buf, sizeof(osb))); 628 } 629 630 /* 631 * Convert a new format statfs structure to an old format statfs structure. 632 */ 633 static void 634 cvtstatfs(nsp, osp) 635 struct statfs *nsp; 636 struct ostatfs *osp; 637 { 638 639 bzero(osp, sizeof(*osp)); 640 osp->f_bsize = MIN(nsp->f_bsize, LONG_MAX); 641 osp->f_iosize = MIN(nsp->f_iosize, LONG_MAX); 642 osp->f_blocks = MIN(nsp->f_blocks, LONG_MAX); 643 osp->f_bfree = MIN(nsp->f_bfree, LONG_MAX); 644 osp->f_bavail = MIN(nsp->f_bavail, LONG_MAX); 645 osp->f_files = MIN(nsp->f_files, LONG_MAX); 646 osp->f_ffree = MIN(nsp->f_ffree, LONG_MAX); 647 osp->f_owner = nsp->f_owner; 648 osp->f_type = nsp->f_type; 649 osp->f_flags = nsp->f_flags; 650 osp->f_syncwrites = MIN(nsp->f_syncwrites, LONG_MAX); 651 osp->f_asyncwrites = MIN(nsp->f_asyncwrites, LONG_MAX); 652 osp->f_syncreads = MIN(nsp->f_syncreads, LONG_MAX); 653 osp->f_asyncreads = MIN(nsp->f_asyncreads, LONG_MAX); 654 strlcpy(osp->f_fstypename, nsp->f_fstypename, 655 MIN(MFSNAMELEN, OMFSNAMELEN)); 656 strlcpy(osp->f_mntonname, nsp->f_mntonname, 657 MIN(MNAMELEN, OMNAMELEN)); 658 strlcpy(osp->f_mntfromname, nsp->f_mntfromname, 659 MIN(MNAMELEN, OMNAMELEN)); 660 osp->f_fsid = nsp->f_fsid; 661 } 662 #endif /* COMPAT_FREEBSD4 */ 663 664 /* 665 * Change current working directory to a given file descriptor. 666 */ 667 #ifndef _SYS_SYSPROTO_H_ 668 struct fchdir_args { 669 int fd; 670 }; 671 #endif 672 int 673 fchdir(td, uap) 674 struct thread *td; 675 struct fchdir_args /* { 676 int fd; 677 } */ *uap; 678 { 679 register struct filedesc *fdp = td->td_proc->p_fd; 680 struct vnode *vp, *tdp, *vpold; 681 struct mount *mp; 682 struct file *fp; 683 int vfslocked; 684 int error; 685 686 AUDIT_ARG(fd, uap->fd); 687 if ((error = getvnode(fdp, uap->fd, &fp)) != 0) 688 return (error); 689 vp = fp->f_vnode; 690 VREF(vp); 691 fdrop(fp, td); 692 vfslocked = VFS_LOCK_GIANT(vp->v_mount); 693 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 694 AUDIT_ARG(vnode, vp, ARG_VNODE1); 695 error = change_dir(vp, td); 696 while (!error && (mp = vp->v_mountedhere) != NULL) { 697 int tvfslocked; 698 if (vfs_busy(mp, 0, 0, td)) 699 continue; 700 tvfslocked = VFS_LOCK_GIANT(mp); 701 error = VFS_ROOT(mp, LK_EXCLUSIVE, &tdp, td); 702 vfs_unbusy(mp, td); 703 if (error) { 704 VFS_UNLOCK_GIANT(tvfslocked); 705 break; 706 } 707 vput(vp); 708 VFS_UNLOCK_GIANT(vfslocked); 709 vp = tdp; 710 vfslocked = tvfslocked; 711 } 712 if (error) { 713 vput(vp); 714 VFS_UNLOCK_GIANT(vfslocked); 715 return (error); 716 } 717 VOP_UNLOCK(vp, 0, td); 718 VFS_UNLOCK_GIANT(vfslocked); 719 FILEDESC_XLOCK(fdp); 720 vpold = fdp->fd_cdir; 721 fdp->fd_cdir = vp; 722 FILEDESC_XUNLOCK(fdp); 723 vfslocked = VFS_LOCK_GIANT(vpold->v_mount); 724 vrele(vpold); 725 VFS_UNLOCK_GIANT(vfslocked); 726 return (0); 727 } 728 729 /* 730 * Change current working directory (``.''). 731 */ 732 #ifndef _SYS_SYSPROTO_H_ 733 struct chdir_args { 734 char *path; 735 }; 736 #endif 737 int 738 chdir(td, uap) 739 struct thread *td; 740 struct chdir_args /* { 741 char *path; 742 } */ *uap; 743 { 744 745 return (kern_chdir(td, uap->path, UIO_USERSPACE)); 746 } 747 748 int 749 kern_chdir(struct thread *td, char *path, enum uio_seg pathseg) 750 { 751 register struct filedesc *fdp = td->td_proc->p_fd; 752 int error; 753 struct nameidata nd; 754 struct vnode *vp; 755 int vfslocked; 756 757 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1 | MPSAFE, 758 pathseg, path, td); 759 if ((error = namei(&nd)) != 0) 760 return (error); 761 vfslocked = NDHASGIANT(&nd); 762 if ((error = change_dir(nd.ni_vp, td)) != 0) { 763 vput(nd.ni_vp); 764 VFS_UNLOCK_GIANT(vfslocked); 765 NDFREE(&nd, NDF_ONLY_PNBUF); 766 return (error); 767 } 768 VOP_UNLOCK(nd.ni_vp, 0, td); 769 VFS_UNLOCK_GIANT(vfslocked); 770 NDFREE(&nd, NDF_ONLY_PNBUF); 771 FILEDESC_XLOCK(fdp); 772 vp = fdp->fd_cdir; 773 fdp->fd_cdir = nd.ni_vp; 774 FILEDESC_XUNLOCK(fdp); 775 vfslocked = VFS_LOCK_GIANT(vp->v_mount); 776 vrele(vp); 777 VFS_UNLOCK_GIANT(vfslocked); 778 return (0); 779 } 780 781 /* 782 * Helper function for raised chroot(2) security function: Refuse if 783 * any filedescriptors are open directories. 784 */ 785 static int 786 chroot_refuse_vdir_fds(fdp) 787 struct filedesc *fdp; 788 { 789 struct vnode *vp; 790 struct file *fp; 791 int fd; 792 793 FILEDESC_LOCK_ASSERT(fdp); 794 795 for (fd = 0; fd < fdp->fd_nfiles ; fd++) { 796 fp = fget_locked(fdp, fd); 797 if (fp == NULL) 798 continue; 799 if (fp->f_type == DTYPE_VNODE) { 800 vp = fp->f_vnode; 801 if (vp->v_type == VDIR) 802 return (EPERM); 803 } 804 } 805 return (0); 806 } 807 808 /* 809 * This sysctl determines if we will allow a process to chroot(2) if it 810 * has a directory open: 811 * 0: disallowed for all processes. 812 * 1: allowed for processes that were not already chroot(2)'ed. 813 * 2: allowed for all processes. 814 */ 815 816 static int chroot_allow_open_directories = 1; 817 818 SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW, 819 &chroot_allow_open_directories, 0, ""); 820 821 /* 822 * Change notion of root (``/'') directory. 823 */ 824 #ifndef _SYS_SYSPROTO_H_ 825 struct chroot_args { 826 char *path; 827 }; 828 #endif 829 int 830 chroot(td, uap) 831 struct thread *td; 832 struct chroot_args /* { 833 char *path; 834 } */ *uap; 835 { 836 int error; 837 struct nameidata nd; 838 int vfslocked; 839 840 error = priv_check_cred(td->td_ucred, PRIV_VFS_CHROOT, 841 SUSER_ALLOWJAIL); 842 if (error) 843 return (error); 844 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, 845 UIO_USERSPACE, uap->path, td); 846 error = namei(&nd); 847 if (error) 848 goto error; 849 vfslocked = NDHASGIANT(&nd); 850 if ((error = change_dir(nd.ni_vp, td)) != 0) 851 goto e_vunlock; 852 #ifdef MAC 853 if ((error = mac_check_vnode_chroot(td->td_ucred, nd.ni_vp))) 854 goto e_vunlock; 855 #endif 856 VOP_UNLOCK(nd.ni_vp, 0, td); 857 error = change_root(nd.ni_vp, td); 858 vrele(nd.ni_vp); 859 VFS_UNLOCK_GIANT(vfslocked); 860 NDFREE(&nd, NDF_ONLY_PNBUF); 861 return (error); 862 e_vunlock: 863 vput(nd.ni_vp); 864 VFS_UNLOCK_GIANT(vfslocked); 865 error: 866 NDFREE(&nd, NDF_ONLY_PNBUF); 867 return (error); 868 } 869 870 /* 871 * Common routine for chroot and chdir. Callers must provide a locked vnode 872 * instance. 873 */ 874 int 875 change_dir(vp, td) 876 struct vnode *vp; 877 struct thread *td; 878 { 879 int error; 880 881 ASSERT_VOP_LOCKED(vp, "change_dir(): vp not locked"); 882 if (vp->v_type != VDIR) 883 return (ENOTDIR); 884 #ifdef MAC 885 error = mac_check_vnode_chdir(td->td_ucred, vp); 886 if (error) 887 return (error); 888 #endif 889 error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td); 890 return (error); 891 } 892 893 /* 894 * Common routine for kern_chroot() and jail_attach(). The caller is 895 * responsible for invoking priv_check() and mac_check_chroot() to authorize 896 * this operation. 897 */ 898 int 899 change_root(vp, td) 900 struct vnode *vp; 901 struct thread *td; 902 { 903 struct filedesc *fdp; 904 struct vnode *oldvp; 905 int vfslocked; 906 int error; 907 908 VFS_ASSERT_GIANT(vp->v_mount); 909 fdp = td->td_proc->p_fd; 910 FILEDESC_XLOCK(fdp); 911 if (chroot_allow_open_directories == 0 || 912 (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) { 913 error = chroot_refuse_vdir_fds(fdp); 914 if (error) { 915 FILEDESC_XUNLOCK(fdp); 916 return (error); 917 } 918 } 919 oldvp = fdp->fd_rdir; 920 fdp->fd_rdir = vp; 921 VREF(fdp->fd_rdir); 922 if (!fdp->fd_jdir) { 923 fdp->fd_jdir = vp; 924 VREF(fdp->fd_jdir); 925 } 926 FILEDESC_XUNLOCK(fdp); 927 vfslocked = VFS_LOCK_GIANT(oldvp->v_mount); 928 vrele(oldvp); 929 VFS_UNLOCK_GIANT(vfslocked); 930 return (0); 931 } 932 933 /* 934 * Check permissions, allocate an open file structure, and call the device 935 * open routine if any. 936 */ 937 #ifndef _SYS_SYSPROTO_H_ 938 struct open_args { 939 char *path; 940 int flags; 941 int mode; 942 }; 943 #endif 944 int 945 open(td, uap) 946 struct thread *td; 947 register struct open_args /* { 948 char *path; 949 int flags; 950 int mode; 951 } */ *uap; 952 { 953 954 return kern_open(td, uap->path, UIO_USERSPACE, uap->flags, uap->mode); 955 } 956 957 int 958 kern_open(struct thread *td, char *path, enum uio_seg pathseg, int flags, 959 int mode) 960 { 961 struct proc *p = td->td_proc; 962 struct filedesc *fdp = p->p_fd; 963 struct file *fp; 964 struct vnode *vp; 965 struct vattr vat; 966 struct mount *mp; 967 int cmode; 968 struct file *nfp; 969 int type, indx, error; 970 struct flock lf; 971 struct nameidata nd; 972 int vfslocked; 973 974 AUDIT_ARG(fflags, flags); 975 AUDIT_ARG(mode, mode); 976 if ((flags & O_ACCMODE) == O_ACCMODE) 977 return (EINVAL); 978 flags = FFLAGS(flags); 979 error = falloc(td, &nfp, &indx); 980 if (error) 981 return (error); 982 /* An extra reference on `nfp' has been held for us by falloc(). */ 983 fp = nfp; 984 cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; 985 NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1 | MPSAFE, pathseg, path, td); 986 td->td_dupfd = -1; /* XXX check for fdopen */ 987 error = vn_open(&nd, &flags, cmode, indx); 988 if (error) { 989 /* 990 * If the vn_open replaced the method vector, something 991 * wonderous happened deep below and we just pass it up 992 * pretending we know what we do. 993 */ 994 if (error == ENXIO && fp->f_ops != &badfileops) { 995 fdrop(fp, td); 996 td->td_retval[0] = indx; 997 return (0); 998 } 999 1000 /* 1001 * handle special fdopen() case. bleh. dupfdopen() is 1002 * responsible for dropping the old contents of ofiles[indx] 1003 * if it succeeds. 1004 */ 1005 if ((error == ENODEV || error == ENXIO) && 1006 td->td_dupfd >= 0 && /* XXX from fdopen */ 1007 (error = 1008 dupfdopen(td, fdp, indx, td->td_dupfd, flags, error)) == 0) { 1009 td->td_retval[0] = indx; 1010 fdrop(fp, td); 1011 return (0); 1012 } 1013 /* 1014 * Clean up the descriptor, but only if another thread hadn't 1015 * replaced or closed it. 1016 */ 1017 fdclose(fdp, fp, indx, td); 1018 fdrop(fp, td); 1019 1020 if (error == ERESTART) 1021 error = EINTR; 1022 return (error); 1023 } 1024 td->td_dupfd = 0; 1025 vfslocked = NDHASGIANT(&nd); 1026 NDFREE(&nd, NDF_ONLY_PNBUF); 1027 vp = nd.ni_vp; 1028 1029 FILE_LOCK(fp); 1030 fp->f_vnode = vp; 1031 if (fp->f_data == NULL) 1032 fp->f_data = vp; 1033 fp->f_flag = flags & FMASK; 1034 fp->f_seqcount = 1; 1035 fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE); 1036 if (fp->f_ops == &badfileops) 1037 fp->f_ops = &vnops; 1038 FILE_UNLOCK(fp); 1039 1040 VOP_UNLOCK(vp, 0, td); 1041 if (flags & (O_EXLOCK | O_SHLOCK)) { 1042 lf.l_whence = SEEK_SET; 1043 lf.l_start = 0; 1044 lf.l_len = 0; 1045 if (flags & O_EXLOCK) 1046 lf.l_type = F_WRLCK; 1047 else 1048 lf.l_type = F_RDLCK; 1049 type = F_FLOCK; 1050 if ((flags & FNONBLOCK) == 0) 1051 type |= F_WAIT; 1052 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, 1053 type)) != 0) 1054 goto bad; 1055 fp->f_flag |= FHASLOCK; 1056 } 1057 if (flags & O_TRUNC) { 1058 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 1059 goto bad; 1060 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 1061 VATTR_NULL(&vat); 1062 vat.va_size = 0; 1063 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 1064 #ifdef MAC 1065 error = mac_check_vnode_write(td->td_ucred, fp->f_cred, vp); 1066 if (error == 0) 1067 #endif 1068 error = VOP_SETATTR(vp, &vat, td->td_ucred, td); 1069 VOP_UNLOCK(vp, 0, td); 1070 vn_finished_write(mp); 1071 if (error) 1072 goto bad; 1073 } 1074 VFS_UNLOCK_GIANT(vfslocked); 1075 /* 1076 * Release our private reference, leaving the one associated with 1077 * the descriptor table intact. 1078 */ 1079 fdrop(fp, td); 1080 td->td_retval[0] = indx; 1081 return (0); 1082 bad: 1083 VFS_UNLOCK_GIANT(vfslocked); 1084 fdclose(fdp, fp, indx, td); 1085 fdrop(fp, td); 1086 return (error); 1087 } 1088 1089 #ifdef COMPAT_43 1090 /* 1091 * Create a file. 1092 */ 1093 #ifndef _SYS_SYSPROTO_H_ 1094 struct ocreat_args { 1095 char *path; 1096 int mode; 1097 }; 1098 #endif 1099 int 1100 ocreat(td, uap) 1101 struct thread *td; 1102 register struct ocreat_args /* { 1103 char *path; 1104 int mode; 1105 } */ *uap; 1106 { 1107 1108 return (kern_open(td, uap->path, UIO_USERSPACE, 1109 O_WRONLY | O_CREAT | O_TRUNC, uap->mode)); 1110 } 1111 #endif /* COMPAT_43 */ 1112 1113 /* 1114 * Create a special file. 1115 */ 1116 #ifndef _SYS_SYSPROTO_H_ 1117 struct mknod_args { 1118 char *path; 1119 int mode; 1120 int dev; 1121 }; 1122 #endif 1123 int 1124 mknod(td, uap) 1125 struct thread *td; 1126 register struct mknod_args /* { 1127 char *path; 1128 int mode; 1129 int dev; 1130 } */ *uap; 1131 { 1132 1133 return (kern_mknod(td, uap->path, UIO_USERSPACE, uap->mode, uap->dev)); 1134 } 1135 1136 int 1137 kern_mknod(struct thread *td, char *path, enum uio_seg pathseg, int mode, 1138 int dev) 1139 { 1140 struct vnode *vp; 1141 struct mount *mp; 1142 struct vattr vattr; 1143 int error; 1144 int whiteout = 0; 1145 struct nameidata nd; 1146 int vfslocked; 1147 1148 AUDIT_ARG(mode, mode); 1149 AUDIT_ARG(dev, dev); 1150 switch (mode & S_IFMT) { 1151 case S_IFCHR: 1152 case S_IFBLK: 1153 error = priv_check(td, PRIV_VFS_MKNOD_DEV); 1154 break; 1155 case S_IFMT: 1156 error = priv_check(td, PRIV_VFS_MKNOD_BAD); 1157 break; 1158 case S_IFWHT: 1159 error = priv_check(td, PRIV_VFS_MKNOD_WHT); 1160 break; 1161 default: 1162 error = EINVAL; 1163 break; 1164 } 1165 if (error) 1166 return (error); 1167 restart: 1168 bwillwrite(); 1169 NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1, 1170 pathseg, path, td); 1171 if ((error = namei(&nd)) != 0) 1172 return (error); 1173 vfslocked = NDHASGIANT(&nd); 1174 vp = nd.ni_vp; 1175 if (vp != NULL) { 1176 NDFREE(&nd, NDF_ONLY_PNBUF); 1177 if (vp == nd.ni_dvp) 1178 vrele(nd.ni_dvp); 1179 else 1180 vput(nd.ni_dvp); 1181 vrele(vp); 1182 VFS_UNLOCK_GIANT(vfslocked); 1183 return (EEXIST); 1184 } else { 1185 VATTR_NULL(&vattr); 1186 FILEDESC_SLOCK(td->td_proc->p_fd); 1187 vattr.va_mode = (mode & ALLPERMS) & 1188 ~td->td_proc->p_fd->fd_cmask; 1189 FILEDESC_SUNLOCK(td->td_proc->p_fd); 1190 vattr.va_rdev = dev; 1191 whiteout = 0; 1192 1193 switch (mode & S_IFMT) { 1194 case S_IFMT: /* used by badsect to flag bad sectors */ 1195 vattr.va_type = VBAD; 1196 break; 1197 case S_IFCHR: 1198 vattr.va_type = VCHR; 1199 break; 1200 case S_IFBLK: 1201 vattr.va_type = VBLK; 1202 break; 1203 case S_IFWHT: 1204 whiteout = 1; 1205 break; 1206 default: 1207 panic("kern_mknod: invalid mode"); 1208 } 1209 } 1210 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1211 NDFREE(&nd, NDF_ONLY_PNBUF); 1212 vput(nd.ni_dvp); 1213 VFS_UNLOCK_GIANT(vfslocked); 1214 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 1215 return (error); 1216 goto restart; 1217 } 1218 #ifdef MAC 1219 if (error == 0 && !whiteout) 1220 error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, 1221 &nd.ni_cnd, &vattr); 1222 #endif 1223 if (!error) { 1224 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); 1225 if (whiteout) 1226 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE); 1227 else { 1228 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, 1229 &nd.ni_cnd, &vattr); 1230 if (error == 0) 1231 vput(nd.ni_vp); 1232 } 1233 } 1234 NDFREE(&nd, NDF_ONLY_PNBUF); 1235 vput(nd.ni_dvp); 1236 vn_finished_write(mp); 1237 VFS_UNLOCK_GIANT(vfslocked); 1238 return (error); 1239 } 1240 1241 /* 1242 * Create a named pipe. 1243 */ 1244 #ifndef _SYS_SYSPROTO_H_ 1245 struct mkfifo_args { 1246 char *path; 1247 int mode; 1248 }; 1249 #endif 1250 int 1251 mkfifo(td, uap) 1252 struct thread *td; 1253 register struct mkfifo_args /* { 1254 char *path; 1255 int mode; 1256 } */ *uap; 1257 { 1258 1259 return (kern_mkfifo(td, uap->path, UIO_USERSPACE, uap->mode)); 1260 } 1261 1262 int 1263 kern_mkfifo(struct thread *td, char *path, enum uio_seg pathseg, int mode) 1264 { 1265 struct mount *mp; 1266 struct vattr vattr; 1267 int error; 1268 struct nameidata nd; 1269 int vfslocked; 1270 1271 AUDIT_ARG(mode, mode); 1272 restart: 1273 bwillwrite(); 1274 NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1, 1275 pathseg, path, td); 1276 if ((error = namei(&nd)) != 0) 1277 return (error); 1278 vfslocked = NDHASGIANT(&nd); 1279 if (nd.ni_vp != NULL) { 1280 NDFREE(&nd, NDF_ONLY_PNBUF); 1281 if (nd.ni_vp == nd.ni_dvp) 1282 vrele(nd.ni_dvp); 1283 else 1284 vput(nd.ni_dvp); 1285 vrele(nd.ni_vp); 1286 VFS_UNLOCK_GIANT(vfslocked); 1287 return (EEXIST); 1288 } 1289 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1290 NDFREE(&nd, NDF_ONLY_PNBUF); 1291 vput(nd.ni_dvp); 1292 VFS_UNLOCK_GIANT(vfslocked); 1293 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 1294 return (error); 1295 goto restart; 1296 } 1297 VATTR_NULL(&vattr); 1298 vattr.va_type = VFIFO; 1299 FILEDESC_SLOCK(td->td_proc->p_fd); 1300 vattr.va_mode = (mode & ALLPERMS) & ~td->td_proc->p_fd->fd_cmask; 1301 FILEDESC_SUNLOCK(td->td_proc->p_fd); 1302 #ifdef MAC 1303 error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd, 1304 &vattr); 1305 if (error) 1306 goto out; 1307 #endif 1308 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); 1309 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 1310 if (error == 0) 1311 vput(nd.ni_vp); 1312 #ifdef MAC 1313 out: 1314 #endif 1315 vput(nd.ni_dvp); 1316 vn_finished_write(mp); 1317 VFS_UNLOCK_GIANT(vfslocked); 1318 NDFREE(&nd, NDF_ONLY_PNBUF); 1319 return (error); 1320 } 1321 1322 /* 1323 * Make a hard file link. 1324 */ 1325 #ifndef _SYS_SYSPROTO_H_ 1326 struct link_args { 1327 char *path; 1328 char *link; 1329 }; 1330 #endif 1331 int 1332 link(td, uap) 1333 struct thread *td; 1334 register struct link_args /* { 1335 char *path; 1336 char *link; 1337 } */ *uap; 1338 { 1339 int error; 1340 1341 error = kern_link(td, uap->path, uap->link, UIO_USERSPACE); 1342 return (error); 1343 } 1344 1345 static int hardlink_check_uid = 0; 1346 SYSCTL_INT(_security_bsd, OID_AUTO, hardlink_check_uid, CTLFLAG_RW, 1347 &hardlink_check_uid, 0, 1348 "Unprivileged processes cannot create hard links to files owned by other " 1349 "users"); 1350 static int hardlink_check_gid = 0; 1351 SYSCTL_INT(_security_bsd, OID_AUTO, hardlink_check_gid, CTLFLAG_RW, 1352 &hardlink_check_gid, 0, 1353 "Unprivileged processes cannot create hard links to files owned by other " 1354 "groups"); 1355 1356 static int 1357 can_hardlink(struct vnode *vp, struct thread *td, struct ucred *cred) 1358 { 1359 struct vattr va; 1360 int error; 1361 1362 if (!hardlink_check_uid && !hardlink_check_gid) 1363 return (0); 1364 1365 error = VOP_GETATTR(vp, &va, cred, td); 1366 if (error != 0) 1367 return (error); 1368 1369 if (hardlink_check_uid && cred->cr_uid != va.va_uid) { 1370 error = priv_check_cred(cred, PRIV_VFS_LINK, 1371 SUSER_ALLOWJAIL); 1372 if (error) 1373 return (error); 1374 } 1375 1376 if (hardlink_check_gid && !groupmember(va.va_gid, cred)) { 1377 error = priv_check_cred(cred, PRIV_VFS_LINK, 1378 SUSER_ALLOWJAIL); 1379 if (error) 1380 return (error); 1381 } 1382 1383 return (0); 1384 } 1385 1386 int 1387 kern_link(struct thread *td, char *path, char *link, enum uio_seg segflg) 1388 { 1389 struct vnode *vp; 1390 struct mount *mp; 1391 struct nameidata nd; 1392 int vfslocked; 1393 int lvfslocked; 1394 int error; 1395 1396 bwillwrite(); 1397 NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, segflg, path, td); 1398 if ((error = namei(&nd)) != 0) 1399 return (error); 1400 vfslocked = NDHASGIANT(&nd); 1401 NDFREE(&nd, NDF_ONLY_PNBUF); 1402 vp = nd.ni_vp; 1403 if (vp->v_type == VDIR) { 1404 vrele(vp); 1405 VFS_UNLOCK_GIANT(vfslocked); 1406 return (EPERM); /* POSIX */ 1407 } 1408 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) { 1409 vrele(vp); 1410 VFS_UNLOCK_GIANT(vfslocked); 1411 return (error); 1412 } 1413 NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE2, 1414 segflg, link, td); 1415 if ((error = namei(&nd)) == 0) { 1416 lvfslocked = NDHASGIANT(&nd); 1417 if (nd.ni_vp != NULL) { 1418 if (nd.ni_dvp == nd.ni_vp) 1419 vrele(nd.ni_dvp); 1420 else 1421 vput(nd.ni_dvp); 1422 vrele(nd.ni_vp); 1423 error = EEXIST; 1424 } else if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td)) 1425 == 0) { 1426 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); 1427 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 1428 error = can_hardlink(vp, td, td->td_ucred); 1429 if (error == 0) 1430 #ifdef MAC 1431 error = mac_check_vnode_link(td->td_ucred, 1432 nd.ni_dvp, vp, &nd.ni_cnd); 1433 if (error == 0) 1434 #endif 1435 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); 1436 VOP_UNLOCK(vp, 0, td); 1437 vput(nd.ni_dvp); 1438 } 1439 NDFREE(&nd, NDF_ONLY_PNBUF); 1440 VFS_UNLOCK_GIANT(lvfslocked); 1441 } 1442 vrele(vp); 1443 vn_finished_write(mp); 1444 VFS_UNLOCK_GIANT(vfslocked); 1445 return (error); 1446 } 1447 1448 /* 1449 * Make a symbolic link. 1450 */ 1451 #ifndef _SYS_SYSPROTO_H_ 1452 struct symlink_args { 1453 char *path; 1454 char *link; 1455 }; 1456 #endif 1457 int 1458 symlink(td, uap) 1459 struct thread *td; 1460 register struct symlink_args /* { 1461 char *path; 1462 char *link; 1463 } */ *uap; 1464 { 1465 1466 return (kern_symlink(td, uap->path, uap->link, UIO_USERSPACE)); 1467 } 1468 1469 int 1470 kern_symlink(struct thread *td, char *path, char *link, enum uio_seg segflg) 1471 { 1472 struct mount *mp; 1473 struct vattr vattr; 1474 char *syspath; 1475 int error; 1476 struct nameidata nd; 1477 int vfslocked; 1478 1479 if (segflg == UIO_SYSSPACE) { 1480 syspath = path; 1481 } else { 1482 syspath = uma_zalloc(namei_zone, M_WAITOK); 1483 if ((error = copyinstr(path, syspath, MAXPATHLEN, NULL)) != 0) 1484 goto out; 1485 } 1486 AUDIT_ARG(text, syspath); 1487 restart: 1488 bwillwrite(); 1489 NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1, 1490 segflg, link, td); 1491 if ((error = namei(&nd)) != 0) 1492 goto out; 1493 vfslocked = NDHASGIANT(&nd); 1494 if (nd.ni_vp) { 1495 NDFREE(&nd, NDF_ONLY_PNBUF); 1496 if (nd.ni_vp == nd.ni_dvp) 1497 vrele(nd.ni_dvp); 1498 else 1499 vput(nd.ni_dvp); 1500 vrele(nd.ni_vp); 1501 VFS_UNLOCK_GIANT(vfslocked); 1502 error = EEXIST; 1503 goto out; 1504 } 1505 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1506 NDFREE(&nd, NDF_ONLY_PNBUF); 1507 vput(nd.ni_dvp); 1508 VFS_UNLOCK_GIANT(vfslocked); 1509 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 1510 goto out; 1511 goto restart; 1512 } 1513 VATTR_NULL(&vattr); 1514 FILEDESC_SLOCK(td->td_proc->p_fd); 1515 vattr.va_mode = ACCESSPERMS &~ td->td_proc->p_fd->fd_cmask; 1516 FILEDESC_SUNLOCK(td->td_proc->p_fd); 1517 #ifdef MAC 1518 vattr.va_type = VLNK; 1519 error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd, 1520 &vattr); 1521 if (error) 1522 goto out2; 1523 #endif 1524 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); 1525 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, syspath); 1526 if (error == 0) 1527 vput(nd.ni_vp); 1528 #ifdef MAC 1529 out2: 1530 #endif 1531 NDFREE(&nd, NDF_ONLY_PNBUF); 1532 vput(nd.ni_dvp); 1533 vn_finished_write(mp); 1534 VFS_UNLOCK_GIANT(vfslocked); 1535 out: 1536 if (segflg != UIO_SYSSPACE) 1537 uma_zfree(namei_zone, syspath); 1538 return (error); 1539 } 1540 1541 /* 1542 * Delete a whiteout from the filesystem. 1543 */ 1544 int 1545 undelete(td, uap) 1546 struct thread *td; 1547 register struct undelete_args /* { 1548 char *path; 1549 } */ *uap; 1550 { 1551 int error; 1552 struct mount *mp; 1553 struct nameidata nd; 1554 int vfslocked; 1555 1556 restart: 1557 bwillwrite(); 1558 NDINIT(&nd, DELETE, LOCKPARENT | DOWHITEOUT | MPSAFE | AUDITVNODE1, 1559 UIO_USERSPACE, uap->path, td); 1560 error = namei(&nd); 1561 if (error) 1562 return (error); 1563 vfslocked = NDHASGIANT(&nd); 1564 1565 if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) { 1566 NDFREE(&nd, NDF_ONLY_PNBUF); 1567 if (nd.ni_vp == nd.ni_dvp) 1568 vrele(nd.ni_dvp); 1569 else 1570 vput(nd.ni_dvp); 1571 if (nd.ni_vp) 1572 vrele(nd.ni_vp); 1573 VFS_UNLOCK_GIANT(vfslocked); 1574 return (EEXIST); 1575 } 1576 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1577 NDFREE(&nd, NDF_ONLY_PNBUF); 1578 vput(nd.ni_dvp); 1579 VFS_UNLOCK_GIANT(vfslocked); 1580 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 1581 return (error); 1582 goto restart; 1583 } 1584 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); 1585 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE); 1586 NDFREE(&nd, NDF_ONLY_PNBUF); 1587 vput(nd.ni_dvp); 1588 vn_finished_write(mp); 1589 VFS_UNLOCK_GIANT(vfslocked); 1590 return (error); 1591 } 1592 1593 /* 1594 * Delete a name from the filesystem. 1595 */ 1596 #ifndef _SYS_SYSPROTO_H_ 1597 struct unlink_args { 1598 char *path; 1599 }; 1600 #endif 1601 int 1602 unlink(td, uap) 1603 struct thread *td; 1604 struct unlink_args /* { 1605 char *path; 1606 } */ *uap; 1607 { 1608 int error; 1609 1610 error = kern_unlink(td, uap->path, UIO_USERSPACE); 1611 return (error); 1612 } 1613 1614 int 1615 kern_unlink(struct thread *td, char *path, enum uio_seg pathseg) 1616 { 1617 struct mount *mp; 1618 struct vnode *vp; 1619 int error; 1620 struct nameidata nd; 1621 int vfslocked; 1622 1623 restart: 1624 bwillwrite(); 1625 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF | MPSAFE | AUDITVNODE1, 1626 pathseg, path, td); 1627 if ((error = namei(&nd)) != 0) 1628 return (error == EINVAL ? EPERM : error); 1629 vfslocked = NDHASGIANT(&nd); 1630 vp = nd.ni_vp; 1631 if (vp->v_type == VDIR) 1632 error = EPERM; /* POSIX */ 1633 else { 1634 /* 1635 * The root of a mounted filesystem cannot be deleted. 1636 * 1637 * XXX: can this only be a VDIR case? 1638 */ 1639 if (vp->v_vflag & VV_ROOT) 1640 error = EBUSY; 1641 } 1642 if (error == 0) { 1643 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1644 NDFREE(&nd, NDF_ONLY_PNBUF); 1645 vput(nd.ni_dvp); 1646 if (vp == nd.ni_dvp) 1647 vrele(vp); 1648 else 1649 vput(vp); 1650 VFS_UNLOCK_GIANT(vfslocked); 1651 if ((error = vn_start_write(NULL, &mp, 1652 V_XSLEEP | PCATCH)) != 0) 1653 return (error); 1654 goto restart; 1655 } 1656 #ifdef MAC 1657 error = mac_check_vnode_delete(td->td_ucred, nd.ni_dvp, vp, 1658 &nd.ni_cnd); 1659 if (error) 1660 goto out; 1661 #endif 1662 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); 1663 error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd); 1664 #ifdef MAC 1665 out: 1666 #endif 1667 vn_finished_write(mp); 1668 } 1669 NDFREE(&nd, NDF_ONLY_PNBUF); 1670 vput(nd.ni_dvp); 1671 if (vp == nd.ni_dvp) 1672 vrele(vp); 1673 else 1674 vput(vp); 1675 VFS_UNLOCK_GIANT(vfslocked); 1676 return (error); 1677 } 1678 1679 /* 1680 * Reposition read/write file offset. 1681 */ 1682 #ifndef _SYS_SYSPROTO_H_ 1683 struct lseek_args { 1684 int fd; 1685 int pad; 1686 off_t offset; 1687 int whence; 1688 }; 1689 #endif 1690 int 1691 lseek(td, uap) 1692 struct thread *td; 1693 register struct lseek_args /* { 1694 int fd; 1695 int pad; 1696 off_t offset; 1697 int whence; 1698 } */ *uap; 1699 { 1700 struct ucred *cred = td->td_ucred; 1701 struct file *fp; 1702 struct vnode *vp; 1703 struct vattr vattr; 1704 off_t offset; 1705 int error, noneg; 1706 int vfslocked; 1707 1708 if ((error = fget(td, uap->fd, &fp)) != 0) 1709 return (error); 1710 if (!(fp->f_ops->fo_flags & DFLAG_SEEKABLE)) { 1711 fdrop(fp, td); 1712 return (ESPIPE); 1713 } 1714 vp = fp->f_vnode; 1715 vfslocked = VFS_LOCK_GIANT(vp->v_mount); 1716 noneg = (vp->v_type != VCHR); 1717 offset = uap->offset; 1718 switch (uap->whence) { 1719 case L_INCR: 1720 if (noneg && 1721 (fp->f_offset < 0 || 1722 (offset > 0 && fp->f_offset > OFF_MAX - offset))) { 1723 error = EOVERFLOW; 1724 break; 1725 } 1726 offset += fp->f_offset; 1727 break; 1728 case L_XTND: 1729 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 1730 error = VOP_GETATTR(vp, &vattr, cred, td); 1731 VOP_UNLOCK(vp, 0, td); 1732 if (error) 1733 break; 1734 if (noneg && 1735 (vattr.va_size > OFF_MAX || 1736 (offset > 0 && vattr.va_size > OFF_MAX - offset))) { 1737 error = EOVERFLOW; 1738 break; 1739 } 1740 offset += vattr.va_size; 1741 break; 1742 case L_SET: 1743 break; 1744 case SEEK_DATA: 1745 error = fo_ioctl(fp, FIOSEEKDATA, &offset, cred, td); 1746 break; 1747 case SEEK_HOLE: 1748 error = fo_ioctl(fp, FIOSEEKHOLE, &offset, cred, td); 1749 break; 1750 default: 1751 error = EINVAL; 1752 } 1753 if (error == 0 && noneg && offset < 0) 1754 error = EINVAL; 1755 if (error != 0) 1756 goto drop; 1757 fp->f_offset = offset; 1758 *(off_t *)(td->td_retval) = fp->f_offset; 1759 drop: 1760 fdrop(fp, td); 1761 VFS_UNLOCK_GIANT(vfslocked); 1762 return (error); 1763 } 1764 1765 #if defined(COMPAT_43) 1766 /* 1767 * Reposition read/write file offset. 1768 */ 1769 #ifndef _SYS_SYSPROTO_H_ 1770 struct olseek_args { 1771 int fd; 1772 long offset; 1773 int whence; 1774 }; 1775 #endif 1776 int 1777 olseek(td, uap) 1778 struct thread *td; 1779 register struct olseek_args /* { 1780 int fd; 1781 long offset; 1782 int whence; 1783 } */ *uap; 1784 { 1785 struct lseek_args /* { 1786 int fd; 1787 int pad; 1788 off_t offset; 1789 int whence; 1790 } */ nuap; 1791 int error; 1792 1793 nuap.fd = uap->fd; 1794 nuap.offset = uap->offset; 1795 nuap.whence = uap->whence; 1796 error = lseek(td, &nuap); 1797 return (error); 1798 } 1799 #endif /* COMPAT_43 */ 1800 1801 /* 1802 * Check access permissions using passed credentials. 1803 */ 1804 static int 1805 vn_access(vp, user_flags, cred, td) 1806 struct vnode *vp; 1807 int user_flags; 1808 struct ucred *cred; 1809 struct thread *td; 1810 { 1811 int error, flags; 1812 1813 /* Flags == 0 means only check for existence. */ 1814 error = 0; 1815 if (user_flags) { 1816 flags = 0; 1817 if (user_flags & R_OK) 1818 flags |= VREAD; 1819 if (user_flags & W_OK) 1820 flags |= VWRITE; 1821 if (user_flags & X_OK) 1822 flags |= VEXEC; 1823 #ifdef MAC 1824 error = mac_check_vnode_access(cred, vp, flags); 1825 if (error) 1826 return (error); 1827 #endif 1828 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) 1829 error = VOP_ACCESS(vp, flags, cred, td); 1830 } 1831 return (error); 1832 } 1833 1834 /* 1835 * Check access permissions using "real" credentials. 1836 */ 1837 #ifndef _SYS_SYSPROTO_H_ 1838 struct access_args { 1839 char *path; 1840 int flags; 1841 }; 1842 #endif 1843 int 1844 access(td, uap) 1845 struct thread *td; 1846 register struct access_args /* { 1847 char *path; 1848 int flags; 1849 } */ *uap; 1850 { 1851 1852 return (kern_access(td, uap->path, UIO_USERSPACE, uap->flags)); 1853 } 1854 1855 int 1856 kern_access(struct thread *td, char *path, enum uio_seg pathseg, int flags) 1857 { 1858 struct ucred *cred, *tmpcred; 1859 register struct vnode *vp; 1860 struct nameidata nd; 1861 int vfslocked; 1862 int error; 1863 1864 /* 1865 * Create and modify a temporary credential instead of one that 1866 * is potentially shared. This could also mess up socket 1867 * buffer accounting which can run in an interrupt context. 1868 */ 1869 cred = td->td_ucred; 1870 tmpcred = crdup(cred); 1871 tmpcred->cr_uid = cred->cr_ruid; 1872 tmpcred->cr_groups[0] = cred->cr_rgid; 1873 td->td_ucred = tmpcred; 1874 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, 1875 pathseg, path, td); 1876 if ((error = namei(&nd)) != 0) 1877 goto out1; 1878 vfslocked = NDHASGIANT(&nd); 1879 vp = nd.ni_vp; 1880 1881 error = vn_access(vp, flags, tmpcred, td); 1882 NDFREE(&nd, NDF_ONLY_PNBUF); 1883 vput(vp); 1884 VFS_UNLOCK_GIANT(vfslocked); 1885 out1: 1886 td->td_ucred = cred; 1887 crfree(tmpcred); 1888 return (error); 1889 } 1890 1891 /* 1892 * Check access permissions using "effective" credentials. 1893 */ 1894 #ifndef _SYS_SYSPROTO_H_ 1895 struct eaccess_args { 1896 char *path; 1897 int flags; 1898 }; 1899 #endif 1900 int 1901 eaccess(td, uap) 1902 struct thread *td; 1903 register struct eaccess_args /* { 1904 char *path; 1905 int flags; 1906 } */ *uap; 1907 { 1908 1909 return (kern_eaccess(td, uap->path, UIO_USERSPACE, uap->flags)); 1910 } 1911 1912 int 1913 kern_eaccess(struct thread *td, char *path, enum uio_seg pathseg, int flags) 1914 { 1915 struct nameidata nd; 1916 struct vnode *vp; 1917 int vfslocked; 1918 int error; 1919 1920 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, 1921 pathseg, path, td); 1922 if ((error = namei(&nd)) != 0) 1923 return (error); 1924 vp = nd.ni_vp; 1925 vfslocked = NDHASGIANT(&nd); 1926 error = vn_access(vp, flags, td->td_ucred, td); 1927 NDFREE(&nd, NDF_ONLY_PNBUF); 1928 vput(vp); 1929 VFS_UNLOCK_GIANT(vfslocked); 1930 return (error); 1931 } 1932 1933 #if defined(COMPAT_43) 1934 /* 1935 * Get file status; this version follows links. 1936 */ 1937 #ifndef _SYS_SYSPROTO_H_ 1938 struct ostat_args { 1939 char *path; 1940 struct ostat *ub; 1941 }; 1942 #endif 1943 int 1944 ostat(td, uap) 1945 struct thread *td; 1946 register struct ostat_args /* { 1947 char *path; 1948 struct ostat *ub; 1949 } */ *uap; 1950 { 1951 struct stat sb; 1952 struct ostat osb; 1953 int error; 1954 1955 error = kern_stat(td, uap->path, UIO_USERSPACE, &sb); 1956 if (error) 1957 return (error); 1958 cvtstat(&sb, &osb); 1959 error = copyout(&osb, uap->ub, sizeof (osb)); 1960 return (error); 1961 } 1962 1963 /* 1964 * Get file status; this version does not follow links. 1965 */ 1966 #ifndef _SYS_SYSPROTO_H_ 1967 struct olstat_args { 1968 char *path; 1969 struct ostat *ub; 1970 }; 1971 #endif 1972 int 1973 olstat(td, uap) 1974 struct thread *td; 1975 register struct olstat_args /* { 1976 char *path; 1977 struct ostat *ub; 1978 } */ *uap; 1979 { 1980 struct stat sb; 1981 struct ostat osb; 1982 int error; 1983 1984 error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb); 1985 if (error) 1986 return (error); 1987 cvtstat(&sb, &osb); 1988 error = copyout(&osb, uap->ub, sizeof (osb)); 1989 return (error); 1990 } 1991 1992 /* 1993 * Convert from an old to a new stat structure. 1994 */ 1995 void 1996 cvtstat(st, ost) 1997 struct stat *st; 1998 struct ostat *ost; 1999 { 2000 2001 ost->st_dev = st->st_dev; 2002 ost->st_ino = st->st_ino; 2003 ost->st_mode = st->st_mode; 2004 ost->st_nlink = st->st_nlink; 2005 ost->st_uid = st->st_uid; 2006 ost->st_gid = st->st_gid; 2007 ost->st_rdev = st->st_rdev; 2008 if (st->st_size < (quad_t)1 << 32) 2009 ost->st_size = st->st_size; 2010 else 2011 ost->st_size = -2; 2012 ost->st_atime = st->st_atime; 2013 ost->st_mtime = st->st_mtime; 2014 ost->st_ctime = st->st_ctime; 2015 ost->st_blksize = st->st_blksize; 2016 ost->st_blocks = st->st_blocks; 2017 ost->st_flags = st->st_flags; 2018 ost->st_gen = st->st_gen; 2019 } 2020 #endif /* COMPAT_43 */ 2021 2022 /* 2023 * Get file status; this version follows links. 2024 */ 2025 #ifndef _SYS_SYSPROTO_H_ 2026 struct stat_args { 2027 char *path; 2028 struct stat *ub; 2029 }; 2030 #endif 2031 int 2032 stat(td, uap) 2033 struct thread *td; 2034 register struct stat_args /* { 2035 char *path; 2036 struct stat *ub; 2037 } */ *uap; 2038 { 2039 struct stat sb; 2040 int error; 2041 2042 error = kern_stat(td, uap->path, UIO_USERSPACE, &sb); 2043 if (error == 0) 2044 error = copyout(&sb, uap->ub, sizeof (sb)); 2045 return (error); 2046 } 2047 2048 int 2049 kern_stat(struct thread *td, char *path, enum uio_seg pathseg, struct stat *sbp) 2050 { 2051 struct nameidata nd; 2052 struct stat sb; 2053 int error, vfslocked; 2054 2055 NDINIT(&nd, LOOKUP, 2056 FOLLOW | LOCKSHARED | LOCKLEAF | MPSAFE | AUDITVNODE1, 2057 pathseg, path, td); 2058 if ((error = namei(&nd)) != 0) 2059 return (error); 2060 vfslocked = NDHASGIANT(&nd); 2061 error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td); 2062 NDFREE(&nd, NDF_ONLY_PNBUF); 2063 vput(nd.ni_vp); 2064 VFS_UNLOCK_GIANT(vfslocked); 2065 if (mtx_owned(&Giant)) 2066 printf("stat(%d): %s\n", vfslocked, path); 2067 if (error) 2068 return (error); 2069 *sbp = sb; 2070 return (0); 2071 } 2072 2073 /* 2074 * Get file status; this version does not follow links. 2075 */ 2076 #ifndef _SYS_SYSPROTO_H_ 2077 struct lstat_args { 2078 char *path; 2079 struct stat *ub; 2080 }; 2081 #endif 2082 int 2083 lstat(td, uap) 2084 struct thread *td; 2085 register struct lstat_args /* { 2086 char *path; 2087 struct stat *ub; 2088 } */ *uap; 2089 { 2090 struct stat sb; 2091 int error; 2092 2093 error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb); 2094 if (error == 0) 2095 error = copyout(&sb, uap->ub, sizeof (sb)); 2096 return (error); 2097 } 2098 2099 int 2100 kern_lstat(struct thread *td, char *path, enum uio_seg pathseg, struct stat *sbp) 2101 { 2102 struct vnode *vp; 2103 struct stat sb; 2104 struct nameidata nd; 2105 int error, vfslocked; 2106 2107 NDINIT(&nd, LOOKUP, 2108 NOFOLLOW | LOCKLEAF | LOCKSHARED | MPSAFE | AUDITVNODE1, 2109 pathseg, path, td); 2110 if ((error = namei(&nd)) != 0) 2111 return (error); 2112 vfslocked = NDHASGIANT(&nd); 2113 vp = nd.ni_vp; 2114 error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td); 2115 NDFREE(&nd, NDF_ONLY_PNBUF); 2116 vput(vp); 2117 VFS_UNLOCK_GIANT(vfslocked); 2118 if (error) 2119 return (error); 2120 *sbp = sb; 2121 return (0); 2122 } 2123 2124 /* 2125 * Implementation of the NetBSD [l]stat() functions. 2126 */ 2127 void 2128 cvtnstat(sb, nsb) 2129 struct stat *sb; 2130 struct nstat *nsb; 2131 { 2132 bzero(nsb, sizeof *nsb); 2133 nsb->st_dev = sb->st_dev; 2134 nsb->st_ino = sb->st_ino; 2135 nsb->st_mode = sb->st_mode; 2136 nsb->st_nlink = sb->st_nlink; 2137 nsb->st_uid = sb->st_uid; 2138 nsb->st_gid = sb->st_gid; 2139 nsb->st_rdev = sb->st_rdev; 2140 nsb->st_atimespec = sb->st_atimespec; 2141 nsb->st_mtimespec = sb->st_mtimespec; 2142 nsb->st_ctimespec = sb->st_ctimespec; 2143 nsb->st_size = sb->st_size; 2144 nsb->st_blocks = sb->st_blocks; 2145 nsb->st_blksize = sb->st_blksize; 2146 nsb->st_flags = sb->st_flags; 2147 nsb->st_gen = sb->st_gen; 2148 nsb->st_birthtimespec = sb->st_birthtimespec; 2149 } 2150 2151 #ifndef _SYS_SYSPROTO_H_ 2152 struct nstat_args { 2153 char *path; 2154 struct nstat *ub; 2155 }; 2156 #endif 2157 int 2158 nstat(td, uap) 2159 struct thread *td; 2160 register struct nstat_args /* { 2161 char *path; 2162 struct nstat *ub; 2163 } */ *uap; 2164 { 2165 struct stat sb; 2166 struct nstat nsb; 2167 int error; 2168 2169 error = kern_stat(td, uap->path, UIO_USERSPACE, &sb); 2170 if (error) 2171 return (error); 2172 cvtnstat(&sb, &nsb); 2173 error = copyout(&nsb, uap->ub, sizeof (nsb)); 2174 return (error); 2175 } 2176 2177 /* 2178 * NetBSD lstat. Get file status; this version does not follow links. 2179 */ 2180 #ifndef _SYS_SYSPROTO_H_ 2181 struct lstat_args { 2182 char *path; 2183 struct stat *ub; 2184 }; 2185 #endif 2186 int 2187 nlstat(td, uap) 2188 struct thread *td; 2189 register struct nlstat_args /* { 2190 char *path; 2191 struct nstat *ub; 2192 } */ *uap; 2193 { 2194 struct stat sb; 2195 struct nstat nsb; 2196 int error; 2197 2198 error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb); 2199 if (error) 2200 return (error); 2201 cvtnstat(&sb, &nsb); 2202 error = copyout(&nsb, uap->ub, sizeof (nsb)); 2203 return (error); 2204 } 2205 2206 /* 2207 * Get configurable pathname variables. 2208 */ 2209 #ifndef _SYS_SYSPROTO_H_ 2210 struct pathconf_args { 2211 char *path; 2212 int name; 2213 }; 2214 #endif 2215 int 2216 pathconf(td, uap) 2217 struct thread *td; 2218 register struct pathconf_args /* { 2219 char *path; 2220 int name; 2221 } */ *uap; 2222 { 2223 2224 return (kern_pathconf(td, uap->path, UIO_USERSPACE, uap->name)); 2225 } 2226 2227 int 2228 kern_pathconf(struct thread *td, char *path, enum uio_seg pathseg, int name) 2229 { 2230 struct nameidata nd; 2231 int error, vfslocked; 2232 2233 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, 2234 pathseg, path, td); 2235 if ((error = namei(&nd)) != 0) 2236 return (error); 2237 vfslocked = NDHASGIANT(&nd); 2238 NDFREE(&nd, NDF_ONLY_PNBUF); 2239 2240 /* If asynchronous I/O is available, it works for all files. */ 2241 if (name == _PC_ASYNC_IO) 2242 td->td_retval[0] = async_io_version; 2243 else 2244 error = VOP_PATHCONF(nd.ni_vp, name, td->td_retval); 2245 vput(nd.ni_vp); 2246 VFS_UNLOCK_GIANT(vfslocked); 2247 return (error); 2248 } 2249 2250 /* 2251 * Return target name of a symbolic link. 2252 */ 2253 #ifndef _SYS_SYSPROTO_H_ 2254 struct readlink_args { 2255 char *path; 2256 char *buf; 2257 int count; 2258 }; 2259 #endif 2260 int 2261 readlink(td, uap) 2262 struct thread *td; 2263 register struct readlink_args /* { 2264 char *path; 2265 char *buf; 2266 int count; 2267 } */ *uap; 2268 { 2269 2270 return (kern_readlink(td, uap->path, UIO_USERSPACE, uap->buf, 2271 UIO_USERSPACE, uap->count)); 2272 } 2273 2274 int 2275 kern_readlink(struct thread *td, char *path, enum uio_seg pathseg, char *buf, 2276 enum uio_seg bufseg, int count) 2277 { 2278 register struct vnode *vp; 2279 struct iovec aiov; 2280 struct uio auio; 2281 int error; 2282 struct nameidata nd; 2283 int vfslocked; 2284 2285 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, 2286 pathseg, path, td); 2287 if ((error = namei(&nd)) != 0) 2288 return (error); 2289 NDFREE(&nd, NDF_ONLY_PNBUF); 2290 vfslocked = NDHASGIANT(&nd); 2291 vp = nd.ni_vp; 2292 #ifdef MAC 2293 error = mac_check_vnode_readlink(td->td_ucred, vp); 2294 if (error) { 2295 vput(vp); 2296 VFS_UNLOCK_GIANT(vfslocked); 2297 return (error); 2298 } 2299 #endif 2300 if (vp->v_type != VLNK) 2301 error = EINVAL; 2302 else { 2303 aiov.iov_base = buf; 2304 aiov.iov_len = count; 2305 auio.uio_iov = &aiov; 2306 auio.uio_iovcnt = 1; 2307 auio.uio_offset = 0; 2308 auio.uio_rw = UIO_READ; 2309 auio.uio_segflg = bufseg; 2310 auio.uio_td = td; 2311 auio.uio_resid = count; 2312 error = VOP_READLINK(vp, &auio, td->td_ucred); 2313 } 2314 vput(vp); 2315 VFS_UNLOCK_GIANT(vfslocked); 2316 td->td_retval[0] = count - auio.uio_resid; 2317 return (error); 2318 } 2319 2320 /* 2321 * Common implementation code for chflags() and fchflags(). 2322 */ 2323 static int 2324 setfflags(td, vp, flags) 2325 struct thread *td; 2326 struct vnode *vp; 2327 int flags; 2328 { 2329 int error; 2330 struct mount *mp; 2331 struct vattr vattr; 2332 2333 /* 2334 * Prevent non-root users from setting flags on devices. When 2335 * a device is reused, users can retain ownership of the device 2336 * if they are allowed to set flags and programs assume that 2337 * chown can't fail when done as root. 2338 */ 2339 if (vp->v_type == VCHR || vp->v_type == VBLK) { 2340 error = priv_check_cred(td->td_ucred, PRIV_VFS_CHFLAGS_DEV, 2341 SUSER_ALLOWJAIL); 2342 if (error) 2343 return (error); 2344 } 2345 2346 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 2347 return (error); 2348 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 2349 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2350 VATTR_NULL(&vattr); 2351 vattr.va_flags = flags; 2352 #ifdef MAC 2353 error = mac_check_vnode_setflags(td->td_ucred, vp, vattr.va_flags); 2354 if (error == 0) 2355 #endif 2356 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); 2357 VOP_UNLOCK(vp, 0, td); 2358 vn_finished_write(mp); 2359 return (error); 2360 } 2361 2362 /* 2363 * Change flags of a file given a path name. 2364 */ 2365 #ifndef _SYS_SYSPROTO_H_ 2366 struct chflags_args { 2367 char *path; 2368 int flags; 2369 }; 2370 #endif 2371 int 2372 chflags(td, uap) 2373 struct thread *td; 2374 register struct chflags_args /* { 2375 char *path; 2376 int flags; 2377 } */ *uap; 2378 { 2379 int error; 2380 struct nameidata nd; 2381 int vfslocked; 2382 2383 AUDIT_ARG(fflags, uap->flags); 2384 NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, UIO_USERSPACE, 2385 uap->path, td); 2386 if ((error = namei(&nd)) != 0) 2387 return (error); 2388 NDFREE(&nd, NDF_ONLY_PNBUF); 2389 vfslocked = NDHASGIANT(&nd); 2390 error = setfflags(td, nd.ni_vp, uap->flags); 2391 vrele(nd.ni_vp); 2392 VFS_UNLOCK_GIANT(vfslocked); 2393 return (error); 2394 } 2395 2396 /* 2397 * Same as chflags() but doesn't follow symlinks. 2398 */ 2399 int 2400 lchflags(td, uap) 2401 struct thread *td; 2402 register struct lchflags_args /* { 2403 char *path; 2404 int flags; 2405 } */ *uap; 2406 { 2407 int error; 2408 struct nameidata nd; 2409 int vfslocked; 2410 2411 AUDIT_ARG(fflags, uap->flags); 2412 NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE | AUDITVNODE1, UIO_USERSPACE, 2413 uap->path, td); 2414 if ((error = namei(&nd)) != 0) 2415 return (error); 2416 vfslocked = NDHASGIANT(&nd); 2417 NDFREE(&nd, NDF_ONLY_PNBUF); 2418 error = setfflags(td, nd.ni_vp, uap->flags); 2419 vrele(nd.ni_vp); 2420 VFS_UNLOCK_GIANT(vfslocked); 2421 return (error); 2422 } 2423 2424 /* 2425 * Change flags of a file given a file descriptor. 2426 */ 2427 #ifndef _SYS_SYSPROTO_H_ 2428 struct fchflags_args { 2429 int fd; 2430 int flags; 2431 }; 2432 #endif 2433 int 2434 fchflags(td, uap) 2435 struct thread *td; 2436 register struct fchflags_args /* { 2437 int fd; 2438 int flags; 2439 } */ *uap; 2440 { 2441 struct file *fp; 2442 int vfslocked; 2443 int error; 2444 2445 AUDIT_ARG(fd, uap->fd); 2446 AUDIT_ARG(fflags, uap->flags); 2447 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) 2448 return (error); 2449 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); 2450 #ifdef AUDIT 2451 vn_lock(fp->f_vnode, LK_EXCLUSIVE | LK_RETRY, td); 2452 AUDIT_ARG(vnode, fp->f_vnode, ARG_VNODE1); 2453 VOP_UNLOCK(fp->f_vnode, 0, td); 2454 #endif 2455 error = setfflags(td, fp->f_vnode, uap->flags); 2456 VFS_UNLOCK_GIANT(vfslocked); 2457 fdrop(fp, td); 2458 return (error); 2459 } 2460 2461 /* 2462 * Common implementation code for chmod(), lchmod() and fchmod(). 2463 */ 2464 static int 2465 setfmode(td, vp, mode) 2466 struct thread *td; 2467 struct vnode *vp; 2468 int mode; 2469 { 2470 int error; 2471 struct mount *mp; 2472 struct vattr vattr; 2473 2474 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 2475 return (error); 2476 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 2477 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2478 VATTR_NULL(&vattr); 2479 vattr.va_mode = mode & ALLPERMS; 2480 #ifdef MAC 2481 error = mac_check_vnode_setmode(td->td_ucred, vp, vattr.va_mode); 2482 if (error == 0) 2483 #endif 2484 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); 2485 VOP_UNLOCK(vp, 0, td); 2486 vn_finished_write(mp); 2487 return (error); 2488 } 2489 2490 /* 2491 * Change mode of a file given path name. 2492 */ 2493 #ifndef _SYS_SYSPROTO_H_ 2494 struct chmod_args { 2495 char *path; 2496 int mode; 2497 }; 2498 #endif 2499 int 2500 chmod(td, uap) 2501 struct thread *td; 2502 register struct chmod_args /* { 2503 char *path; 2504 int mode; 2505 } */ *uap; 2506 { 2507 2508 return (kern_chmod(td, uap->path, UIO_USERSPACE, uap->mode)); 2509 } 2510 2511 int 2512 kern_chmod(struct thread *td, char *path, enum uio_seg pathseg, int mode) 2513 { 2514 int error; 2515 struct nameidata nd; 2516 int vfslocked; 2517 2518 AUDIT_ARG(mode, mode); 2519 NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td); 2520 if ((error = namei(&nd)) != 0) 2521 return (error); 2522 vfslocked = NDHASGIANT(&nd); 2523 NDFREE(&nd, NDF_ONLY_PNBUF); 2524 error = setfmode(td, nd.ni_vp, mode); 2525 vrele(nd.ni_vp); 2526 VFS_UNLOCK_GIANT(vfslocked); 2527 return (error); 2528 } 2529 2530 /* 2531 * Change mode of a file given path name (don't follow links.) 2532 */ 2533 #ifndef _SYS_SYSPROTO_H_ 2534 struct lchmod_args { 2535 char *path; 2536 int mode; 2537 }; 2538 #endif 2539 int 2540 lchmod(td, uap) 2541 struct thread *td; 2542 register struct lchmod_args /* { 2543 char *path; 2544 int mode; 2545 } */ *uap; 2546 { 2547 int error; 2548 struct nameidata nd; 2549 int vfslocked; 2550 2551 AUDIT_ARG(mode, (mode_t)uap->mode); 2552 NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE | AUDITVNODE1, UIO_USERSPACE, 2553 uap->path, td); 2554 if ((error = namei(&nd)) != 0) 2555 return (error); 2556 vfslocked = NDHASGIANT(&nd); 2557 NDFREE(&nd, NDF_ONLY_PNBUF); 2558 error = setfmode(td, nd.ni_vp, uap->mode); 2559 vrele(nd.ni_vp); 2560 VFS_UNLOCK_GIANT(vfslocked); 2561 return (error); 2562 } 2563 2564 /* 2565 * Change mode of a file given a file descriptor. 2566 */ 2567 #ifndef _SYS_SYSPROTO_H_ 2568 struct fchmod_args { 2569 int fd; 2570 int mode; 2571 }; 2572 #endif 2573 int 2574 fchmod(td, uap) 2575 struct thread *td; 2576 register struct fchmod_args /* { 2577 int fd; 2578 int mode; 2579 } */ *uap; 2580 { 2581 struct file *fp; 2582 int vfslocked; 2583 int error; 2584 2585 AUDIT_ARG(fd, uap->fd); 2586 AUDIT_ARG(mode, uap->mode); 2587 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) 2588 return (error); 2589 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); 2590 #ifdef AUDIT 2591 vn_lock(fp->f_vnode, LK_EXCLUSIVE | LK_RETRY, td); 2592 AUDIT_ARG(vnode, fp->f_vnode, ARG_VNODE1); 2593 VOP_UNLOCK(fp->f_vnode, 0, td); 2594 #endif 2595 error = setfmode(td, fp->f_vnode, uap->mode); 2596 VFS_UNLOCK_GIANT(vfslocked); 2597 fdrop(fp, td); 2598 return (error); 2599 } 2600 2601 /* 2602 * Common implementation for chown(), lchown(), and fchown() 2603 */ 2604 static int 2605 setfown(td, vp, uid, gid) 2606 struct thread *td; 2607 struct vnode *vp; 2608 uid_t uid; 2609 gid_t gid; 2610 { 2611 int error; 2612 struct mount *mp; 2613 struct vattr vattr; 2614 2615 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 2616 return (error); 2617 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 2618 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2619 VATTR_NULL(&vattr); 2620 vattr.va_uid = uid; 2621 vattr.va_gid = gid; 2622 #ifdef MAC 2623 error = mac_check_vnode_setowner(td->td_ucred, vp, vattr.va_uid, 2624 vattr.va_gid); 2625 if (error == 0) 2626 #endif 2627 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); 2628 VOP_UNLOCK(vp, 0, td); 2629 vn_finished_write(mp); 2630 return (error); 2631 } 2632 2633 /* 2634 * Set ownership given a path name. 2635 */ 2636 #ifndef _SYS_SYSPROTO_H_ 2637 struct chown_args { 2638 char *path; 2639 int uid; 2640 int gid; 2641 }; 2642 #endif 2643 int 2644 chown(td, uap) 2645 struct thread *td; 2646 register struct chown_args /* { 2647 char *path; 2648 int uid; 2649 int gid; 2650 } */ *uap; 2651 { 2652 2653 return (kern_chown(td, uap->path, UIO_USERSPACE, uap->uid, uap->gid)); 2654 } 2655 2656 int 2657 kern_chown(struct thread *td, char *path, enum uio_seg pathseg, int uid, 2658 int gid) 2659 { 2660 int error; 2661 struct nameidata nd; 2662 int vfslocked; 2663 2664 AUDIT_ARG(owner, uid, gid); 2665 NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td); 2666 if ((error = namei(&nd)) != 0) 2667 return (error); 2668 vfslocked = NDHASGIANT(&nd); 2669 NDFREE(&nd, NDF_ONLY_PNBUF); 2670 error = setfown(td, nd.ni_vp, uid, gid); 2671 vrele(nd.ni_vp); 2672 VFS_UNLOCK_GIANT(vfslocked); 2673 return (error); 2674 } 2675 2676 /* 2677 * Set ownership given a path name, do not cross symlinks. 2678 */ 2679 #ifndef _SYS_SYSPROTO_H_ 2680 struct lchown_args { 2681 char *path; 2682 int uid; 2683 int gid; 2684 }; 2685 #endif 2686 int 2687 lchown(td, uap) 2688 struct thread *td; 2689 register struct lchown_args /* { 2690 char *path; 2691 int uid; 2692 int gid; 2693 } */ *uap; 2694 { 2695 2696 return (kern_lchown(td, uap->path, UIO_USERSPACE, uap->uid, uap->gid)); 2697 } 2698 2699 int 2700 kern_lchown(struct thread *td, char *path, enum uio_seg pathseg, int uid, 2701 int gid) 2702 { 2703 int error; 2704 struct nameidata nd; 2705 int vfslocked; 2706 2707 AUDIT_ARG(owner, uid, gid); 2708 NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td); 2709 if ((error = namei(&nd)) != 0) 2710 return (error); 2711 vfslocked = NDHASGIANT(&nd); 2712 NDFREE(&nd, NDF_ONLY_PNBUF); 2713 error = setfown(td, nd.ni_vp, uid, gid); 2714 vrele(nd.ni_vp); 2715 VFS_UNLOCK_GIANT(vfslocked); 2716 return (error); 2717 } 2718 2719 /* 2720 * Set ownership given a file descriptor. 2721 */ 2722 #ifndef _SYS_SYSPROTO_H_ 2723 struct fchown_args { 2724 int fd; 2725 int uid; 2726 int gid; 2727 }; 2728 #endif 2729 int 2730 fchown(td, uap) 2731 struct thread *td; 2732 register struct fchown_args /* { 2733 int fd; 2734 int uid; 2735 int gid; 2736 } */ *uap; 2737 { 2738 struct file *fp; 2739 int vfslocked; 2740 int error; 2741 2742 AUDIT_ARG(fd, uap->fd); 2743 AUDIT_ARG(owner, uap->uid, uap->gid); 2744 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) 2745 return (error); 2746 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); 2747 #ifdef AUDIT 2748 vn_lock(fp->f_vnode, LK_EXCLUSIVE | LK_RETRY, td); 2749 AUDIT_ARG(vnode, fp->f_vnode, ARG_VNODE1); 2750 VOP_UNLOCK(fp->f_vnode, 0, td); 2751 #endif 2752 error = setfown(td, fp->f_vnode, uap->uid, uap->gid); 2753 VFS_UNLOCK_GIANT(vfslocked); 2754 fdrop(fp, td); 2755 return (error); 2756 } 2757 2758 /* 2759 * Common implementation code for utimes(), lutimes(), and futimes(). 2760 */ 2761 static int 2762 getutimes(usrtvp, tvpseg, tsp) 2763 const struct timeval *usrtvp; 2764 enum uio_seg tvpseg; 2765 struct timespec *tsp; 2766 { 2767 struct timeval tv[2]; 2768 const struct timeval *tvp; 2769 int error; 2770 2771 if (usrtvp == NULL) { 2772 microtime(&tv[0]); 2773 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]); 2774 tsp[1] = tsp[0]; 2775 } else { 2776 if (tvpseg == UIO_SYSSPACE) { 2777 tvp = usrtvp; 2778 } else { 2779 if ((error = copyin(usrtvp, tv, sizeof(tv))) != 0) 2780 return (error); 2781 tvp = tv; 2782 } 2783 2784 if (tvp[0].tv_usec < 0 || tvp[0].tv_usec >= 1000000 || 2785 tvp[1].tv_usec < 0 || tvp[1].tv_usec >= 1000000) 2786 return (EINVAL); 2787 TIMEVAL_TO_TIMESPEC(&tvp[0], &tsp[0]); 2788 TIMEVAL_TO_TIMESPEC(&tvp[1], &tsp[1]); 2789 } 2790 return (0); 2791 } 2792 2793 /* 2794 * Common implementation code for utimes(), lutimes(), and futimes(). 2795 */ 2796 static int 2797 setutimes(td, vp, ts, numtimes, nullflag) 2798 struct thread *td; 2799 struct vnode *vp; 2800 const struct timespec *ts; 2801 int numtimes; 2802 int nullflag; 2803 { 2804 int error, setbirthtime; 2805 struct mount *mp; 2806 struct vattr vattr; 2807 2808 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 2809 return (error); 2810 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 2811 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2812 setbirthtime = 0; 2813 if (numtimes < 3 && VOP_GETATTR(vp, &vattr, td->td_ucred, td) == 0 && 2814 timespeccmp(&ts[1], &vattr.va_birthtime, < )) 2815 setbirthtime = 1; 2816 VATTR_NULL(&vattr); 2817 vattr.va_atime = ts[0]; 2818 vattr.va_mtime = ts[1]; 2819 if (setbirthtime) 2820 vattr.va_birthtime = ts[1]; 2821 if (numtimes > 2) 2822 vattr.va_birthtime = ts[2]; 2823 if (nullflag) 2824 vattr.va_vaflags |= VA_UTIMES_NULL; 2825 #ifdef MAC 2826 error = mac_check_vnode_setutimes(td->td_ucred, vp, vattr.va_atime, 2827 vattr.va_mtime); 2828 #endif 2829 if (error == 0) 2830 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); 2831 VOP_UNLOCK(vp, 0, td); 2832 vn_finished_write(mp); 2833 return (error); 2834 } 2835 2836 /* 2837 * Set the access and modification times of a file. 2838 */ 2839 #ifndef _SYS_SYSPROTO_H_ 2840 struct utimes_args { 2841 char *path; 2842 struct timeval *tptr; 2843 }; 2844 #endif 2845 int 2846 utimes(td, uap) 2847 struct thread *td; 2848 register struct utimes_args /* { 2849 char *path; 2850 struct timeval *tptr; 2851 } */ *uap; 2852 { 2853 2854 return (kern_utimes(td, uap->path, UIO_USERSPACE, uap->tptr, 2855 UIO_USERSPACE)); 2856 } 2857 2858 int 2859 kern_utimes(struct thread *td, char *path, enum uio_seg pathseg, 2860 struct timeval *tptr, enum uio_seg tptrseg) 2861 { 2862 struct timespec ts[2]; 2863 int error; 2864 struct nameidata nd; 2865 int vfslocked; 2866 2867 if ((error = getutimes(tptr, tptrseg, ts)) != 0) 2868 return (error); 2869 NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td); 2870 if ((error = namei(&nd)) != 0) 2871 return (error); 2872 vfslocked = NDHASGIANT(&nd); 2873 NDFREE(&nd, NDF_ONLY_PNBUF); 2874 error = setutimes(td, nd.ni_vp, ts, 2, tptr == NULL); 2875 vrele(nd.ni_vp); 2876 VFS_UNLOCK_GIANT(vfslocked); 2877 return (error); 2878 } 2879 2880 /* 2881 * Set the access and modification times of a file. 2882 */ 2883 #ifndef _SYS_SYSPROTO_H_ 2884 struct lutimes_args { 2885 char *path; 2886 struct timeval *tptr; 2887 }; 2888 #endif 2889 int 2890 lutimes(td, uap) 2891 struct thread *td; 2892 register struct lutimes_args /* { 2893 char *path; 2894 struct timeval *tptr; 2895 } */ *uap; 2896 { 2897 2898 return (kern_lutimes(td, uap->path, UIO_USERSPACE, uap->tptr, 2899 UIO_USERSPACE)); 2900 } 2901 2902 int 2903 kern_lutimes(struct thread *td, char *path, enum uio_seg pathseg, 2904 struct timeval *tptr, enum uio_seg tptrseg) 2905 { 2906 struct timespec ts[2]; 2907 int error; 2908 struct nameidata nd; 2909 int vfslocked; 2910 2911 if ((error = getutimes(tptr, tptrseg, ts)) != 0) 2912 return (error); 2913 NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td); 2914 if ((error = namei(&nd)) != 0) 2915 return (error); 2916 vfslocked = NDHASGIANT(&nd); 2917 NDFREE(&nd, NDF_ONLY_PNBUF); 2918 error = setutimes(td, nd.ni_vp, ts, 2, tptr == NULL); 2919 vrele(nd.ni_vp); 2920 VFS_UNLOCK_GIANT(vfslocked); 2921 return (error); 2922 } 2923 2924 /* 2925 * Set the access and modification times of a file. 2926 */ 2927 #ifndef _SYS_SYSPROTO_H_ 2928 struct futimes_args { 2929 int fd; 2930 struct timeval *tptr; 2931 }; 2932 #endif 2933 int 2934 futimes(td, uap) 2935 struct thread *td; 2936 register struct futimes_args /* { 2937 int fd; 2938 struct timeval *tptr; 2939 } */ *uap; 2940 { 2941 2942 return (kern_futimes(td, uap->fd, uap->tptr, UIO_USERSPACE)); 2943 } 2944 2945 int 2946 kern_futimes(struct thread *td, int fd, struct timeval *tptr, 2947 enum uio_seg tptrseg) 2948 { 2949 struct timespec ts[2]; 2950 struct file *fp; 2951 int vfslocked; 2952 int error; 2953 2954 AUDIT_ARG(fd, fd); 2955 if ((error = getutimes(tptr, tptrseg, ts)) != 0) 2956 return (error); 2957 if ((error = getvnode(td->td_proc->p_fd, fd, &fp)) != 0) 2958 return (error); 2959 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); 2960 #ifdef AUDIT 2961 vn_lock(fp->f_vnode, LK_EXCLUSIVE | LK_RETRY, td); 2962 AUDIT_ARG(vnode, fp->f_vnode, ARG_VNODE1); 2963 VOP_UNLOCK(fp->f_vnode, 0, td); 2964 #endif 2965 error = setutimes(td, fp->f_vnode, ts, 2, tptr == NULL); 2966 VFS_UNLOCK_GIANT(vfslocked); 2967 fdrop(fp, td); 2968 return (error); 2969 } 2970 2971 /* 2972 * Truncate a file given its path name. 2973 */ 2974 #ifndef _SYS_SYSPROTO_H_ 2975 struct truncate_args { 2976 char *path; 2977 int pad; 2978 off_t length; 2979 }; 2980 #endif 2981 int 2982 truncate(td, uap) 2983 struct thread *td; 2984 register struct truncate_args /* { 2985 char *path; 2986 int pad; 2987 off_t length; 2988 } */ *uap; 2989 { 2990 2991 return (kern_truncate(td, uap->path, UIO_USERSPACE, uap->length)); 2992 } 2993 2994 int 2995 kern_truncate(struct thread *td, char *path, enum uio_seg pathseg, off_t length) 2996 { 2997 struct mount *mp; 2998 struct vnode *vp; 2999 struct vattr vattr; 3000 int error; 3001 struct nameidata nd; 3002 int vfslocked; 3003 3004 if (length < 0) 3005 return(EINVAL); 3006 NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td); 3007 if ((error = namei(&nd)) != 0) 3008 return (error); 3009 vfslocked = NDHASGIANT(&nd); 3010 vp = nd.ni_vp; 3011 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) { 3012 vrele(vp); 3013 VFS_UNLOCK_GIANT(vfslocked); 3014 return (error); 3015 } 3016 NDFREE(&nd, NDF_ONLY_PNBUF); 3017 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 3018 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3019 if (vp->v_type == VDIR) 3020 error = EISDIR; 3021 #ifdef MAC 3022 else if ((error = mac_check_vnode_write(td->td_ucred, NOCRED, vp))) { 3023 } 3024 #endif 3025 else if ((error = vn_writechk(vp)) == 0 && 3026 (error = VOP_ACCESS(vp, VWRITE, td->td_ucred, td)) == 0) { 3027 VATTR_NULL(&vattr); 3028 vattr.va_size = length; 3029 error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); 3030 } 3031 vput(vp); 3032 vn_finished_write(mp); 3033 VFS_UNLOCK_GIANT(vfslocked); 3034 return (error); 3035 } 3036 3037 /* 3038 * Truncate a file given a file descriptor. 3039 */ 3040 #ifndef _SYS_SYSPROTO_H_ 3041 struct ftruncate_args { 3042 int fd; 3043 int pad; 3044 off_t length; 3045 }; 3046 #endif 3047 int 3048 ftruncate(td, uap) 3049 struct thread *td; 3050 register struct ftruncate_args /* { 3051 int fd; 3052 int pad; 3053 off_t length; 3054 } */ *uap; 3055 { 3056 struct mount *mp; 3057 struct vattr vattr; 3058 struct vnode *vp; 3059 struct file *fp; 3060 int vfslocked; 3061 int error; 3062 3063 AUDIT_ARG(fd, uap->fd); 3064 if (uap->length < 0) 3065 return(EINVAL); 3066 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) 3067 return (error); 3068 if ((fp->f_flag & FWRITE) == 0) { 3069 fdrop(fp, td); 3070 return (EINVAL); 3071 } 3072 vp = fp->f_vnode; 3073 vfslocked = VFS_LOCK_GIANT(vp->v_mount); 3074 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 3075 goto drop; 3076 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 3077 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3078 AUDIT_ARG(vnode, vp, ARG_VNODE1); 3079 if (vp->v_type == VDIR) 3080 error = EISDIR; 3081 #ifdef MAC 3082 else if ((error = mac_check_vnode_write(td->td_ucred, fp->f_cred, 3083 vp))) { 3084 } 3085 #endif 3086 else if ((error = vn_writechk(vp)) == 0) { 3087 VATTR_NULL(&vattr); 3088 vattr.va_size = uap->length; 3089 error = VOP_SETATTR(vp, &vattr, fp->f_cred, td); 3090 } 3091 VOP_UNLOCK(vp, 0, td); 3092 vn_finished_write(mp); 3093 drop: 3094 VFS_UNLOCK_GIANT(vfslocked); 3095 fdrop(fp, td); 3096 return (error); 3097 } 3098 3099 #if defined(COMPAT_43) 3100 /* 3101 * Truncate a file given its path name. 3102 */ 3103 #ifndef _SYS_SYSPROTO_H_ 3104 struct otruncate_args { 3105 char *path; 3106 long length; 3107 }; 3108 #endif 3109 int 3110 otruncate(td, uap) 3111 struct thread *td; 3112 register struct otruncate_args /* { 3113 char *path; 3114 long length; 3115 } */ *uap; 3116 { 3117 struct truncate_args /* { 3118 char *path; 3119 int pad; 3120 off_t length; 3121 } */ nuap; 3122 3123 nuap.path = uap->path; 3124 nuap.length = uap->length; 3125 return (truncate(td, &nuap)); 3126 } 3127 3128 /* 3129 * Truncate a file given a file descriptor. 3130 */ 3131 #ifndef _SYS_SYSPROTO_H_ 3132 struct oftruncate_args { 3133 int fd; 3134 long length; 3135 }; 3136 #endif 3137 int 3138 oftruncate(td, uap) 3139 struct thread *td; 3140 register struct oftruncate_args /* { 3141 int fd; 3142 long length; 3143 } */ *uap; 3144 { 3145 struct ftruncate_args /* { 3146 int fd; 3147 int pad; 3148 off_t length; 3149 } */ nuap; 3150 3151 nuap.fd = uap->fd; 3152 nuap.length = uap->length; 3153 return (ftruncate(td, &nuap)); 3154 } 3155 #endif /* COMPAT_43 */ 3156 3157 /* 3158 * Sync an open file. 3159 */ 3160 #ifndef _SYS_SYSPROTO_H_ 3161 struct fsync_args { 3162 int fd; 3163 }; 3164 #endif 3165 int 3166 fsync(td, uap) 3167 struct thread *td; 3168 struct fsync_args /* { 3169 int fd; 3170 } */ *uap; 3171 { 3172 struct vnode *vp; 3173 struct mount *mp; 3174 struct file *fp; 3175 int vfslocked; 3176 int error; 3177 3178 AUDIT_ARG(fd, uap->fd); 3179 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) 3180 return (error); 3181 vp = fp->f_vnode; 3182 vfslocked = VFS_LOCK_GIANT(vp->v_mount); 3183 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 3184 goto drop; 3185 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3186 AUDIT_ARG(vnode, vp, ARG_VNODE1); 3187 if (vp->v_object != NULL) { 3188 VM_OBJECT_LOCK(vp->v_object); 3189 vm_object_page_clean(vp->v_object, 0, 0, 0); 3190 VM_OBJECT_UNLOCK(vp->v_object); 3191 } 3192 error = VOP_FSYNC(vp, MNT_WAIT, td); 3193 3194 VOP_UNLOCK(vp, 0, td); 3195 vn_finished_write(mp); 3196 drop: 3197 VFS_UNLOCK_GIANT(vfslocked); 3198 fdrop(fp, td); 3199 return (error); 3200 } 3201 3202 /* 3203 * Rename files. Source and destination must either both be directories, or 3204 * both not be directories. If target is a directory, it must be empty. 3205 */ 3206 #ifndef _SYS_SYSPROTO_H_ 3207 struct rename_args { 3208 char *from; 3209 char *to; 3210 }; 3211 #endif 3212 int 3213 rename(td, uap) 3214 struct thread *td; 3215 register struct rename_args /* { 3216 char *from; 3217 char *to; 3218 } */ *uap; 3219 { 3220 3221 return (kern_rename(td, uap->from, uap->to, UIO_USERSPACE)); 3222 } 3223 3224 int 3225 kern_rename(struct thread *td, char *from, char *to, enum uio_seg pathseg) 3226 { 3227 struct mount *mp = NULL; 3228 struct vnode *tvp, *fvp, *tdvp; 3229 struct nameidata fromnd, tond; 3230 int tvfslocked; 3231 int fvfslocked; 3232 int error; 3233 3234 bwillwrite(); 3235 #ifdef MAC 3236 NDINIT(&fromnd, DELETE, LOCKPARENT | LOCKLEAF | SAVESTART | MPSAFE | 3237 AUDITVNODE1, pathseg, from, td); 3238 #else 3239 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART | MPSAFE | 3240 AUDITVNODE1, pathseg, from, td); 3241 #endif 3242 if ((error = namei(&fromnd)) != 0) 3243 return (error); 3244 fvfslocked = NDHASGIANT(&fromnd); 3245 tvfslocked = 0; 3246 #ifdef MAC 3247 error = mac_check_vnode_rename_from(td->td_ucred, fromnd.ni_dvp, 3248 fromnd.ni_vp, &fromnd.ni_cnd); 3249 VOP_UNLOCK(fromnd.ni_dvp, 0, td); 3250 if (fromnd.ni_dvp != fromnd.ni_vp) 3251 VOP_UNLOCK(fromnd.ni_vp, 0, td); 3252 #endif 3253 fvp = fromnd.ni_vp; 3254 if (error == 0) 3255 error = vn_start_write(fvp, &mp, V_WAIT | PCATCH); 3256 if (error != 0) { 3257 NDFREE(&fromnd, NDF_ONLY_PNBUF); 3258 vrele(fromnd.ni_dvp); 3259 vrele(fvp); 3260 goto out1; 3261 } 3262 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | 3263 MPSAFE | AUDITVNODE2, pathseg, to, td); 3264 if (fromnd.ni_vp->v_type == VDIR) 3265 tond.ni_cnd.cn_flags |= WILLBEDIR; 3266 if ((error = namei(&tond)) != 0) { 3267 /* Translate error code for rename("dir1", "dir2/."). */ 3268 if (error == EISDIR && fvp->v_type == VDIR) 3269 error = EINVAL; 3270 NDFREE(&fromnd, NDF_ONLY_PNBUF); 3271 vrele(fromnd.ni_dvp); 3272 vrele(fvp); 3273 vn_finished_write(mp); 3274 goto out1; 3275 } 3276 tvfslocked = NDHASGIANT(&tond); 3277 tdvp = tond.ni_dvp; 3278 tvp = tond.ni_vp; 3279 if (tvp != NULL) { 3280 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 3281 error = ENOTDIR; 3282 goto out; 3283 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 3284 error = EISDIR; 3285 goto out; 3286 } 3287 } 3288 if (fvp == tdvp) 3289 error = EINVAL; 3290 /* 3291 * If the source is the same as the destination (that is, if they 3292 * are links to the same vnode), then there is nothing to do. 3293 */ 3294 if (fvp == tvp) 3295 error = -1; 3296 #ifdef MAC 3297 else 3298 error = mac_check_vnode_rename_to(td->td_ucred, tdvp, 3299 tond.ni_vp, fromnd.ni_dvp == tdvp, &tond.ni_cnd); 3300 #endif 3301 out: 3302 if (!error) { 3303 VOP_LEASE(tdvp, td, td->td_ucred, LEASE_WRITE); 3304 if (fromnd.ni_dvp != tdvp) { 3305 VOP_LEASE(fromnd.ni_dvp, td, td->td_ucred, LEASE_WRITE); 3306 } 3307 if (tvp) { 3308 VOP_LEASE(tvp, td, td->td_ucred, LEASE_WRITE); 3309 } 3310 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 3311 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 3312 NDFREE(&fromnd, NDF_ONLY_PNBUF); 3313 NDFREE(&tond, NDF_ONLY_PNBUF); 3314 } else { 3315 NDFREE(&fromnd, NDF_ONLY_PNBUF); 3316 NDFREE(&tond, NDF_ONLY_PNBUF); 3317 if (tvp) 3318 vput(tvp); 3319 if (tdvp == tvp) 3320 vrele(tdvp); 3321 else 3322 vput(tdvp); 3323 vrele(fromnd.ni_dvp); 3324 vrele(fvp); 3325 } 3326 vrele(tond.ni_startdir); 3327 vn_finished_write(mp); 3328 out1: 3329 if (fromnd.ni_startdir) 3330 vrele(fromnd.ni_startdir); 3331 VFS_UNLOCK_GIANT(fvfslocked); 3332 VFS_UNLOCK_GIANT(tvfslocked); 3333 if (error == -1) 3334 return (0); 3335 return (error); 3336 } 3337 3338 /* 3339 * Make a directory file. 3340 */ 3341 #ifndef _SYS_SYSPROTO_H_ 3342 struct mkdir_args { 3343 char *path; 3344 int mode; 3345 }; 3346 #endif 3347 int 3348 mkdir(td, uap) 3349 struct thread *td; 3350 register struct mkdir_args /* { 3351 char *path; 3352 int mode; 3353 } */ *uap; 3354 { 3355 3356 return (kern_mkdir(td, uap->path, UIO_USERSPACE, uap->mode)); 3357 } 3358 3359 int 3360 kern_mkdir(struct thread *td, char *path, enum uio_seg segflg, int mode) 3361 { 3362 struct mount *mp; 3363 struct vnode *vp; 3364 struct vattr vattr; 3365 int error; 3366 struct nameidata nd; 3367 int vfslocked; 3368 3369 AUDIT_ARG(mode, mode); 3370 restart: 3371 bwillwrite(); 3372 NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1, 3373 segflg, path, td); 3374 nd.ni_cnd.cn_flags |= WILLBEDIR; 3375 if ((error = namei(&nd)) != 0) 3376 return (error); 3377 vfslocked = NDHASGIANT(&nd); 3378 vp = nd.ni_vp; 3379 if (vp != NULL) { 3380 NDFREE(&nd, NDF_ONLY_PNBUF); 3381 /* 3382 * XXX namei called with LOCKPARENT but not LOCKLEAF has 3383 * the strange behaviour of leaving the vnode unlocked 3384 * if the target is the same vnode as the parent. 3385 */ 3386 if (vp == nd.ni_dvp) 3387 vrele(nd.ni_dvp); 3388 else 3389 vput(nd.ni_dvp); 3390 vrele(vp); 3391 VFS_UNLOCK_GIANT(vfslocked); 3392 return (EEXIST); 3393 } 3394 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 3395 NDFREE(&nd, NDF_ONLY_PNBUF); 3396 vput(nd.ni_dvp); 3397 VFS_UNLOCK_GIANT(vfslocked); 3398 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 3399 return (error); 3400 goto restart; 3401 } 3402 VATTR_NULL(&vattr); 3403 vattr.va_type = VDIR; 3404 FILEDESC_SLOCK(td->td_proc->p_fd); 3405 vattr.va_mode = (mode & ACCESSPERMS) &~ td->td_proc->p_fd->fd_cmask; 3406 FILEDESC_SUNLOCK(td->td_proc->p_fd); 3407 #ifdef MAC 3408 error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd, 3409 &vattr); 3410 if (error) 3411 goto out; 3412 #endif 3413 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); 3414 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 3415 #ifdef MAC 3416 out: 3417 #endif 3418 NDFREE(&nd, NDF_ONLY_PNBUF); 3419 vput(nd.ni_dvp); 3420 if (!error) 3421 vput(nd.ni_vp); 3422 vn_finished_write(mp); 3423 VFS_UNLOCK_GIANT(vfslocked); 3424 return (error); 3425 } 3426 3427 /* 3428 * Remove a directory file. 3429 */ 3430 #ifndef _SYS_SYSPROTO_H_ 3431 struct rmdir_args { 3432 char *path; 3433 }; 3434 #endif 3435 int 3436 rmdir(td, uap) 3437 struct thread *td; 3438 struct rmdir_args /* { 3439 char *path; 3440 } */ *uap; 3441 { 3442 3443 return (kern_rmdir(td, uap->path, UIO_USERSPACE)); 3444 } 3445 3446 int 3447 kern_rmdir(struct thread *td, char *path, enum uio_seg pathseg) 3448 { 3449 struct mount *mp; 3450 struct vnode *vp; 3451 int error; 3452 struct nameidata nd; 3453 int vfslocked; 3454 3455 restart: 3456 bwillwrite(); 3457 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF | MPSAFE | AUDITVNODE1, 3458 pathseg, path, td); 3459 if ((error = namei(&nd)) != 0) 3460 return (error); 3461 vfslocked = NDHASGIANT(&nd); 3462 vp = nd.ni_vp; 3463 if (vp->v_type != VDIR) { 3464 error = ENOTDIR; 3465 goto out; 3466 } 3467 /* 3468 * No rmdir "." please. 3469 */ 3470 if (nd.ni_dvp == vp) { 3471 error = EINVAL; 3472 goto out; 3473 } 3474 /* 3475 * The root of a mounted filesystem cannot be deleted. 3476 */ 3477 if (vp->v_vflag & VV_ROOT) { 3478 error = EBUSY; 3479 goto out; 3480 } 3481 #ifdef MAC 3482 error = mac_check_vnode_delete(td->td_ucred, nd.ni_dvp, vp, 3483 &nd.ni_cnd); 3484 if (error) 3485 goto out; 3486 #endif 3487 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 3488 NDFREE(&nd, NDF_ONLY_PNBUF); 3489 vput(vp); 3490 if (nd.ni_dvp == vp) 3491 vrele(nd.ni_dvp); 3492 else 3493 vput(nd.ni_dvp); 3494 VFS_UNLOCK_GIANT(vfslocked); 3495 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 3496 return (error); 3497 goto restart; 3498 } 3499 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); 3500 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 3501 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 3502 vn_finished_write(mp); 3503 out: 3504 NDFREE(&nd, NDF_ONLY_PNBUF); 3505 vput(vp); 3506 if (nd.ni_dvp == vp) 3507 vrele(nd.ni_dvp); 3508 else 3509 vput(nd.ni_dvp); 3510 VFS_UNLOCK_GIANT(vfslocked); 3511 return (error); 3512 } 3513 3514 #ifdef COMPAT_43 3515 /* 3516 * Read a block of directory entries in a filesystem independent format. 3517 */ 3518 #ifndef _SYS_SYSPROTO_H_ 3519 struct ogetdirentries_args { 3520 int fd; 3521 char *buf; 3522 u_int count; 3523 long *basep; 3524 }; 3525 #endif 3526 int 3527 ogetdirentries(td, uap) 3528 struct thread *td; 3529 register struct ogetdirentries_args /* { 3530 int fd; 3531 char *buf; 3532 u_int count; 3533 long *basep; 3534 } */ *uap; 3535 { 3536 struct vnode *vp; 3537 struct file *fp; 3538 struct uio auio, kuio; 3539 struct iovec aiov, kiov; 3540 struct dirent *dp, *edp; 3541 caddr_t dirbuf; 3542 int error, eofflag, readcnt, vfslocked; 3543 long loff; 3544 3545 /* XXX arbitrary sanity limit on `count'. */ 3546 if (uap->count > 64 * 1024) 3547 return (EINVAL); 3548 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) 3549 return (error); 3550 if ((fp->f_flag & FREAD) == 0) { 3551 fdrop(fp, td); 3552 return (EBADF); 3553 } 3554 vp = fp->f_vnode; 3555 unionread: 3556 vfslocked = VFS_LOCK_GIANT(vp->v_mount); 3557 if (vp->v_type != VDIR) { 3558 VFS_UNLOCK_GIANT(vfslocked); 3559 fdrop(fp, td); 3560 return (EINVAL); 3561 } 3562 aiov.iov_base = uap->buf; 3563 aiov.iov_len = uap->count; 3564 auio.uio_iov = &aiov; 3565 auio.uio_iovcnt = 1; 3566 auio.uio_rw = UIO_READ; 3567 auio.uio_segflg = UIO_USERSPACE; 3568 auio.uio_td = td; 3569 auio.uio_resid = uap->count; 3570 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3571 loff = auio.uio_offset = fp->f_offset; 3572 #ifdef MAC 3573 error = mac_check_vnode_readdir(td->td_ucred, vp); 3574 if (error) { 3575 VOP_UNLOCK(vp, 0, td); 3576 VFS_UNLOCK_GIANT(vfslocked); 3577 fdrop(fp, td); 3578 return (error); 3579 } 3580 #endif 3581 # if (BYTE_ORDER != LITTLE_ENDIAN) 3582 if (vp->v_mount->mnt_maxsymlinklen <= 0) { 3583 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, 3584 NULL, NULL); 3585 fp->f_offset = auio.uio_offset; 3586 } else 3587 # endif 3588 { 3589 kuio = auio; 3590 kuio.uio_iov = &kiov; 3591 kuio.uio_segflg = UIO_SYSSPACE; 3592 kiov.iov_len = uap->count; 3593 MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK); 3594 kiov.iov_base = dirbuf; 3595 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag, 3596 NULL, NULL); 3597 fp->f_offset = kuio.uio_offset; 3598 if (error == 0) { 3599 readcnt = uap->count - kuio.uio_resid; 3600 edp = (struct dirent *)&dirbuf[readcnt]; 3601 for (dp = (struct dirent *)dirbuf; dp < edp; ) { 3602 # if (BYTE_ORDER == LITTLE_ENDIAN) 3603 /* 3604 * The expected low byte of 3605 * dp->d_namlen is our dp->d_type. 3606 * The high MBZ byte of dp->d_namlen 3607 * is our dp->d_namlen. 3608 */ 3609 dp->d_type = dp->d_namlen; 3610 dp->d_namlen = 0; 3611 # else 3612 /* 3613 * The dp->d_type is the high byte 3614 * of the expected dp->d_namlen, 3615 * so must be zero'ed. 3616 */ 3617 dp->d_type = 0; 3618 # endif 3619 if (dp->d_reclen > 0) { 3620 dp = (struct dirent *) 3621 ((char *)dp + dp->d_reclen); 3622 } else { 3623 error = EIO; 3624 break; 3625 } 3626 } 3627 if (dp >= edp) 3628 error = uiomove(dirbuf, readcnt, &auio); 3629 } 3630 FREE(dirbuf, M_TEMP); 3631 } 3632 if (error) { 3633 VOP_UNLOCK(vp, 0, td); 3634 VFS_UNLOCK_GIANT(vfslocked); 3635 fdrop(fp, td); 3636 return (error); 3637 } 3638 if (uap->count == auio.uio_resid && 3639 (vp->v_vflag & VV_ROOT) && 3640 (vp->v_mount->mnt_flag & MNT_UNION)) { 3641 struct vnode *tvp = vp; 3642 vp = vp->v_mount->mnt_vnodecovered; 3643 VREF(vp); 3644 fp->f_vnode = vp; 3645 fp->f_data = vp; 3646 fp->f_offset = 0; 3647 vput(tvp); 3648 VFS_UNLOCK_GIANT(vfslocked); 3649 goto unionread; 3650 } 3651 VOP_UNLOCK(vp, 0, td); 3652 VFS_UNLOCK_GIANT(vfslocked); 3653 error = copyout(&loff, uap->basep, sizeof(long)); 3654 fdrop(fp, td); 3655 td->td_retval[0] = uap->count - auio.uio_resid; 3656 return (error); 3657 } 3658 #endif /* COMPAT_43 */ 3659 3660 /* 3661 * Read a block of directory entries in a filesystem independent format. 3662 */ 3663 #ifndef _SYS_SYSPROTO_H_ 3664 struct getdirentries_args { 3665 int fd; 3666 char *buf; 3667 u_int count; 3668 long *basep; 3669 }; 3670 #endif 3671 int 3672 getdirentries(td, uap) 3673 struct thread *td; 3674 register struct getdirentries_args /* { 3675 int fd; 3676 char *buf; 3677 u_int count; 3678 long *basep; 3679 } */ *uap; 3680 { 3681 struct vnode *vp; 3682 struct file *fp; 3683 struct uio auio; 3684 struct iovec aiov; 3685 int vfslocked; 3686 long loff; 3687 int error, eofflag; 3688 3689 AUDIT_ARG(fd, uap->fd); 3690 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) 3691 return (error); 3692 if ((fp->f_flag & FREAD) == 0) { 3693 fdrop(fp, td); 3694 return (EBADF); 3695 } 3696 vp = fp->f_vnode; 3697 unionread: 3698 vfslocked = VFS_LOCK_GIANT(vp->v_mount); 3699 if (vp->v_type != VDIR) { 3700 VFS_UNLOCK_GIANT(vfslocked); 3701 error = EINVAL; 3702 goto fail; 3703 } 3704 aiov.iov_base = uap->buf; 3705 aiov.iov_len = uap->count; 3706 auio.uio_iov = &aiov; 3707 auio.uio_iovcnt = 1; 3708 auio.uio_rw = UIO_READ; 3709 auio.uio_segflg = UIO_USERSPACE; 3710 auio.uio_td = td; 3711 auio.uio_resid = uap->count; 3712 /* vn_lock(vp, LK_SHARED | LK_RETRY, td); */ 3713 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3714 AUDIT_ARG(vnode, vp, ARG_VNODE1); 3715 loff = auio.uio_offset = fp->f_offset; 3716 #ifdef MAC 3717 error = mac_check_vnode_readdir(td->td_ucred, vp); 3718 if (error == 0) 3719 #endif 3720 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, 3721 NULL); 3722 fp->f_offset = auio.uio_offset; 3723 if (error) { 3724 VOP_UNLOCK(vp, 0, td); 3725 VFS_UNLOCK_GIANT(vfslocked); 3726 goto fail; 3727 } 3728 if (uap->count == auio.uio_resid && 3729 (vp->v_vflag & VV_ROOT) && 3730 (vp->v_mount->mnt_flag & MNT_UNION)) { 3731 struct vnode *tvp = vp; 3732 vp = vp->v_mount->mnt_vnodecovered; 3733 VREF(vp); 3734 fp->f_vnode = vp; 3735 fp->f_data = vp; 3736 fp->f_offset = 0; 3737 vput(tvp); 3738 VFS_UNLOCK_GIANT(vfslocked); 3739 goto unionread; 3740 } 3741 VOP_UNLOCK(vp, 0, td); 3742 VFS_UNLOCK_GIANT(vfslocked); 3743 if (uap->basep != NULL) { 3744 error = copyout(&loff, uap->basep, sizeof(long)); 3745 } 3746 td->td_retval[0] = uap->count - auio.uio_resid; 3747 fail: 3748 fdrop(fp, td); 3749 return (error); 3750 } 3751 3752 #ifndef _SYS_SYSPROTO_H_ 3753 struct getdents_args { 3754 int fd; 3755 char *buf; 3756 size_t count; 3757 }; 3758 #endif 3759 int 3760 getdents(td, uap) 3761 struct thread *td; 3762 register struct getdents_args /* { 3763 int fd; 3764 char *buf; 3765 u_int count; 3766 } */ *uap; 3767 { 3768 struct getdirentries_args ap; 3769 ap.fd = uap->fd; 3770 ap.buf = uap->buf; 3771 ap.count = uap->count; 3772 ap.basep = NULL; 3773 return (getdirentries(td, &ap)); 3774 } 3775 3776 /* 3777 * Set the mode mask for creation of filesystem nodes. 3778 */ 3779 #ifndef _SYS_SYSPROTO_H_ 3780 struct umask_args { 3781 int newmask; 3782 }; 3783 #endif 3784 int 3785 umask(td, uap) 3786 struct thread *td; 3787 struct umask_args /* { 3788 int newmask; 3789 } */ *uap; 3790 { 3791 register struct filedesc *fdp; 3792 3793 FILEDESC_XLOCK(td->td_proc->p_fd); 3794 fdp = td->td_proc->p_fd; 3795 td->td_retval[0] = fdp->fd_cmask; 3796 fdp->fd_cmask = uap->newmask & ALLPERMS; 3797 FILEDESC_XUNLOCK(td->td_proc->p_fd); 3798 return (0); 3799 } 3800 3801 /* 3802 * Void all references to file by ripping underlying filesystem away from 3803 * vnode. 3804 */ 3805 #ifndef _SYS_SYSPROTO_H_ 3806 struct revoke_args { 3807 char *path; 3808 }; 3809 #endif 3810 int 3811 revoke(td, uap) 3812 struct thread *td; 3813 register struct revoke_args /* { 3814 char *path; 3815 } */ *uap; 3816 { 3817 struct vnode *vp; 3818 struct vattr vattr; 3819 int error; 3820 struct nameidata nd; 3821 int vfslocked; 3822 3823 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, 3824 UIO_USERSPACE, uap->path, td); 3825 if ((error = namei(&nd)) != 0) 3826 return (error); 3827 vfslocked = NDHASGIANT(&nd); 3828 vp = nd.ni_vp; 3829 NDFREE(&nd, NDF_ONLY_PNBUF); 3830 if (vp->v_type != VCHR) { 3831 error = EINVAL; 3832 goto out; 3833 } 3834 #ifdef MAC 3835 error = mac_check_vnode_revoke(td->td_ucred, vp); 3836 if (error) 3837 goto out; 3838 #endif 3839 error = VOP_GETATTR(vp, &vattr, td->td_ucred, td); 3840 if (error) 3841 goto out; 3842 if (td->td_ucred->cr_uid != vattr.va_uid) { 3843 error = priv_check_cred(td->td_ucred, PRIV_VFS_ADMIN, 3844 SUSER_ALLOWJAIL); 3845 if (error) 3846 goto out; 3847 } 3848 if (vcount(vp) > 1) 3849 VOP_REVOKE(vp, REVOKEALL); 3850 out: 3851 vput(vp); 3852 VFS_UNLOCK_GIANT(vfslocked); 3853 return (error); 3854 } 3855 3856 /* 3857 * Convert a user file descriptor to a kernel file entry. 3858 * A reference on the file entry is held upon returning. 3859 */ 3860 int 3861 getvnode(fdp, fd, fpp) 3862 struct filedesc *fdp; 3863 int fd; 3864 struct file **fpp; 3865 { 3866 int error; 3867 struct file *fp; 3868 3869 fp = NULL; 3870 if (fdp == NULL) 3871 error = EBADF; 3872 else { 3873 FILEDESC_SLOCK(fdp); 3874 if ((u_int)fd >= fdp->fd_nfiles || 3875 (fp = fdp->fd_ofiles[fd]) == NULL) 3876 error = EBADF; 3877 else if (fp->f_vnode == NULL) { 3878 fp = NULL; 3879 error = EINVAL; 3880 } else { 3881 fhold(fp); 3882 error = 0; 3883 } 3884 FILEDESC_SUNLOCK(fdp); 3885 } 3886 *fpp = fp; 3887 return (error); 3888 } 3889 3890 /* 3891 * Get an (NFS) file handle. 3892 */ 3893 #ifndef _SYS_SYSPROTO_H_ 3894 struct lgetfh_args { 3895 char *fname; 3896 fhandle_t *fhp; 3897 }; 3898 #endif 3899 int 3900 lgetfh(td, uap) 3901 struct thread *td; 3902 register struct lgetfh_args *uap; 3903 { 3904 struct nameidata nd; 3905 fhandle_t fh; 3906 register struct vnode *vp; 3907 int vfslocked; 3908 int error; 3909 3910 error = priv_check(td, PRIV_VFS_GETFH); 3911 if (error) 3912 return (error); 3913 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, 3914 UIO_USERSPACE, uap->fname, td); 3915 error = namei(&nd); 3916 if (error) 3917 return (error); 3918 vfslocked = NDHASGIANT(&nd); 3919 NDFREE(&nd, NDF_ONLY_PNBUF); 3920 vp = nd.ni_vp; 3921 bzero(&fh, sizeof(fh)); 3922 fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid; 3923 error = VOP_VPTOFH(vp, &fh.fh_fid); 3924 vput(vp); 3925 VFS_UNLOCK_GIANT(vfslocked); 3926 if (error) 3927 return (error); 3928 error = copyout(&fh, uap->fhp, sizeof (fh)); 3929 return (error); 3930 } 3931 3932 #ifndef _SYS_SYSPROTO_H_ 3933 struct getfh_args { 3934 char *fname; 3935 fhandle_t *fhp; 3936 }; 3937 #endif 3938 int 3939 getfh(td, uap) 3940 struct thread *td; 3941 register struct getfh_args *uap; 3942 { 3943 struct nameidata nd; 3944 fhandle_t fh; 3945 register struct vnode *vp; 3946 int vfslocked; 3947 int error; 3948 3949 error = priv_check(td, PRIV_VFS_GETFH); 3950 if (error) 3951 return (error); 3952 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, 3953 UIO_USERSPACE, uap->fname, td); 3954 error = namei(&nd); 3955 if (error) 3956 return (error); 3957 vfslocked = NDHASGIANT(&nd); 3958 NDFREE(&nd, NDF_ONLY_PNBUF); 3959 vp = nd.ni_vp; 3960 bzero(&fh, sizeof(fh)); 3961 fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid; 3962 error = VOP_VPTOFH(vp, &fh.fh_fid); 3963 vput(vp); 3964 VFS_UNLOCK_GIANT(vfslocked); 3965 if (error) 3966 return (error); 3967 error = copyout(&fh, uap->fhp, sizeof (fh)); 3968 return (error); 3969 } 3970 3971 /* 3972 * syscall for the rpc.lockd to use to translate a NFS file handle into an 3973 * open descriptor. 3974 * 3975 * warning: do not remove the priv_check() call or this becomes one giant 3976 * security hole. 3977 */ 3978 #ifndef _SYS_SYSPROTO_H_ 3979 struct fhopen_args { 3980 const struct fhandle *u_fhp; 3981 int flags; 3982 }; 3983 #endif 3984 int 3985 fhopen(td, uap) 3986 struct thread *td; 3987 struct fhopen_args /* { 3988 const struct fhandle *u_fhp; 3989 int flags; 3990 } */ *uap; 3991 { 3992 struct proc *p = td->td_proc; 3993 struct mount *mp; 3994 struct vnode *vp; 3995 struct fhandle fhp; 3996 struct vattr vat; 3997 struct vattr *vap = &vat; 3998 struct flock lf; 3999 struct file *fp; 4000 register struct filedesc *fdp = p->p_fd; 4001 int fmode, mode, error, type; 4002 struct file *nfp; 4003 int vfslocked; 4004 int indx; 4005 4006 error = priv_check(td, PRIV_VFS_FHOPEN); 4007 if (error) 4008 return (error); 4009 fmode = FFLAGS(uap->flags); 4010 /* why not allow a non-read/write open for our lockd? */ 4011 if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT)) 4012 return (EINVAL); 4013 error = copyin(uap->u_fhp, &fhp, sizeof(fhp)); 4014 if (error) 4015 return(error); 4016 /* find the mount point */ 4017 mp = vfs_getvfs(&fhp.fh_fsid); 4018 if (mp == NULL) 4019 return (ESTALE); 4020 vfslocked = VFS_LOCK_GIANT(mp); 4021 /* now give me my vnode, it gets returned to me locked */ 4022 error = VFS_FHTOVP(mp, &fhp.fh_fid, &vp); 4023 if (error) 4024 goto out; 4025 /* 4026 * from now on we have to make sure not 4027 * to forget about the vnode 4028 * any error that causes an abort must vput(vp) 4029 * just set error = err and 'goto bad;'. 4030 */ 4031 4032 /* 4033 * from vn_open 4034 */ 4035 if (vp->v_type == VLNK) { 4036 error = EMLINK; 4037 goto bad; 4038 } 4039 if (vp->v_type == VSOCK) { 4040 error = EOPNOTSUPP; 4041 goto bad; 4042 } 4043 mode = 0; 4044 if (fmode & (FWRITE | O_TRUNC)) { 4045 if (vp->v_type == VDIR) { 4046 error = EISDIR; 4047 goto bad; 4048 } 4049 error = vn_writechk(vp); 4050 if (error) 4051 goto bad; 4052 mode |= VWRITE; 4053 } 4054 if (fmode & FREAD) 4055 mode |= VREAD; 4056 if (fmode & O_APPEND) 4057 mode |= VAPPEND; 4058 #ifdef MAC 4059 error = mac_check_vnode_open(td->td_ucred, vp, mode); 4060 if (error) 4061 goto bad; 4062 #endif 4063 if (mode) { 4064 error = VOP_ACCESS(vp, mode, td->td_ucred, td); 4065 if (error) 4066 goto bad; 4067 } 4068 if (fmode & O_TRUNC) { 4069 VOP_UNLOCK(vp, 0, td); /* XXX */ 4070 if ((error = vn_start_write(NULL, &mp, V_WAIT | PCATCH)) != 0) { 4071 vrele(vp); 4072 goto out; 4073 } 4074 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); 4075 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); /* XXX */ 4076 #ifdef MAC 4077 /* 4078 * We don't yet have fp->f_cred, so use td->td_ucred, which 4079 * should be right. 4080 */ 4081 error = mac_check_vnode_write(td->td_ucred, td->td_ucred, vp); 4082 if (error == 0) { 4083 #endif 4084 VATTR_NULL(vap); 4085 vap->va_size = 0; 4086 error = VOP_SETATTR(vp, vap, td->td_ucred, td); 4087 #ifdef MAC 4088 } 4089 #endif 4090 vn_finished_write(mp); 4091 if (error) 4092 goto bad; 4093 } 4094 error = VOP_OPEN(vp, fmode, td->td_ucred, td, -1); 4095 if (error) 4096 goto bad; 4097 4098 if (fmode & FWRITE) 4099 vp->v_writecount++; 4100 4101 /* 4102 * end of vn_open code 4103 */ 4104 4105 if ((error = falloc(td, &nfp, &indx)) != 0) { 4106 if (fmode & FWRITE) 4107 vp->v_writecount--; 4108 goto bad; 4109 } 4110 /* An extra reference on `nfp' has been held for us by falloc(). */ 4111 fp = nfp; 4112 4113 FILE_LOCK(nfp); 4114 nfp->f_vnode = vp; 4115 nfp->f_data = vp; 4116 nfp->f_flag = fmode & FMASK; 4117 nfp->f_type = DTYPE_VNODE; 4118 nfp->f_ops = &vnops; 4119 FILE_UNLOCK(nfp); 4120 if (fmode & (O_EXLOCK | O_SHLOCK)) { 4121 lf.l_whence = SEEK_SET; 4122 lf.l_start = 0; 4123 lf.l_len = 0; 4124 if (fmode & O_EXLOCK) 4125 lf.l_type = F_WRLCK; 4126 else 4127 lf.l_type = F_RDLCK; 4128 type = F_FLOCK; 4129 if ((fmode & FNONBLOCK) == 0) 4130 type |= F_WAIT; 4131 VOP_UNLOCK(vp, 0, td); 4132 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, 4133 type)) != 0) { 4134 /* 4135 * The lock request failed. Normally close the 4136 * descriptor but handle the case where someone might 4137 * have dup()d or close()d it when we weren't looking. 4138 */ 4139 fdclose(fdp, fp, indx, td); 4140 4141 /* 4142 * release our private reference 4143 */ 4144 fdrop(fp, td); 4145 goto out; 4146 } 4147 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 4148 fp->f_flag |= FHASLOCK; 4149 } 4150 4151 VOP_UNLOCK(vp, 0, td); 4152 fdrop(fp, td); 4153 vfs_rel(mp); 4154 VFS_UNLOCK_GIANT(vfslocked); 4155 td->td_retval[0] = indx; 4156 return (0); 4157 4158 bad: 4159 vput(vp); 4160 out: 4161 vfs_rel(mp); 4162 VFS_UNLOCK_GIANT(vfslocked); 4163 return (error); 4164 } 4165 4166 /* 4167 * Stat an (NFS) file handle. 4168 */ 4169 #ifndef _SYS_SYSPROTO_H_ 4170 struct fhstat_args { 4171 struct fhandle *u_fhp; 4172 struct stat *sb; 4173 }; 4174 #endif 4175 int 4176 fhstat(td, uap) 4177 struct thread *td; 4178 register struct fhstat_args /* { 4179 struct fhandle *u_fhp; 4180 struct stat *sb; 4181 } */ *uap; 4182 { 4183 struct stat sb; 4184 fhandle_t fh; 4185 struct mount *mp; 4186 struct vnode *vp; 4187 int vfslocked; 4188 int error; 4189 4190 error = priv_check(td, PRIV_VFS_FHSTAT); 4191 if (error) 4192 return (error); 4193 error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t)); 4194 if (error) 4195 return (error); 4196 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) 4197 return (ESTALE); 4198 vfslocked = VFS_LOCK_GIANT(mp); 4199 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp))) { 4200 vfs_rel(mp); 4201 VFS_UNLOCK_GIANT(vfslocked); 4202 return (error); 4203 } 4204 error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td); 4205 vput(vp); 4206 vfs_rel(mp); 4207 VFS_UNLOCK_GIANT(vfslocked); 4208 if (error) 4209 return (error); 4210 error = copyout(&sb, uap->sb, sizeof(sb)); 4211 return (error); 4212 } 4213 4214 /* 4215 * Implement fstatfs() for (NFS) file handles. 4216 */ 4217 #ifndef _SYS_SYSPROTO_H_ 4218 struct fhstatfs_args { 4219 struct fhandle *u_fhp; 4220 struct statfs *buf; 4221 }; 4222 #endif 4223 int 4224 fhstatfs(td, uap) 4225 struct thread *td; 4226 struct fhstatfs_args /* { 4227 struct fhandle *u_fhp; 4228 struct statfs *buf; 4229 } */ *uap; 4230 { 4231 struct statfs sf; 4232 fhandle_t fh; 4233 int error; 4234 4235 error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t)); 4236 if (error) 4237 return (error); 4238 error = kern_fhstatfs(td, fh, &sf); 4239 if (error) 4240 return (error); 4241 return (copyout(&sf, uap->buf, sizeof(sf))); 4242 } 4243 4244 int 4245 kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf) 4246 { 4247 struct statfs *sp; 4248 struct mount *mp; 4249 struct vnode *vp; 4250 int vfslocked; 4251 int error; 4252 4253 error = priv_check(td, PRIV_VFS_FHSTATFS); 4254 if (error) 4255 return (error); 4256 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) 4257 return (ESTALE); 4258 vfslocked = VFS_LOCK_GIANT(mp); 4259 error = VFS_FHTOVP(mp, &fh.fh_fid, &vp); 4260 if (error) { 4261 VFS_UNLOCK_GIANT(vfslocked); 4262 vfs_rel(mp); 4263 return (error); 4264 } 4265 vput(vp); 4266 error = prison_canseemount(td->td_ucred, mp); 4267 if (error) 4268 goto out; 4269 #ifdef MAC 4270 error = mac_check_mount_stat(td->td_ucred, mp); 4271 if (error) 4272 goto out; 4273 #endif 4274 /* 4275 * Set these in case the underlying filesystem fails to do so. 4276 */ 4277 sp = &mp->mnt_stat; 4278 sp->f_version = STATFS_VERSION; 4279 sp->f_namemax = NAME_MAX; 4280 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 4281 error = VFS_STATFS(mp, sp, td); 4282 if (error == 0) 4283 *buf = *sp; 4284 out: 4285 vfs_rel(mp); 4286 VFS_UNLOCK_GIANT(vfslocked); 4287 return (error); 4288 } 4289