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