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