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

Cache object: 690a68085250fa98e900506dae02db7e


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