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