The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/vfs_syscalls.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: b0e4a20c130f6282a04219ec23bd143e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.