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