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