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

Cache object: a2467b65627aa6b8baf4dd0ca9c67cdd


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