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