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