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