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

Cache object: d64d43e426099ccfa4183085cc1adeb8


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