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