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_extattr.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) 1999-2001 Robert N. M. Watson
    3  * All rights reserved.
    4  *
    5  * This software was developed by Robert Watson for the TrustedBSD Project.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD: releng/8.2/sys/kern/vfs_extattr.c 199583 2009-11-20 15:27:52Z jhb $");
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/lock.h>
   35 #include <sys/mount.h>
   36 #include <sys/mutex.h>
   37 #include <sys/sysproto.h>
   38 #include <sys/fcntl.h>
   39 #include <sys/namei.h>
   40 #include <sys/filedesc.h>
   41 #include <sys/limits.h>
   42 #include <sys/vnode.h>
   43 #include <sys/proc.h>
   44 #include <sys/extattr.h>
   45 
   46 #include <security/audit/audit.h>
   47 #include <security/mac/mac_framework.h>
   48 
   49 /*
   50  * Syscall to push extended attribute configuration information into the VFS.
   51  * Accepts a path, which it converts to a mountpoint, as well as a command
   52  * (int cmd), and attribute name and misc data.
   53  *
   54  * Currently this is used only by UFS1 extended attributes.
   55  */
   56 int
   57 extattrctl(td, uap)
   58         struct thread *td;
   59         struct extattrctl_args /* {
   60                 const char *path;
   61                 int cmd;
   62                 const char *filename;
   63                 int attrnamespace;
   64                 const char *attrname;
   65         } */ *uap;
   66 {
   67         struct vnode *filename_vp;
   68         struct nameidata nd;
   69         struct mount *mp, *mp_writable;
   70         char attrname[EXTATTR_MAXNAMELEN];
   71         int vfslocked, fnvfslocked, error;
   72 
   73         AUDIT_ARG_CMD(uap->cmd);
   74         AUDIT_ARG_VALUE(uap->attrnamespace);
   75         /*
   76          * uap->attrname is not always defined.  We check again later when we
   77          * invoke the VFS call so as to pass in NULL there if needed.
   78          */
   79         if (uap->attrname != NULL) {
   80                 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN,
   81                     NULL);
   82                 if (error)
   83                         return (error);
   84         }
   85         AUDIT_ARG_TEXT(attrname);
   86 
   87         vfslocked = fnvfslocked = 0;
   88         mp = NULL;
   89         filename_vp = NULL;
   90         if (uap->filename != NULL) {
   91                 NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE2,
   92                     UIO_USERSPACE, uap->filename, td);
   93                 error = namei(&nd);
   94                 if (error)
   95                         return (error);
   96                 fnvfslocked = NDHASGIANT(&nd);
   97                 filename_vp = nd.ni_vp;
   98                 NDFREE(&nd, NDF_NO_VP_RELE);
   99         }
  100 
  101         /* uap->path is always defined. */
  102         NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | LOCKLEAF | AUDITVNODE1,
  103             UIO_USERSPACE, uap->path, td);
  104         error = namei(&nd);
  105         if (error)
  106                 goto out;
  107         vfslocked = NDHASGIANT(&nd);
  108         mp = nd.ni_vp->v_mount;
  109         error = vfs_busy(mp, 0);
  110         if (error) {
  111                 NDFREE(&nd, 0);
  112                 mp = NULL;
  113                 goto out;
  114         }
  115         VOP_UNLOCK(nd.ni_vp, 0);
  116         error = vn_start_write(nd.ni_vp, &mp_writable, V_WAIT | PCATCH);
  117         NDFREE(&nd, NDF_NO_VP_UNLOCK);
  118         if (error)
  119                 goto out;
  120         if (filename_vp != NULL) {
  121                 /*
  122                  * uap->filename is not always defined.  If it is,
  123                  * grab a vnode lock, which VFS_EXTATTRCTL() will
  124                  * later release.
  125                  */
  126                 error = vn_lock(filename_vp, LK_EXCLUSIVE);
  127                 if (error) {
  128                         vn_finished_write(mp_writable);
  129                         goto out;
  130                 }
  131         }
  132 
  133         error = VFS_EXTATTRCTL(mp, uap->cmd, filename_vp, uap->attrnamespace,
  134             uap->attrname != NULL ? attrname : NULL);
  135 
  136         vn_finished_write(mp_writable);
  137 out:
  138         if (mp != NULL)
  139                 vfs_unbusy(mp);
  140 
  141         /*
  142          * VFS_EXTATTRCTL will have unlocked, but not de-ref'd, filename_vp,
  143          * so vrele it if it is defined.
  144          */
  145         if (filename_vp != NULL)
  146                 vrele(filename_vp);
  147         VFS_UNLOCK_GIANT(fnvfslocked);
  148         VFS_UNLOCK_GIANT(vfslocked);
  149         return (error);
  150 }
  151 
  152 /*-
  153  * Set a named extended attribute on a file or directory
  154  *
  155  * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
  156  *            kernelspace string pointer "attrname", userspace buffer
  157  *            pointer "data", buffer length "nbytes", thread "td".
  158  * Returns: 0 on success, an error number otherwise
  159  * Locks: none
  160  * References: vp must be a valid reference for the duration of the call
  161  */
  162 static int
  163 extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname,
  164     void *data, size_t nbytes, struct thread *td)
  165 {
  166         struct mount *mp;
  167         struct uio auio;
  168         struct iovec aiov;
  169         ssize_t cnt;
  170         int error;
  171 
  172         VFS_ASSERT_GIANT(vp->v_mount);
  173         error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
  174         if (error)
  175                 return (error);
  176         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
  177 
  178         aiov.iov_base = data;
  179         aiov.iov_len = nbytes;
  180         auio.uio_iov = &aiov;
  181         auio.uio_iovcnt = 1;
  182         auio.uio_offset = 0;
  183         if (nbytes > INT_MAX) {
  184                 error = EINVAL;
  185                 goto done;
  186         }
  187         auio.uio_resid = nbytes;
  188         auio.uio_rw = UIO_WRITE;
  189         auio.uio_segflg = UIO_USERSPACE;
  190         auio.uio_td = td;
  191         cnt = nbytes;
  192 
  193 #ifdef MAC
  194         error = mac_vnode_check_setextattr(td->td_ucred, vp, attrnamespace,
  195             attrname);
  196         if (error)
  197                 goto done;
  198 #endif
  199 
  200         error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio,
  201             td->td_ucred, td);
  202         cnt -= auio.uio_resid;
  203         td->td_retval[0] = cnt;
  204 
  205 done:
  206         VOP_UNLOCK(vp, 0);
  207         vn_finished_write(mp);
  208         return (error);
  209 }
  210 
  211 int
  212 extattr_set_fd(td, uap)
  213         struct thread *td;
  214         struct extattr_set_fd_args /* {
  215                 int fd;
  216                 int attrnamespace;
  217                 const char *attrname;
  218                 void *data;
  219                 size_t nbytes;
  220         } */ *uap;
  221 {
  222         struct file *fp;
  223         char attrname[EXTATTR_MAXNAMELEN];
  224         int vfslocked, error;
  225 
  226         AUDIT_ARG_FD(uap->fd);
  227         AUDIT_ARG_VALUE(uap->attrnamespace);
  228         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
  229         if (error)
  230                 return (error);
  231         AUDIT_ARG_TEXT(attrname);
  232 
  233         error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
  234         if (error)
  235                 return (error);
  236 
  237         vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
  238         error = extattr_set_vp(fp->f_vnode, uap->attrnamespace,
  239             attrname, uap->data, uap->nbytes, td);
  240         fdrop(fp, td);
  241         VFS_UNLOCK_GIANT(vfslocked);
  242 
  243         return (error);
  244 }
  245 
  246 int
  247 extattr_set_file(td, uap)
  248         struct thread *td;
  249         struct extattr_set_file_args /* {
  250                 const char *path;
  251                 int attrnamespace;
  252                 const char *attrname;
  253                 void *data;
  254                 size_t nbytes;
  255         } */ *uap;
  256 {
  257         struct nameidata nd;
  258         char attrname[EXTATTR_MAXNAMELEN];
  259         int vfslocked, error;
  260 
  261         AUDIT_ARG_VALUE(uap->attrnamespace);
  262         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
  263         if (error)
  264                 return (error);
  265         AUDIT_ARG_TEXT(attrname);
  266 
  267         NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE1, UIO_USERSPACE,
  268             uap->path, td);
  269         error = namei(&nd);
  270         if (error)
  271                 return (error);
  272         NDFREE(&nd, NDF_ONLY_PNBUF);
  273 
  274         vfslocked = NDHASGIANT(&nd);
  275         error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname,
  276             uap->data, uap->nbytes, td);
  277 
  278         vrele(nd.ni_vp);
  279         VFS_UNLOCK_GIANT(vfslocked);
  280         return (error);
  281 }
  282 
  283 int
  284 extattr_set_link(td, uap)
  285         struct thread *td;
  286         struct extattr_set_link_args /* {
  287                 const char *path;
  288                 int attrnamespace;
  289                 const char *attrname;
  290                 void *data;
  291                 size_t nbytes;
  292         } */ *uap;
  293 {
  294         struct nameidata nd;
  295         char attrname[EXTATTR_MAXNAMELEN];
  296         int vfslocked, error;
  297 
  298         AUDIT_ARG_VALUE(uap->attrnamespace);
  299         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
  300         if (error)
  301                 return (error);
  302         AUDIT_ARG_TEXT(attrname);
  303 
  304         NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW | AUDITVNODE1, UIO_USERSPACE,
  305             uap->path, td);
  306         error = namei(&nd);
  307         if (error)
  308                 return (error);
  309         NDFREE(&nd, NDF_ONLY_PNBUF);
  310 
  311         vfslocked = NDHASGIANT(&nd);
  312         error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname,
  313             uap->data, uap->nbytes, td);
  314 
  315         vrele(nd.ni_vp);
  316         VFS_UNLOCK_GIANT(vfslocked);
  317         return (error);
  318 }
  319 
  320 /*-
  321  * Get a named extended attribute on a file or directory
  322  *
  323  * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
  324  *            kernelspace string pointer "attrname", userspace buffer
  325  *            pointer "data", buffer length "nbytes", thread "td".
  326  * Returns: 0 on success, an error number otherwise
  327  * Locks: none
  328  * References: vp must be a valid reference for the duration of the call
  329  */
  330 static int
  331 extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname,
  332     void *data, size_t nbytes, struct thread *td)
  333 {
  334         struct uio auio, *auiop;
  335         struct iovec aiov;
  336         ssize_t cnt;
  337         size_t size, *sizep;
  338         int error;
  339 
  340         VFS_ASSERT_GIANT(vp->v_mount);
  341         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
  342 
  343         /*
  344          * Slightly unusual semantics: if the user provides a NULL data
  345          * pointer, they don't want to receive the data, just the maximum
  346          * read length.
  347          */
  348         auiop = NULL;
  349         sizep = NULL;
  350         cnt = 0;
  351         if (data != NULL) {
  352                 aiov.iov_base = data;
  353                 aiov.iov_len = nbytes;
  354                 auio.uio_iov = &aiov;
  355                 auio.uio_iovcnt = 1;
  356                 auio.uio_offset = 0;
  357                 if (nbytes > INT_MAX) {
  358                         error = EINVAL;
  359                         goto done;
  360                 }
  361                 auio.uio_resid = nbytes;
  362                 auio.uio_rw = UIO_READ;
  363                 auio.uio_segflg = UIO_USERSPACE;
  364                 auio.uio_td = td;
  365                 auiop = &auio;
  366                 cnt = nbytes;
  367         } else
  368                 sizep = &size;
  369 
  370 #ifdef MAC
  371         error = mac_vnode_check_getextattr(td->td_ucred, vp, attrnamespace,
  372             attrname);
  373         if (error)
  374                 goto done;
  375 #endif
  376 
  377         error = VOP_GETEXTATTR(vp, attrnamespace, attrname, auiop, sizep,
  378             td->td_ucred, td);
  379 
  380         if (auiop != NULL) {
  381                 cnt -= auio.uio_resid;
  382                 td->td_retval[0] = cnt;
  383         } else
  384                 td->td_retval[0] = size;
  385 
  386 done:
  387         VOP_UNLOCK(vp, 0);
  388         return (error);
  389 }
  390 
  391 int
  392 extattr_get_fd(td, uap)
  393         struct thread *td;
  394         struct extattr_get_fd_args /* {
  395                 int fd;
  396                 int attrnamespace;
  397                 const char *attrname;
  398                 void *data;
  399                 size_t nbytes;
  400         } */ *uap;
  401 {
  402         struct file *fp;
  403         char attrname[EXTATTR_MAXNAMELEN];
  404         int vfslocked, error;
  405 
  406         AUDIT_ARG_FD(uap->fd);
  407         AUDIT_ARG_VALUE(uap->attrnamespace);
  408         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
  409         if (error)
  410                 return (error);
  411         AUDIT_ARG_TEXT(attrname);
  412 
  413         error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
  414         if (error)
  415                 return (error);
  416 
  417         vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
  418         error = extattr_get_vp(fp->f_vnode, uap->attrnamespace,
  419             attrname, uap->data, uap->nbytes, td);
  420 
  421         fdrop(fp, td);
  422         VFS_UNLOCK_GIANT(vfslocked);
  423         return (error);
  424 }
  425 
  426 int
  427 extattr_get_file(td, uap)
  428         struct thread *td;
  429         struct extattr_get_file_args /* {
  430                 const char *path;
  431                 int attrnamespace;
  432                 const char *attrname;
  433                 void *data;
  434                 size_t nbytes;
  435         } */ *uap;
  436 {
  437         struct nameidata nd;
  438         char attrname[EXTATTR_MAXNAMELEN];
  439         int vfslocked, error;
  440 
  441         AUDIT_ARG_VALUE(uap->attrnamespace);
  442         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
  443         if (error)
  444                 return (error);
  445         AUDIT_ARG_TEXT(attrname);
  446 
  447         NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE1, UIO_USERSPACE,
  448             uap->path, td);
  449         error = namei(&nd);
  450         if (error)
  451                 return (error);
  452         NDFREE(&nd, NDF_ONLY_PNBUF);
  453 
  454         vfslocked = NDHASGIANT(&nd);
  455         error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname,
  456             uap->data, uap->nbytes, td);
  457 
  458         vrele(nd.ni_vp);
  459         VFS_UNLOCK_GIANT(vfslocked);
  460         return (error);
  461 }
  462 
  463 int
  464 extattr_get_link(td, uap)
  465         struct thread *td;
  466         struct extattr_get_link_args /* {
  467                 const char *path;
  468                 int attrnamespace;
  469                 const char *attrname;
  470                 void *data;
  471                 size_t nbytes;
  472         } */ *uap;
  473 {
  474         struct nameidata nd;
  475         char attrname[EXTATTR_MAXNAMELEN];
  476         int vfslocked, error;
  477 
  478         AUDIT_ARG_VALUE(uap->attrnamespace);
  479         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
  480         if (error)
  481                 return (error);
  482         AUDIT_ARG_TEXT(attrname);
  483 
  484         NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW | AUDITVNODE1, UIO_USERSPACE,
  485             uap->path, td);
  486         error = namei(&nd);
  487         if (error)
  488                 return (error);
  489         NDFREE(&nd, NDF_ONLY_PNBUF);
  490 
  491         vfslocked = NDHASGIANT(&nd);
  492         error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname,
  493             uap->data, uap->nbytes, td);
  494 
  495         vrele(nd.ni_vp);
  496         VFS_UNLOCK_GIANT(vfslocked);
  497         return (error);
  498 }
  499 
  500 /*
  501  * extattr_delete_vp(): Delete a named extended attribute on a file or
  502  *                      directory
  503  *
  504  * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
  505  *            kernelspace string pointer "attrname", proc "p"
  506  * Returns: 0 on success, an error number otherwise
  507  * Locks: none
  508  * References: vp must be a valid reference for the duration of the call
  509  */
  510 static int
  511 extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname,
  512     struct thread *td)
  513 {
  514         struct mount *mp;
  515         int error;
  516 
  517         VFS_ASSERT_GIANT(vp->v_mount);
  518         error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
  519         if (error)
  520                 return (error);
  521         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
  522 
  523 #ifdef MAC
  524         error = mac_vnode_check_deleteextattr(td->td_ucred, vp, attrnamespace,
  525             attrname);
  526         if (error)
  527                 goto done;
  528 #endif
  529 
  530         error = VOP_DELETEEXTATTR(vp, attrnamespace, attrname, td->td_ucred,
  531             td);
  532         if (error == EOPNOTSUPP)
  533                 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL,
  534                     td->td_ucred, td);
  535 #ifdef MAC
  536 done:
  537 #endif
  538         VOP_UNLOCK(vp, 0);
  539         vn_finished_write(mp);
  540         return (error);
  541 }
  542 
  543 int
  544 extattr_delete_fd(td, uap)
  545         struct thread *td;
  546         struct extattr_delete_fd_args /* {
  547                 int fd;
  548                 int attrnamespace;
  549                 const char *attrname;
  550         } */ *uap;
  551 {
  552         struct file *fp;
  553         char attrname[EXTATTR_MAXNAMELEN];
  554         int vfslocked, error;
  555 
  556         AUDIT_ARG_FD(uap->fd);
  557         AUDIT_ARG_VALUE(uap->attrnamespace);
  558         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
  559         if (error)
  560                 return (error);
  561         AUDIT_ARG_TEXT(attrname);
  562 
  563         error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
  564         if (error)
  565                 return (error);
  566 
  567         vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
  568         error = extattr_delete_vp(fp->f_vnode, uap->attrnamespace,
  569             attrname, td);
  570         fdrop(fp, td);
  571         VFS_UNLOCK_GIANT(vfslocked);
  572         return (error);
  573 }
  574 
  575 int
  576 extattr_delete_file(td, uap)
  577         struct thread *td;
  578         struct extattr_delete_file_args /* {
  579                 const char *path;
  580                 int attrnamespace;
  581                 const char *attrname;
  582         } */ *uap;
  583 {
  584         struct nameidata nd;
  585         char attrname[EXTATTR_MAXNAMELEN];
  586         int vfslocked, error;
  587 
  588         AUDIT_ARG_VALUE(uap->attrnamespace);
  589         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
  590         if (error)
  591                 return(error);
  592         AUDIT_ARG_TEXT(attrname);
  593 
  594         NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE1, UIO_USERSPACE,
  595             uap->path, td);
  596         error = namei(&nd);
  597         if (error)
  598                 return(error);
  599         NDFREE(&nd, NDF_ONLY_PNBUF);
  600 
  601         vfslocked = NDHASGIANT(&nd);
  602         error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td);
  603         vrele(nd.ni_vp);
  604         VFS_UNLOCK_GIANT(vfslocked);
  605         return(error);
  606 }
  607 
  608 int
  609 extattr_delete_link(td, uap)
  610         struct thread *td;
  611         struct extattr_delete_link_args /* {
  612                 const char *path;
  613                 int attrnamespace;
  614                 const char *attrname;
  615         } */ *uap;
  616 {
  617         struct nameidata nd;
  618         char attrname[EXTATTR_MAXNAMELEN];
  619         int vfslocked, error;
  620 
  621         AUDIT_ARG_VALUE(uap->attrnamespace);
  622         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
  623         if (error)
  624                 return(error);
  625         AUDIT_ARG_TEXT(attrname);
  626 
  627         NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW | AUDITVNODE1, UIO_USERSPACE,
  628             uap->path, td);
  629         error = namei(&nd);
  630         if (error)
  631                 return(error);
  632         NDFREE(&nd, NDF_ONLY_PNBUF);
  633 
  634         vfslocked = NDHASGIANT(&nd);
  635         error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td);
  636         vrele(nd.ni_vp);
  637         VFS_UNLOCK_GIANT(vfslocked);
  638         return(error);
  639 }
  640 
  641 /*-
  642  * Retrieve a list of extended attributes on a file or directory.
  643  *
  644  * Arguments: unlocked vnode "vp", attribute namespace 'attrnamespace",
  645  *            userspace buffer pointer "data", buffer length "nbytes",
  646  *            thread "td".
  647  * Returns: 0 on success, an error number otherwise
  648  * Locks: none
  649  * References: vp must be a valid reference for the duration of the call
  650  */
  651 static int
  652 extattr_list_vp(struct vnode *vp, int attrnamespace, void *data,
  653     size_t nbytes, struct thread *td)
  654 {
  655         struct uio auio, *auiop;
  656         size_t size, *sizep;
  657         struct iovec aiov;
  658         ssize_t cnt;
  659         int error;
  660 
  661         VFS_ASSERT_GIANT(vp->v_mount);
  662         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
  663 
  664         auiop = NULL;
  665         sizep = NULL;
  666         cnt = 0;
  667         if (data != NULL) {
  668                 aiov.iov_base = data;
  669                 aiov.iov_len = nbytes;
  670                 auio.uio_iov = &aiov;
  671                 auio.uio_iovcnt = 1;
  672                 auio.uio_offset = 0;
  673                 if (nbytes > INT_MAX) {
  674                         error = EINVAL;
  675                         goto done;
  676                 }
  677                 auio.uio_resid = nbytes;
  678                 auio.uio_rw = UIO_READ;
  679                 auio.uio_segflg = UIO_USERSPACE;
  680                 auio.uio_td = td;
  681                 auiop = &auio;
  682                 cnt = nbytes;
  683         } else
  684                 sizep = &size;
  685 
  686 #ifdef MAC
  687         error = mac_vnode_check_listextattr(td->td_ucred, vp, attrnamespace);
  688         if (error)
  689                 goto done;
  690 #endif
  691 
  692         error = VOP_LISTEXTATTR(vp, attrnamespace, auiop, sizep,
  693             td->td_ucred, td);
  694 
  695         if (auiop != NULL) {
  696                 cnt -= auio.uio_resid;
  697                 td->td_retval[0] = cnt;
  698         } else
  699                 td->td_retval[0] = size;
  700 
  701 done:
  702         VOP_UNLOCK(vp, 0);
  703         return (error);
  704 }
  705 
  706 
  707 int
  708 extattr_list_fd(td, uap)
  709         struct thread *td;
  710         struct extattr_list_fd_args /* {
  711                 int fd;
  712                 int attrnamespace;
  713                 void *data;
  714                 size_t nbytes;
  715         } */ *uap;
  716 {
  717         struct file *fp;
  718         int vfslocked, error;
  719 
  720         AUDIT_ARG_FD(uap->fd);
  721         AUDIT_ARG_VALUE(uap->attrnamespace);
  722         error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
  723         if (error)
  724                 return (error);
  725 
  726         vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
  727         error = extattr_list_vp(fp->f_vnode, uap->attrnamespace, uap->data,
  728             uap->nbytes, td);
  729 
  730         fdrop(fp, td);
  731         VFS_UNLOCK_GIANT(vfslocked);
  732         return (error);
  733 }
  734 
  735 int
  736 extattr_list_file(td, uap)
  737         struct thread*td;
  738         struct extattr_list_file_args /* {
  739                 const char *path;
  740                 int attrnamespace;
  741                 void *data;
  742                 size_t nbytes;
  743         } */ *uap;
  744 {
  745         struct nameidata nd;
  746         int vfslocked, error;
  747 
  748         AUDIT_ARG_VALUE(uap->attrnamespace);
  749         NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE1, UIO_USERSPACE,
  750             uap->path, td);
  751         error = namei(&nd);
  752         if (error)
  753                 return (error);
  754         NDFREE(&nd, NDF_ONLY_PNBUF);
  755 
  756         vfslocked = NDHASGIANT(&nd);
  757         error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data,
  758             uap->nbytes, td);
  759 
  760         vrele(nd.ni_vp);
  761         VFS_UNLOCK_GIANT(vfslocked);
  762         return (error);
  763 }
  764 
  765 int
  766 extattr_list_link(td, uap)
  767         struct thread*td;
  768         struct extattr_list_link_args /* {
  769                 const char *path;
  770                 int attrnamespace;
  771                 void *data;
  772                 size_t nbytes;
  773         } */ *uap;
  774 {
  775         struct nameidata nd;
  776         int vfslocked, error;
  777 
  778         AUDIT_ARG_VALUE(uap->attrnamespace);
  779         NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW | AUDITVNODE1, UIO_USERSPACE,
  780             uap->path, td);
  781         error = namei(&nd);
  782         if (error)
  783                 return (error);
  784         NDFREE(&nd, NDF_ONLY_PNBUF);
  785 
  786         vfslocked = NDHASGIANT(&nd);
  787         error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data,
  788             uap->nbytes, td);
  789 
  790         vrele(nd.ni_vp);
  791         VFS_UNLOCK_GIANT(vfslocked);
  792         return (error);
  793 }

Cache object: 498a70c6fd0bbba5c9898bd85cd194a4


[ 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.