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