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