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

Cache object: 287da548ae004b4ca59e1009f78014cb


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