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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 1999-2001 Robert N. M. Watson
    5  * All rights reserved.
    6  *
    7  * This software was developed by Robert Watson for the TrustedBSD Project.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   28  * SUCH DAMAGE.
   29  */
   30 
   31 #include <sys/cdefs.h>
   32 __FBSDID("$FreeBSD$");
   33 
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/capsicum.h>
   37 #include <sys/lock.h>
   38 #include <sys/mount.h>
   39 #include <sys/mutex.h>
   40 #include <sys/sysproto.h>
   41 #include <sys/fcntl.h>
   42 #include <sys/namei.h>
   43 #include <sys/filedesc.h>
   44 #include <sys/limits.h>
   45 #include <sys/vnode.h>
   46 #include <sys/proc.h>
   47 #include <sys/extattr.h>
   48 
   49 #include <security/audit/audit.h>
   50 #include <security/mac/mac_framework.h>
   51 
   52 static int      kern_extattr_set_path(struct thread *td, const char *path,
   53                     int attrnamespace, const char *attrname, void *data,
   54                     size_t nbytes, int follow);
   55 static int      kern_extattr_get_path(struct thread *td, const char *path,
   56                     int attrnamespace, const char *attrname, void *data,
   57                     size_t nbytes, int follow);
   58 static int      kern_extattr_delete_path(struct thread *td, const char *path,
   59                     int attrnamespace, const char *attrname, int follow);
   60 static int      kern_extattr_list_path(struct thread *td, const char *path,
   61                     int attrnamespace, void *data, size_t nbytes, int follow);
   62 
   63 /*
   64  * Syscall to push extended attribute configuration information into the VFS.
   65  * Accepts a path, which it converts to a mountpoint, as well as a command
   66  * (int cmd), and attribute name and misc data.
   67  *
   68  * Currently this is used only by UFS1 extended attributes.
   69  */
   70 #ifndef _SYS_SYSPROTO_H_
   71 struct extattrctl_args {
   72         const char *path;
   73         int cmd;
   74         const char *filename;
   75         int attrnamespace;
   76         const char *attrname;
   77 };
   78 #endif
   79 int
   80 sys_extattrctl(struct thread *td, struct extattrctl_args *uap)
   81 {
   82         struct vnode *filename_vp;
   83         struct nameidata nd;
   84         struct mount *mp, *mp_writable;
   85         char attrname[EXTATTR_MAXNAMELEN + 1];
   86         int error;
   87 
   88         AUDIT_ARG_CMD(uap->cmd);
   89         AUDIT_ARG_VALUE(uap->attrnamespace);
   90         /*
   91          * uap->attrname is not always defined.  We check again later when we
   92          * invoke the VFS call so as to pass in NULL there if needed.
   93          */
   94         if (uap->attrname != NULL) {
   95                 error = copyinstr(uap->attrname, attrname, sizeof(attrname),
   96                     NULL);
   97                 if (error)
   98                         return (error);
   99         }
  100         AUDIT_ARG_TEXT(attrname);
  101 
  102         mp = NULL;
  103         filename_vp = NULL;
  104         if (uap->filename != NULL) {
  105                 NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE2, UIO_USERSPACE,
  106                     uap->filename);
  107                 error = namei(&nd);
  108                 if (error)
  109                         return (error);
  110                 filename_vp = nd.ni_vp;
  111                 NDFREE_PNBUF(&nd);
  112         }
  113 
  114         /* uap->path is always defined. */
  115         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1, UIO_USERSPACE,
  116             uap->path);
  117         error = namei(&nd);
  118         if (error)
  119                 goto out;
  120         mp = nd.ni_vp->v_mount;
  121         error = vfs_busy(mp, 0);
  122         if (error) {
  123                 vput(nd.ni_vp);
  124                 NDFREE_PNBUF(&nd);
  125                 mp = NULL;
  126                 goto out;
  127         }
  128         VOP_UNLOCK(nd.ni_vp);
  129         error = vn_start_write(nd.ni_vp, &mp_writable, V_WAIT | V_PCATCH);
  130         vrele(nd.ni_vp);
  131         NDFREE_PNBUF(&nd);
  132         if (error)
  133                 goto out;
  134         if (filename_vp != NULL) {
  135                 /*
  136                  * uap->filename is not always defined.  If it is,
  137                  * grab a vnode lock, which VFS_EXTATTRCTL() will
  138                  * later release.
  139                  */
  140                 error = vn_lock(filename_vp, LK_EXCLUSIVE);
  141                 if (error) {
  142                         vn_finished_write(mp_writable);
  143                         goto out;
  144                 }
  145         }
  146 
  147         error = VFS_EXTATTRCTL(mp, uap->cmd, filename_vp, uap->attrnamespace,
  148             uap->attrname != NULL ? attrname : NULL);
  149 
  150         vn_finished_write(mp_writable);
  151 out:
  152         if (mp != NULL)
  153                 vfs_unbusy(mp);
  154 
  155         /*
  156          * VFS_EXTATTRCTL will have unlocked, but not de-ref'd, filename_vp,
  157          * so vrele it if it is defined.
  158          */
  159         if (filename_vp != NULL)
  160                 vrele(filename_vp);
  161         return (error);
  162 }
  163 
  164 /*-
  165  * Set a named extended attribute on a file or directory
  166  *
  167  * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
  168  *            kernelspace string pointer "attrname", userspace buffer
  169  *            pointer "data", buffer length "nbytes", thread "td".
  170  * Returns: 0 on success, an error number otherwise
  171  * Locks: none
  172  * References: vp must be a valid reference for the duration of the call
  173  */
  174 static int
  175 extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname,
  176     void *data, size_t nbytes, struct thread *td)
  177 {
  178         struct mount *mp;
  179         struct uio auio;
  180         struct iovec aiov;
  181         ssize_t cnt;
  182         int error;
  183 
  184         if (nbytes > IOSIZE_MAX)
  185                 return (EINVAL);
  186 
  187         error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH);
  188         if (error)
  189                 return (error);
  190         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
  191 
  192         aiov.iov_base = data;
  193         aiov.iov_len = nbytes;
  194         auio.uio_iov = &aiov;
  195         auio.uio_iovcnt = 1;
  196         auio.uio_offset = 0;
  197         auio.uio_resid = nbytes;
  198         auio.uio_rw = UIO_WRITE;
  199         auio.uio_segflg = UIO_USERSPACE;
  200         auio.uio_td = td;
  201         cnt = nbytes;
  202 
  203 #ifdef MAC
  204         error = mac_vnode_check_setextattr(td->td_ucred, vp, attrnamespace,
  205             attrname);
  206         if (error)
  207                 goto done;
  208 #endif
  209 
  210         error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio,
  211             td->td_ucred, td);
  212         cnt -= auio.uio_resid;
  213         td->td_retval[0] = cnt;
  214 
  215 #ifdef MAC
  216 done:
  217 #endif
  218         VOP_UNLOCK(vp);
  219         vn_finished_write(mp);
  220         return (error);
  221 }
  222 
  223 #ifndef _SYS_SYSPROTO_H_
  224 struct extattr_set_fd_args {
  225         int fd;
  226         int attrnamespace;
  227         const char *attrname;
  228         void *data;
  229         size_t nbytes;
  230 };
  231 #endif
  232 int
  233 sys_extattr_set_fd(struct thread *td, struct extattr_set_fd_args *uap)
  234 {
  235         struct file *fp;
  236         char attrname[EXTATTR_MAXNAMELEN + 1];
  237         cap_rights_t rights;
  238         int error;
  239 
  240         AUDIT_ARG_FD(uap->fd);
  241         AUDIT_ARG_VALUE(uap->attrnamespace);
  242         error = copyinstr(uap->attrname, attrname, sizeof(attrname), NULL);
  243         if (error)
  244                 return (error);
  245         AUDIT_ARG_TEXT(attrname);
  246 
  247         error = getvnode_path(td, uap->fd,
  248             cap_rights_init_one(&rights, CAP_EXTATTR_SET), &fp);
  249         if (error)
  250                 return (error);
  251 
  252         error = extattr_set_vp(fp->f_vnode, uap->attrnamespace,
  253             attrname, uap->data, uap->nbytes, td);
  254         fdrop(fp, td);
  255 
  256         return (error);
  257 }
  258 
  259 #ifndef _SYS_SYSPROTO_H_
  260 struct extattr_set_file_args {
  261         const char *path;
  262         int attrnamespace;
  263         const char *attrname;
  264         void *data;
  265         size_t nbytes;
  266 };
  267 #endif
  268 int
  269 sys_extattr_set_file(struct thread *td, struct extattr_set_file_args *uap)
  270 {
  271 
  272         return (kern_extattr_set_path(td, uap->path, uap->attrnamespace,
  273             uap->attrname, uap->data, uap->nbytes, FOLLOW));
  274 }
  275 
  276 #ifndef _SYS_SYSPROTO_H_
  277 struct extattr_set_link_args {
  278         const char *path;
  279         int attrnamespace;
  280         const char *attrname;
  281         void *data;
  282         size_t nbytes;
  283 };
  284 #endif
  285 int
  286 sys_extattr_set_link(struct thread *td, struct extattr_set_link_args *uap)
  287 {
  288 
  289         return (kern_extattr_set_path(td, uap->path, uap->attrnamespace,
  290             uap->attrname, uap->data, uap->nbytes, NOFOLLOW));
  291 }
  292 
  293 static int
  294 kern_extattr_set_path(struct thread *td, const char *path, int attrnamespace,
  295     const char *uattrname, void *data, size_t nbytes, int follow)
  296 {
  297         struct nameidata nd;
  298         char attrname[EXTATTR_MAXNAMELEN + 1];
  299         int error;
  300 
  301         AUDIT_ARG_VALUE(attrnamespace);
  302         error = copyinstr(uattrname, attrname, sizeof(attrname), NULL);
  303         if (error)
  304                 return (error);
  305         AUDIT_ARG_TEXT(attrname);
  306 
  307         NDINIT(&nd, LOOKUP, follow | AUDITVNODE1, UIO_USERSPACE, path);
  308         error = namei(&nd);
  309         if (error)
  310                 return (error);
  311         NDFREE_PNBUF(&nd);
  312 
  313         error = extattr_set_vp(nd.ni_vp, attrnamespace, attrname, data,
  314             nbytes, td);
  315 
  316         vrele(nd.ni_vp);
  317         return (error);
  318 }
  319 
  320 /*-
  321  * Get a named extended attribute on a file or directory
  322  *
  323  * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
  324  *            kernelspace string pointer "attrname", userspace buffer
  325  *            pointer "data", buffer length "nbytes", thread "td".
  326  * Returns: 0 on success, an error number otherwise
  327  * Locks: none
  328  * References: vp must be a valid reference for the duration of the call
  329  */
  330 static int
  331 extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname,
  332     void *data, size_t nbytes, struct thread *td)
  333 {
  334         struct uio auio, *auiop;
  335         struct iovec aiov;
  336         ssize_t cnt;
  337         size_t size, *sizep;
  338         int error;
  339 
  340         if (nbytes > IOSIZE_MAX)
  341                 return (EINVAL);
  342 
  343         vn_lock(vp, LK_SHARED | LK_RETRY);
  344 
  345         /*
  346          * Slightly unusual semantics: if the user provides a NULL data
  347          * pointer, they don't want to receive the data, just the maximum
  348          * read length.
  349          */
  350         auiop = NULL;
  351         sizep = NULL;
  352         cnt = 0;
  353         if (data != NULL) {
  354                 aiov.iov_base = data;
  355                 aiov.iov_len = nbytes;
  356                 auio.uio_iov = &aiov;
  357                 auio.uio_iovcnt = 1;
  358                 auio.uio_offset = 0;
  359                 auio.uio_resid = nbytes;
  360                 auio.uio_rw = UIO_READ;
  361                 auio.uio_segflg = UIO_USERSPACE;
  362                 auio.uio_td = td;
  363                 auiop = &auio;
  364                 cnt = nbytes;
  365         } else
  366                 sizep = &size;
  367 
  368 #ifdef MAC
  369         error = mac_vnode_check_getextattr(td->td_ucred, vp, attrnamespace,
  370             attrname);
  371         if (error)
  372                 goto done;
  373 #endif
  374 
  375         error = VOP_GETEXTATTR(vp, attrnamespace, attrname, auiop, sizep,
  376             td->td_ucred, td);
  377 
  378         if (auiop != NULL) {
  379                 cnt -= auio.uio_resid;
  380                 td->td_retval[0] = cnt;
  381         } else
  382                 td->td_retval[0] = size;
  383 #ifdef MAC
  384 done:
  385 #endif
  386         VOP_UNLOCK(vp);
  387         return (error);
  388 }
  389 
  390 #ifndef _SYS_SYSPROTO_H_
  391 struct extattr_get_fd_args {
  392         int fd;
  393         int attrnamespace;
  394         const char *attrname;
  395         void *data;
  396         size_t nbytes;
  397 };
  398 #endif
  399 int
  400 sys_extattr_get_fd(struct thread *td, struct extattr_get_fd_args *uap)
  401 {
  402         struct file *fp;
  403         char attrname[EXTATTR_MAXNAMELEN + 1];
  404         cap_rights_t rights;
  405         int error;
  406 
  407         AUDIT_ARG_FD(uap->fd);
  408         AUDIT_ARG_VALUE(uap->attrnamespace);
  409         error = copyinstr(uap->attrname, attrname, sizeof(attrname), NULL);
  410         if (error)
  411                 return (error);
  412         AUDIT_ARG_TEXT(attrname);
  413 
  414         error = getvnode_path(td, uap->fd,
  415             cap_rights_init_one(&rights, CAP_EXTATTR_GET), &fp);
  416         if (error)
  417                 return (error);
  418 
  419         error = extattr_get_vp(fp->f_vnode, uap->attrnamespace,
  420             attrname, uap->data, uap->nbytes, td);
  421 
  422         fdrop(fp, td);
  423         return (error);
  424 }
  425 
  426 #ifndef _SYS_SYSPROTO_H_
  427 struct extattr_get_file_args {
  428         const char *path;
  429         int attrnamespace;
  430         const char *attrname;
  431         void *data;
  432         size_t nbytes;
  433 };
  434 #endif
  435 int
  436 sys_extattr_get_file(struct thread *td, struct extattr_get_file_args *uap)
  437 {
  438         return (kern_extattr_get_path(td, uap->path, uap->attrnamespace,
  439             uap->attrname, uap->data, uap->nbytes, FOLLOW));
  440 }
  441 
  442 #ifndef _SYS_SYSPROTO_H_
  443 struct extattr_get_link_args {
  444         const char *path;
  445         int attrnamespace;
  446         const char *attrname;
  447         void *data;
  448         size_t nbytes;
  449 };
  450 #endif
  451 int
  452 sys_extattr_get_link(struct thread *td, struct extattr_get_link_args *uap)
  453 {
  454         return (kern_extattr_get_path(td, uap->path, uap->attrnamespace,
  455             uap->attrname, uap->data, uap->nbytes, NOFOLLOW));
  456 }
  457 
  458 static int
  459 kern_extattr_get_path(struct thread *td, const char *path, int attrnamespace,
  460     const char *uattrname, void *data, size_t nbytes, int follow)
  461 {
  462         struct nameidata nd;
  463         char attrname[EXTATTR_MAXNAMELEN + 1];
  464         int error;
  465 
  466         AUDIT_ARG_VALUE(attrnamespace);
  467         error = copyinstr(uattrname, attrname, sizeof(attrname), NULL);
  468         if (error)
  469                 return (error);
  470         AUDIT_ARG_TEXT(attrname);
  471 
  472         NDINIT(&nd, LOOKUP, follow | AUDITVNODE1, UIO_USERSPACE, path);
  473         error = namei(&nd);
  474         if (error)
  475                 return (error);
  476         NDFREE_PNBUF(&nd);
  477 
  478         error = extattr_get_vp(nd.ni_vp, attrnamespace, attrname, data,
  479             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 | V_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);
  523         vn_finished_write(mp);
  524         return (error);
  525 }
  526 
  527 #ifndef _SYS_SYSPROTO_H_
  528 struct extattr_delete_fd_args {
  529         int fd;
  530         int attrnamespace;
  531         const char *attrname;
  532 };
  533 #endif
  534 int
  535 sys_extattr_delete_fd(struct thread *td, struct extattr_delete_fd_args *uap)
  536 {
  537         struct file *fp;
  538         char attrname[EXTATTR_MAXNAMELEN + 1];
  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, sizeof(attrname), NULL);
  545         if (error)
  546                 return (error);
  547         AUDIT_ARG_TEXT(attrname);
  548 
  549         error = getvnode_path(td, uap->fd,
  550             cap_rights_init_one(&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 #ifndef _SYS_SYSPROTO_H_
  561 struct extattr_delete_file_args {
  562         const char *path;
  563         int attrnamespace;
  564         const char *attrname;
  565 };
  566 #endif
  567 int
  568 sys_extattr_delete_file(struct thread *td, struct extattr_delete_file_args *uap)
  569 {
  570 
  571         return (kern_extattr_delete_path(td, uap->path, uap->attrnamespace,
  572             uap->attrname, FOLLOW));
  573 }
  574 
  575 #ifndef _SYS_SYSPROTO_H_
  576 struct extattr_delete_link_args {
  577         const char *path;
  578         int attrnamespace;
  579         const char *attrname;
  580 };
  581 #endif
  582 int
  583 sys_extattr_delete_link(struct thread *td, struct extattr_delete_link_args *uap)
  584 {
  585 
  586         return (kern_extattr_delete_path(td, uap->path, uap->attrnamespace,
  587             uap->attrname, NOFOLLOW));
  588 }
  589 
  590 static int
  591 kern_extattr_delete_path(struct thread *td, const char *path, int attrnamespace,
  592     const char *uattrname, int follow)
  593 {
  594         struct nameidata nd;
  595         char attrname[EXTATTR_MAXNAMELEN + 1];
  596         int error;
  597 
  598         AUDIT_ARG_VALUE(attrnamespace);
  599         error = copyinstr(uattrname, attrname, sizeof(attrname), NULL);
  600         if (error)
  601                 return(error);
  602         AUDIT_ARG_TEXT(attrname);
  603 
  604         NDINIT(&nd, LOOKUP, follow | AUDITVNODE1, UIO_USERSPACE, path);
  605         error = namei(&nd);
  606         if (error)
  607                 return(error);
  608         NDFREE_PNBUF(&nd);
  609 
  610         error = extattr_delete_vp(nd.ni_vp, attrnamespace, attrname, td);
  611         vrele(nd.ni_vp);
  612         return(error);
  613 }
  614 
  615 /*-
  616  * Retrieve a list of extended attributes on a file or directory.
  617  *
  618  * Arguments: unlocked vnode "vp", attribute namespace 'attrnamespace",
  619  *            userspace buffer pointer "data", buffer length "nbytes",
  620  *            thread "td".
  621  * Returns: 0 on success, an error number otherwise
  622  * Locks: none
  623  * References: vp must be a valid reference for the duration of the call
  624  */
  625 static int
  626 extattr_list_vp(struct vnode *vp, int attrnamespace, void *data,
  627     size_t nbytes, struct thread *td)
  628 {
  629         struct uio auio, *auiop;
  630         size_t size, *sizep;
  631         struct iovec aiov;
  632         ssize_t cnt;
  633         int error;
  634 
  635         if (nbytes > IOSIZE_MAX)
  636                 return (EINVAL);
  637 
  638         auiop = NULL;
  639         sizep = NULL;
  640         cnt = 0;
  641         if (data != NULL) {
  642                 aiov.iov_base = data;
  643                 aiov.iov_len = nbytes;
  644                 auio.uio_iov = &aiov;
  645                 auio.uio_iovcnt = 1;
  646                 auio.uio_offset = 0;
  647                 auio.uio_resid = nbytes;
  648                 auio.uio_rw = UIO_READ;
  649                 auio.uio_segflg = UIO_USERSPACE;
  650                 auio.uio_td = td;
  651                 auiop = &auio;
  652                 cnt = nbytes;
  653         } else
  654                 sizep = &size;
  655 
  656         vn_lock(vp, LK_SHARED | LK_RETRY);
  657 
  658 #ifdef MAC
  659         error = mac_vnode_check_listextattr(td->td_ucred, vp, attrnamespace);
  660         if (error) {
  661                 VOP_UNLOCK(vp);
  662                 return (error);
  663         }
  664 #endif
  665 
  666         error = VOP_LISTEXTATTR(vp, attrnamespace, auiop, sizep,
  667             td->td_ucred, td);
  668         VOP_UNLOCK(vp);
  669 
  670         if (auiop != NULL) {
  671                 cnt -= auio.uio_resid;
  672                 td->td_retval[0] = cnt;
  673         } else
  674                 td->td_retval[0] = size;
  675         return (error);
  676 }
  677 
  678 #ifndef _SYS_SYSPROTO_H_
  679 struct extattr_list_fd_args {
  680         int fd;
  681         int attrnamespace;
  682         void *data;
  683         size_t nbytes;
  684 };
  685 #endif
  686 int
  687 sys_extattr_list_fd(struct thread *td, struct extattr_list_fd_args *uap)
  688 {
  689         struct file *fp;
  690         cap_rights_t rights;
  691         int error;
  692 
  693         AUDIT_ARG_FD(uap->fd);
  694         AUDIT_ARG_VALUE(uap->attrnamespace);
  695         error = getvnode_path(td, uap->fd,
  696             cap_rights_init_one(&rights, CAP_EXTATTR_LIST), &fp);
  697         if (error)
  698                 return (error);
  699 
  700         error = extattr_list_vp(fp->f_vnode, uap->attrnamespace, uap->data,
  701             uap->nbytes, td);
  702 
  703         fdrop(fp, td);
  704         return (error);
  705 }
  706 
  707 #ifndef _SYS_SYSPROTO_H_
  708 struct extattr_list_file_args {
  709         const char *path;
  710         int attrnamespace;
  711         void *data;
  712         size_t nbytes;
  713 }
  714 #endif
  715 int
  716 sys_extattr_list_file(struct thread *td, struct extattr_list_file_args *uap)
  717 {
  718 
  719         return (kern_extattr_list_path(td, uap->path, uap->attrnamespace,
  720             uap->data, uap->nbytes, FOLLOW));
  721 }
  722 
  723 #ifndef _SYS_SYSPROTO_H_
  724 struct extattr_list_link_args {
  725         const char *path;
  726         int attrnamespace;
  727         void *data;
  728         size_t nbytes;
  729 };
  730 #endif
  731 int
  732 sys_extattr_list_link(struct thread *td, struct extattr_list_link_args *uap)
  733 {
  734 
  735         return (kern_extattr_list_path(td, uap->path, uap->attrnamespace,
  736             uap->data, uap->nbytes, NOFOLLOW));
  737 }
  738 
  739 static int
  740 kern_extattr_list_path(struct thread *td, const char *path, int attrnamespace,
  741     void *data, size_t nbytes, int follow)
  742 {
  743         struct nameidata nd;
  744         int error;
  745 
  746         AUDIT_ARG_VALUE(attrnamespace);
  747         NDINIT(&nd, LOOKUP, follow | AUDITVNODE1, UIO_USERSPACE, path);
  748         error = namei(&nd);
  749         if (error)
  750                 return (error);
  751         NDFREE_PNBUF(&nd);
  752 
  753         error = extattr_list_vp(nd.ni_vp, attrnamespace, data, nbytes, td);
  754 
  755         vrele(nd.ni_vp);
  756         return (error);
  757 }

Cache object: e82b7e79afbd80020d00fa7dd44f51a9


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