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