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/11.0/sys/kern/vfs_extattr.c 284446 2015-06-16 13:09:18Z mjg $");
   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         error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
  169         if (error)
  170                 return (error);
  171         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
  172 
  173         aiov.iov_base = data;
  174         aiov.iov_len = nbytes;
  175         auio.uio_iov = &aiov;
  176         auio.uio_iovcnt = 1;
  177         auio.uio_offset = 0;
  178         if (nbytes > IOSIZE_MAX) {
  179                 error = EINVAL;
  180                 goto done;
  181         }
  182         auio.uio_resid = nbytes;
  183         auio.uio_rw = UIO_WRITE;
  184         auio.uio_segflg = UIO_USERSPACE;
  185         auio.uio_td = td;
  186         cnt = nbytes;
  187 
  188 #ifdef MAC
  189         error = mac_vnode_check_setextattr(td->td_ucred, vp, attrnamespace,
  190             attrname);
  191         if (error)
  192                 goto done;
  193 #endif
  194 
  195         error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio,
  196             td->td_ucred, td);
  197         cnt -= auio.uio_resid;
  198         td->td_retval[0] = cnt;
  199 
  200 done:
  201         VOP_UNLOCK(vp, 0);
  202         vn_finished_write(mp);
  203         return (error);
  204 }
  205 
  206 int
  207 sys_extattr_set_fd(td, uap)
  208         struct thread *td;
  209         struct extattr_set_fd_args /* {
  210                 int fd;
  211                 int attrnamespace;
  212                 const char *attrname;
  213                 void *data;
  214                 size_t nbytes;
  215         } */ *uap;
  216 {
  217         struct file *fp;
  218         char attrname[EXTATTR_MAXNAMELEN];
  219         cap_rights_t rights;
  220         int error;
  221 
  222         AUDIT_ARG_FD(uap->fd);
  223         AUDIT_ARG_VALUE(uap->attrnamespace);
  224         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
  225         if (error)
  226                 return (error);
  227         AUDIT_ARG_TEXT(attrname);
  228 
  229         error = getvnode(td, uap->fd,
  230             cap_rights_init(&rights, CAP_EXTATTR_SET), &fp);
  231         if (error)
  232                 return (error);
  233 
  234         error = extattr_set_vp(fp->f_vnode, uap->attrnamespace,
  235             attrname, uap->data, uap->nbytes, td);
  236         fdrop(fp, td);
  237 
  238         return (error);
  239 }
  240 
  241 int
  242 sys_extattr_set_file(td, uap)
  243         struct thread *td;
  244         struct extattr_set_file_args /* {
  245                 const char *path;
  246                 int attrnamespace;
  247                 const char *attrname;
  248                 void *data;
  249                 size_t nbytes;
  250         } */ *uap;
  251 {
  252         struct nameidata nd;
  253         char attrname[EXTATTR_MAXNAMELEN];
  254         int error;
  255 
  256         AUDIT_ARG_VALUE(uap->attrnamespace);
  257         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
  258         if (error)
  259                 return (error);
  260         AUDIT_ARG_TEXT(attrname);
  261 
  262         NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, UIO_USERSPACE,
  263             uap->path, td);
  264         error = namei(&nd);
  265         if (error)
  266                 return (error);
  267         NDFREE(&nd, NDF_ONLY_PNBUF);
  268 
  269         error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname,
  270             uap->data, uap->nbytes, td);
  271 
  272         vrele(nd.ni_vp);
  273         return (error);
  274 }
  275 
  276 int
  277 sys_extattr_set_link(td, uap)
  278         struct thread *td;
  279         struct extattr_set_link_args /* {
  280                 const char *path;
  281                 int attrnamespace;
  282                 const char *attrname;
  283                 void *data;
  284                 size_t nbytes;
  285         } */ *uap;
  286 {
  287         struct nameidata nd;
  288         char attrname[EXTATTR_MAXNAMELEN];
  289         int error;
  290 
  291         AUDIT_ARG_VALUE(uap->attrnamespace);
  292         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
  293         if (error)
  294                 return (error);
  295         AUDIT_ARG_TEXT(attrname);
  296 
  297         NDINIT(&nd, LOOKUP, NOFOLLOW | AUDITVNODE1, UIO_USERSPACE,
  298             uap->path, td);
  299         error = namei(&nd);
  300         if (error)
  301                 return (error);
  302         NDFREE(&nd, NDF_ONLY_PNBUF);
  303 
  304         error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname,
  305             uap->data, uap->nbytes, td);
  306 
  307         vrele(nd.ni_vp);
  308         return (error);
  309 }
  310 
  311 /*-
  312  * Get a named extended attribute on a file or directory
  313  *
  314  * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
  315  *            kernelspace string pointer "attrname", userspace buffer
  316  *            pointer "data", buffer length "nbytes", thread "td".
  317  * Returns: 0 on success, an error number otherwise
  318  * Locks: none
  319  * References: vp must be a valid reference for the duration of the call
  320  */
  321 static int
  322 extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname,
  323     void *data, size_t nbytes, struct thread *td)
  324 {
  325         struct uio auio, *auiop;
  326         struct iovec aiov;
  327         ssize_t cnt;
  328         size_t size, *sizep;
  329         int error;
  330 
  331         vn_lock(vp, LK_SHARED | LK_RETRY);
  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 > IOSIZE_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_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 
  376 done:
  377         VOP_UNLOCK(vp, 0);
  378         return (error);
  379 }
  380 
  381 int
  382 sys_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         cap_rights_t rights;
  395         int error;
  396 
  397         AUDIT_ARG_FD(uap->fd);
  398         AUDIT_ARG_VALUE(uap->attrnamespace);
  399         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
  400         if (error)
  401                 return (error);
  402         AUDIT_ARG_TEXT(attrname);
  403 
  404         error = getvnode(td, uap->fd,
  405             cap_rights_init(&rights, CAP_EXTATTR_GET), &fp);
  406         if (error)
  407                 return (error);
  408 
  409         error = extattr_get_vp(fp->f_vnode, uap->attrnamespace,
  410             attrname, uap->data, uap->nbytes, td);
  411 
  412         fdrop(fp, td);
  413         return (error);
  414 }
  415 
  416 int
  417 sys_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 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, FOLLOW | AUDITVNODE1, UIO_USERSPACE, uap->path, td);
  438         error = namei(&nd);
  439         if (error)
  440                 return (error);
  441         NDFREE(&nd, NDF_ONLY_PNBUF);
  442 
  443         error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname,
  444             uap->data, uap->nbytes, td);
  445 
  446         vrele(nd.ni_vp);
  447         return (error);
  448 }
  449 
  450 int
  451 sys_extattr_get_link(td, uap)
  452         struct thread *td;
  453         struct extattr_get_link_args /* {
  454                 const char *path;
  455                 int attrnamespace;
  456                 const char *attrname;
  457                 void *data;
  458                 size_t nbytes;
  459         } */ *uap;
  460 {
  461         struct nameidata nd;
  462         char attrname[EXTATTR_MAXNAMELEN];
  463         int error;
  464 
  465         AUDIT_ARG_VALUE(uap->attrnamespace);
  466         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
  467         if (error)
  468                 return (error);
  469         AUDIT_ARG_TEXT(attrname);
  470 
  471         NDINIT(&nd, LOOKUP, NOFOLLOW | AUDITVNODE1, UIO_USERSPACE, uap->path,
  472             td);
  473         error = namei(&nd);
  474         if (error)
  475                 return (error);
  476         NDFREE(&nd, NDF_ONLY_PNBUF);
  477 
  478         error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname,
  479             uap->data, uap->nbytes, td);
  480 
  481         vrele(nd.ni_vp);
  482         return (error);
  483 }
  484 
  485 /*
  486  * extattr_delete_vp(): Delete a named extended attribute on a file or
  487  *                      directory
  488  *
  489  * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
  490  *            kernelspace string pointer "attrname", proc "p"
  491  * Returns: 0 on success, an error number otherwise
  492  * Locks: none
  493  * References: vp must be a valid reference for the duration of the call
  494  */
  495 static int
  496 extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname,
  497     struct thread *td)
  498 {
  499         struct mount *mp;
  500         int error;
  501 
  502         error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
  503         if (error)
  504                 return (error);
  505         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
  506 
  507 #ifdef MAC
  508         error = mac_vnode_check_deleteextattr(td->td_ucred, vp, attrnamespace,
  509             attrname);
  510         if (error)
  511                 goto done;
  512 #endif
  513 
  514         error = VOP_DELETEEXTATTR(vp, attrnamespace, attrname, td->td_ucred,
  515             td);
  516         if (error == EOPNOTSUPP)
  517                 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL,
  518                     td->td_ucred, td);
  519 #ifdef MAC
  520 done:
  521 #endif
  522         VOP_UNLOCK(vp, 0);
  523         vn_finished_write(mp);
  524         return (error);
  525 }
  526 
  527 int
  528 sys_extattr_delete_fd(td, uap)
  529         struct thread *td;
  530         struct extattr_delete_fd_args /* {
  531                 int fd;
  532                 int attrnamespace;
  533                 const char *attrname;
  534         } */ *uap;
  535 {
  536         struct file *fp;
  537         char attrname[EXTATTR_MAXNAMELEN];
  538         cap_rights_t rights;
  539         int error;
  540 
  541         AUDIT_ARG_FD(uap->fd);
  542         AUDIT_ARG_VALUE(uap->attrnamespace);
  543         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
  544         if (error)
  545                 return (error);
  546         AUDIT_ARG_TEXT(attrname);
  547 
  548         error = getvnode(td, uap->fd,
  549             cap_rights_init(&rights, CAP_EXTATTR_DELETE), &fp);
  550         if (error)
  551                 return (error);
  552 
  553         error = extattr_delete_vp(fp->f_vnode, uap->attrnamespace,
  554             attrname, td);
  555         fdrop(fp, td);
  556         return (error);
  557 }
  558 
  559 int
  560 sys_extattr_delete_file(td, uap)
  561         struct thread *td;
  562         struct extattr_delete_file_args /* {
  563                 const char *path;
  564                 int attrnamespace;
  565                 const char *attrname;
  566         } */ *uap;
  567 {
  568         struct nameidata nd;
  569         char attrname[EXTATTR_MAXNAMELEN];
  570         int error;
  571 
  572         AUDIT_ARG_VALUE(uap->attrnamespace);
  573         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
  574         if (error)
  575                 return(error);
  576         AUDIT_ARG_TEXT(attrname);
  577 
  578         NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, UIO_USERSPACE, uap->path, td);
  579         error = namei(&nd);
  580         if (error)
  581                 return(error);
  582         NDFREE(&nd, NDF_ONLY_PNBUF);
  583 
  584         error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td);
  585         vrele(nd.ni_vp);
  586         return(error);
  587 }
  588 
  589 int
  590 sys_extattr_delete_link(td, uap)
  591         struct thread *td;
  592         struct extattr_delete_link_args /* {
  593                 const char *path;
  594                 int attrnamespace;
  595                 const char *attrname;
  596         } */ *uap;
  597 {
  598         struct nameidata nd;
  599         char attrname[EXTATTR_MAXNAMELEN];
  600         int error;
  601 
  602         AUDIT_ARG_VALUE(uap->attrnamespace);
  603         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
  604         if (error)
  605                 return(error);
  606         AUDIT_ARG_TEXT(attrname);
  607 
  608         NDINIT(&nd, LOOKUP, NOFOLLOW | AUDITVNODE1, UIO_USERSPACE, uap->path, td);
  609         error = namei(&nd);
  610         if (error)
  611                 return(error);
  612         NDFREE(&nd, NDF_ONLY_PNBUF);
  613 
  614         error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td);
  615         vrele(nd.ni_vp);
  616         return(error);
  617 }
  618 
  619 /*-
  620  * Retrieve a list of extended attributes on a file or directory.
  621  *
  622  * Arguments: unlocked vnode "vp", attribute namespace 'attrnamespace",
  623  *            userspace buffer pointer "data", buffer length "nbytes",
  624  *            thread "td".
  625  * Returns: 0 on success, an error number otherwise
  626  * Locks: none
  627  * References: vp must be a valid reference for the duration of the call
  628  */
  629 static int
  630 extattr_list_vp(struct vnode *vp, int attrnamespace, void *data,
  631     size_t nbytes, struct thread *td)
  632 {
  633         struct uio auio, *auiop;
  634         size_t size, *sizep;
  635         struct iovec aiov;
  636         ssize_t cnt;
  637         int error;
  638 
  639         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
  640 
  641         auiop = NULL;
  642         sizep = NULL;
  643         cnt = 0;
  644         if (data != NULL) {
  645                 aiov.iov_base = data;
  646                 aiov.iov_len = nbytes;
  647                 auio.uio_iov = &aiov;
  648                 auio.uio_iovcnt = 1;
  649                 auio.uio_offset = 0;
  650                 if (nbytes > IOSIZE_MAX) {
  651                         error = EINVAL;
  652                         goto done;
  653                 }
  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 
  678 done:
  679         VOP_UNLOCK(vp, 0);
  680         return (error);
  681 }
  682 
  683 
  684 int
  685 sys_extattr_list_fd(td, uap)
  686         struct thread *td;
  687         struct extattr_list_fd_args /* {
  688                 int fd;
  689                 int attrnamespace;
  690                 void *data;
  691                 size_t nbytes;
  692         } */ *uap;
  693 {
  694         struct file *fp;
  695         cap_rights_t rights;
  696         int error;
  697 
  698         AUDIT_ARG_FD(uap->fd);
  699         AUDIT_ARG_VALUE(uap->attrnamespace);
  700         error = getvnode(td, uap->fd,
  701             cap_rights_init(&rights, CAP_EXTATTR_LIST), &fp);
  702         if (error)
  703                 return (error);
  704 
  705         error = extattr_list_vp(fp->f_vnode, uap->attrnamespace, uap->data,
  706             uap->nbytes, td);
  707 
  708         fdrop(fp, td);
  709         return (error);
  710 }
  711 
  712 int
  713 sys_extattr_list_file(td, uap)
  714         struct thread*td;
  715         struct extattr_list_file_args /* {
  716                 const char *path;
  717                 int attrnamespace;
  718                 void *data;
  719                 size_t nbytes;
  720         } */ *uap;
  721 {
  722         struct nameidata nd;
  723         int error;
  724 
  725         AUDIT_ARG_VALUE(uap->attrnamespace);
  726         NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, UIO_USERSPACE, uap->path, td);
  727         error = namei(&nd);
  728         if (error)
  729                 return (error);
  730         NDFREE(&nd, NDF_ONLY_PNBUF);
  731 
  732         error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data,
  733             uap->nbytes, td);
  734 
  735         vrele(nd.ni_vp);
  736         return (error);
  737 }
  738 
  739 int
  740 sys_extattr_list_link(td, uap)
  741         struct thread*td;
  742         struct extattr_list_link_args /* {
  743                 const char *path;
  744                 int attrnamespace;
  745                 void *data;
  746                 size_t nbytes;
  747         } */ *uap;
  748 {
  749         struct nameidata nd;
  750         int error;
  751 
  752         AUDIT_ARG_VALUE(uap->attrnamespace);
  753         NDINIT(&nd, LOOKUP, NOFOLLOW | AUDITVNODE1, UIO_USERSPACE, uap->path,
  754             td);
  755         error = namei(&nd);
  756         if (error)
  757                 return (error);
  758         NDFREE(&nd, NDF_ONLY_PNBUF);
  759 
  760         error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data,
  761             uap->nbytes, td);
  762 
  763         vrele(nd.ni_vp);
  764         return (error);
  765 }

Cache object: fa84a3688a1f2d67a4b55c4daf288069


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