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: releng/12.0/sys/kern/vfs_extattr.c 328899 2018-02-05 19:06:34Z brooks $");
   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];
   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, EXTATTR_MAXNAMELEN,
   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,
  106                     UIO_USERSPACE, uap->filename, td);
  107                 error = namei(&nd);
  108                 if (error)
  109                         return (error);
  110                 filename_vp = nd.ni_vp;
  111                 NDFREE(&nd, NDF_NO_VP_RELE);
  112         }
  113 
  114         /* uap->path is always defined. */
  115         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1,
  116             UIO_USERSPACE, uap->path, td);
  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                 NDFREE(&nd, 0);
  124                 mp = NULL;
  125                 goto out;
  126         }
  127         VOP_UNLOCK(nd.ni_vp, 0);
  128         error = vn_start_write(nd.ni_vp, &mp_writable, V_WAIT | PCATCH);
  129         NDFREE(&nd, NDF_NO_VP_UNLOCK);
  130         if (error)
  131                 goto out;
  132         if (filename_vp != NULL) {
  133                 /*
  134                  * uap->filename is not always defined.  If it is,
  135                  * grab a vnode lock, which VFS_EXTATTRCTL() will
  136                  * later release.
  137                  */
  138                 error = vn_lock(filename_vp, LK_EXCLUSIVE);
  139                 if (error) {
  140                         vn_finished_write(mp_writable);
  141                         goto out;
  142                 }
  143         }
  144 
  145         error = VFS_EXTATTRCTL(mp, uap->cmd, filename_vp, uap->attrnamespace,
  146             uap->attrname != NULL ? attrname : NULL);
  147 
  148         vn_finished_write(mp_writable);
  149 out:
  150         if (mp != NULL)
  151                 vfs_unbusy(mp);
  152 
  153         /*
  154          * VFS_EXTATTRCTL will have unlocked, but not de-ref'd, filename_vp,
  155          * so vrele it if it is defined.
  156          */
  157         if (filename_vp != NULL)
  158                 vrele(filename_vp);
  159         return (error);
  160 }
  161 
  162 /*-
  163  * Set a named extended attribute on a file or directory
  164  *
  165  * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
  166  *            kernelspace string pointer "attrname", userspace buffer
  167  *            pointer "data", buffer length "nbytes", thread "td".
  168  * Returns: 0 on success, an error number otherwise
  169  * Locks: none
  170  * References: vp must be a valid reference for the duration of the call
  171  */
  172 static int
  173 extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname,
  174     void *data, size_t nbytes, struct thread *td)
  175 {
  176         struct mount *mp;
  177         struct uio auio;
  178         struct iovec aiov;
  179         ssize_t cnt;
  180         int error;
  181 
  182         if (nbytes > IOSIZE_MAX)
  183                 return (EINVAL);
  184 
  185         error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
  186         if (error)
  187                 return (error);
  188         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
  189 
  190         aiov.iov_base = data;
  191         aiov.iov_len = nbytes;
  192         auio.uio_iov = &aiov;
  193         auio.uio_iovcnt = 1;
  194         auio.uio_offset = 0;
  195         auio.uio_resid = nbytes;
  196         auio.uio_rw = UIO_WRITE;
  197         auio.uio_segflg = UIO_USERSPACE;
  198         auio.uio_td = td;
  199         cnt = nbytes;
  200 
  201 #ifdef MAC
  202         error = mac_vnode_check_setextattr(td->td_ucred, vp, attrnamespace,
  203             attrname);
  204         if (error)
  205                 goto done;
  206 #endif
  207 
  208         error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio,
  209             td->td_ucred, td);
  210         cnt -= auio.uio_resid;
  211         td->td_retval[0] = cnt;
  212 
  213 #ifdef MAC
  214 done:
  215 #endif
  216         VOP_UNLOCK(vp, 0);
  217         vn_finished_write(mp);
  218         return (error);
  219 }
  220 
  221 #ifndef _SYS_SYSPROTO_H_
  222 struct extattr_set_fd_args {
  223         int fd;
  224         int attrnamespace;
  225         const char *attrname;
  226         void *data;
  227         size_t nbytes;
  228 };
  229 #endif
  230 int
  231 sys_extattr_set_fd(struct thread *td, struct extattr_set_fd_args *uap)
  232 {
  233         struct file *fp;
  234         char attrname[EXTATTR_MAXNAMELEN];
  235         cap_rights_t rights;
  236         int error;
  237 
  238         AUDIT_ARG_FD(uap->fd);
  239         AUDIT_ARG_VALUE(uap->attrnamespace);
  240         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
  241         if (error)
  242                 return (error);
  243         AUDIT_ARG_TEXT(attrname);
  244 
  245         error = getvnode(td, uap->fd,
  246             cap_rights_init(&rights, CAP_EXTATTR_SET), &fp);
  247         if (error)
  248                 return (error);
  249 
  250         error = extattr_set_vp(fp->f_vnode, uap->attrnamespace,
  251             attrname, uap->data, uap->nbytes, td);
  252         fdrop(fp, td);
  253 
  254         return (error);
  255 }
  256 
  257 #ifndef _SYS_SYSPROTO_H_
  258 struct extattr_set_file_args {
  259         const char *path;
  260         int attrnamespace;
  261         const char *attrname;
  262         void *data;
  263         size_t nbytes;
  264 };
  265 #endif
  266 int
  267 sys_extattr_set_file(struct thread *td, struct extattr_set_file_args *uap)
  268 {
  269 
  270         return (kern_extattr_set_path(td, uap->path, uap->attrnamespace,
  271             uap->attrname, uap->data, uap->nbytes, FOLLOW));
  272 }
  273 
  274 #ifndef _SYS_SYSPROTO_H_
  275 struct extattr_set_link_args {
  276         const char *path;
  277         int attrnamespace;
  278         const char *attrname;
  279         void *data;
  280         size_t nbytes;
  281 };
  282 #endif
  283 int
  284 sys_extattr_set_link(struct thread *td, struct extattr_set_link_args *uap)
  285 {
  286 
  287         return (kern_extattr_set_path(td, uap->path, uap->attrnamespace,
  288             uap->attrname, uap->data, uap->nbytes, NOFOLLOW));
  289 }
  290 
  291 static int
  292 kern_extattr_set_path(struct thread *td, const char *path, int attrnamespace,
  293     const char *uattrname, void *data, size_t nbytes, int follow)
  294 {
  295         struct nameidata nd;
  296         char attrname[EXTATTR_MAXNAMELEN];
  297         int error;
  298 
  299         AUDIT_ARG_VALUE(attrnamespace);
  300         error = copyinstr(uattrname, attrname, EXTATTR_MAXNAMELEN, NULL);
  301         if (error)
  302                 return (error);
  303         AUDIT_ARG_TEXT(attrname);
  304 
  305         NDINIT(&nd, LOOKUP, follow | AUDITVNODE1, UIO_USERSPACE, path, td);
  306         error = namei(&nd);
  307         if (error)
  308                 return (error);
  309         NDFREE(&nd, NDF_ONLY_PNBUF);
  310 
  311         error = extattr_set_vp(nd.ni_vp, attrnamespace, attrname, data,
  312             nbytes, td);
  313 
  314         vrele(nd.ni_vp);
  315         return (error);
  316 }
  317 
  318 /*-
  319  * Get a named extended attribute on a file or directory
  320  *
  321  * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
  322  *            kernelspace string pointer "attrname", userspace buffer
  323  *            pointer "data", buffer length "nbytes", thread "td".
  324  * Returns: 0 on success, an error number otherwise
  325  * Locks: none
  326  * References: vp must be a valid reference for the duration of the call
  327  */
  328 static int
  329 extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname,
  330     void *data, size_t nbytes, struct thread *td)
  331 {
  332         struct uio auio, *auiop;
  333         struct iovec aiov;
  334         ssize_t cnt;
  335         size_t size, *sizep;
  336         int error;
  337 
  338         if (nbytes > IOSIZE_MAX)
  339                 return (EINVAL);
  340 
  341         vn_lock(vp, LK_SHARED | LK_RETRY);
  342 
  343         /*
  344          * Slightly unusual semantics: if the user provides a NULL data
  345          * pointer, they don't want to receive the data, just the maximum
  346          * read length.
  347          */
  348         auiop = NULL;
  349         sizep = NULL;
  350         cnt = 0;
  351         if (data != NULL) {
  352                 aiov.iov_base = data;
  353                 aiov.iov_len = nbytes;
  354                 auio.uio_iov = &aiov;
  355                 auio.uio_iovcnt = 1;
  356                 auio.uio_offset = 0;
  357                 auio.uio_resid = nbytes;
  358                 auio.uio_rw = UIO_READ;
  359                 auio.uio_segflg = UIO_USERSPACE;
  360                 auio.uio_td = td;
  361                 auiop = &auio;
  362                 cnt = nbytes;
  363         } else
  364                 sizep = &size;
  365 
  366 #ifdef MAC
  367         error = mac_vnode_check_getextattr(td->td_ucred, vp, attrnamespace,
  368             attrname);
  369         if (error)
  370                 goto done;
  371 #endif
  372 
  373         error = VOP_GETEXTATTR(vp, attrnamespace, attrname, auiop, sizep,
  374             td->td_ucred, td);
  375 
  376         if (auiop != NULL) {
  377                 cnt -= auio.uio_resid;
  378                 td->td_retval[0] = cnt;
  379         } else
  380                 td->td_retval[0] = size;
  381 #ifdef MAC
  382 done:
  383 #endif
  384         VOP_UNLOCK(vp, 0);
  385         return (error);
  386 }
  387 
  388 #ifndef _SYS_SYSPROTO_H_
  389 struct extattr_get_fd_args {
  390         int fd;
  391         int attrnamespace;
  392         const char *attrname;
  393         void *data;
  394         size_t nbytes;
  395 };
  396 #endif
  397 int
  398 sys_extattr_get_fd(struct thread *td, struct extattr_get_fd_args *uap)
  399 {
  400         struct file *fp;
  401         char attrname[EXTATTR_MAXNAMELEN];
  402         cap_rights_t rights;
  403         int error;
  404 
  405         AUDIT_ARG_FD(uap->fd);
  406         AUDIT_ARG_VALUE(uap->attrnamespace);
  407         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
  408         if (error)
  409                 return (error);
  410         AUDIT_ARG_TEXT(attrname);
  411 
  412         error = getvnode(td, uap->fd,
  413             cap_rights_init(&rights, CAP_EXTATTR_GET), &fp);
  414         if (error)
  415                 return (error);
  416 
  417         error = extattr_get_vp(fp->f_vnode, uap->attrnamespace,
  418             attrname, uap->data, uap->nbytes, td);
  419 
  420         fdrop(fp, td);
  421         return (error);
  422 }
  423 
  424 #ifndef _SYS_SYSPROTO_H_
  425 struct extattr_get_file_args {
  426         const char *path;
  427         int attrnamespace;
  428         const char *attrname;
  429         void *data;
  430         size_t nbytes;
  431 };
  432 #endif
  433 int
  434 sys_extattr_get_file(struct thread *td, struct extattr_get_file_args *uap)
  435 {
  436         return (kern_extattr_get_path(td, uap->path, uap->attrnamespace,
  437             uap->attrname, uap->data, uap->nbytes, FOLLOW));
  438 }
  439 
  440 #ifndef _SYS_SYSPROTO_H_
  441 struct extattr_get_link_args {
  442         const char *path;
  443         int attrnamespace;
  444         const char *attrname;
  445         void *data;
  446         size_t nbytes;
  447 };
  448 #endif
  449 int
  450 sys_extattr_get_link(struct thread *td, struct extattr_get_link_args *uap)
  451 {
  452         return (kern_extattr_get_path(td, uap->path, uap->attrnamespace,
  453             uap->attrname, uap->data, uap->nbytes, NOFOLLOW));
  454 }
  455 
  456 static int
  457 kern_extattr_get_path(struct thread *td, const char *path, int attrnamespace,
  458     const char *uattrname, void *data, size_t nbytes, int follow)
  459 {
  460         struct nameidata nd;
  461         char attrname[EXTATTR_MAXNAMELEN];
  462         int error;
  463 
  464         AUDIT_ARG_VALUE(attrnamespace);
  465         error = copyinstr(uattrname, attrname, EXTATTR_MAXNAMELEN, NULL);
  466         if (error)
  467                 return (error);
  468         AUDIT_ARG_TEXT(attrname);
  469 
  470         NDINIT(&nd, LOOKUP, follow | AUDITVNODE1, UIO_USERSPACE, path, td);
  471         error = namei(&nd);
  472         if (error)
  473                 return (error);
  474         NDFREE(&nd, NDF_ONLY_PNBUF);
  475 
  476         error = extattr_get_vp(nd.ni_vp, attrnamespace, attrname, data,
  477             nbytes, td);
  478 
  479         vrele(nd.ni_vp);
  480         return (error);
  481 }
  482 
  483 /*
  484  * extattr_delete_vp(): Delete a named extended attribute on a file or
  485  *                      directory
  486  *
  487  * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
  488  *            kernelspace string pointer "attrname", proc "p"
  489  * Returns: 0 on success, an error number otherwise
  490  * Locks: none
  491  * References: vp must be a valid reference for the duration of the call
  492  */
  493 static int
  494 extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname,
  495     struct thread *td)
  496 {
  497         struct mount *mp;
  498         int error;
  499 
  500         error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
  501         if (error)
  502                 return (error);
  503         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
  504 
  505 #ifdef MAC
  506         error = mac_vnode_check_deleteextattr(td->td_ucred, vp, attrnamespace,
  507             attrname);
  508         if (error)
  509                 goto done;
  510 #endif
  511 
  512         error = VOP_DELETEEXTATTR(vp, attrnamespace, attrname, td->td_ucred,
  513             td);
  514         if (error == EOPNOTSUPP)
  515                 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL,
  516                     td->td_ucred, td);
  517 #ifdef MAC
  518 done:
  519 #endif
  520         VOP_UNLOCK(vp, 0);
  521         vn_finished_write(mp);
  522         return (error);
  523 }
  524 
  525 #ifndef _SYS_SYSPROTO_H_
  526 struct extattr_delete_fd_args {
  527         int fd;
  528         int attrnamespace;
  529         const char *attrname;
  530 };
  531 #endif
  532 int
  533 sys_extattr_delete_fd(struct thread *td, struct extattr_delete_fd_args *uap)
  534 {
  535         struct file *fp;
  536         char attrname[EXTATTR_MAXNAMELEN];
  537         cap_rights_t rights;
  538         int error;
  539 
  540         AUDIT_ARG_FD(uap->fd);
  541         AUDIT_ARG_VALUE(uap->attrnamespace);
  542         error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
  543         if (error)
  544                 return (error);
  545         AUDIT_ARG_TEXT(attrname);
  546 
  547         error = getvnode(td, uap->fd,
  548             cap_rights_init(&rights, CAP_EXTATTR_DELETE), &fp);
  549         if (error)
  550                 return (error);
  551 
  552         error = extattr_delete_vp(fp->f_vnode, uap->attrnamespace,
  553             attrname, td);
  554         fdrop(fp, td);
  555         return (error);
  556 }
  557 
  558 #ifndef _SYS_SYSPROTO_H_
  559 struct extattr_delete_file_args {
  560         const char *path;
  561         int attrnamespace;
  562         const char *attrname;
  563 };
  564 #endif
  565 int
  566 sys_extattr_delete_file(struct thread *td, struct extattr_delete_file_args *uap)
  567 {
  568 
  569         return (kern_extattr_delete_path(td, uap->path, uap->attrnamespace,
  570             uap->attrname, FOLLOW));
  571 }
  572 
  573 #ifndef _SYS_SYSPROTO_H_
  574 struct extattr_delete_link_args {
  575         const char *path;
  576         int attrnamespace;
  577         const char *attrname;
  578 };
  579 #endif
  580 int
  581 sys_extattr_delete_link(struct thread *td, struct extattr_delete_link_args *uap)
  582 {
  583 
  584         return (kern_extattr_delete_path(td, uap->path, uap->attrnamespace,
  585             uap->attrname, NOFOLLOW));
  586 }
  587 
  588 static int
  589 kern_extattr_delete_path(struct thread *td, const char *path, int attrnamespace,
  590     const char *uattrname, int follow)
  591 {
  592         struct nameidata nd;
  593         char attrname[EXTATTR_MAXNAMELEN];
  594         int error;
  595 
  596         AUDIT_ARG_VALUE(attrnamespace);
  597         error = copyinstr(uattrname, attrname, EXTATTR_MAXNAMELEN, NULL);
  598         if (error)
  599                 return(error);
  600         AUDIT_ARG_TEXT(attrname);
  601 
  602         NDINIT(&nd, LOOKUP, follow | AUDITVNODE1, UIO_USERSPACE, path, td);
  603         error = namei(&nd);
  604         if (error)
  605                 return(error);
  606         NDFREE(&nd, NDF_ONLY_PNBUF);
  607 
  608         error = extattr_delete_vp(nd.ni_vp, attrnamespace, attrname, td);
  609         vrele(nd.ni_vp);
  610         return(error);
  611 }
  612 
  613 /*-
  614  * Retrieve a list of extended attributes on a file or directory.
  615  *
  616  * Arguments: unlocked vnode "vp", attribute namespace 'attrnamespace",
  617  *            userspace buffer pointer "data", buffer length "nbytes",
  618  *            thread "td".
  619  * Returns: 0 on success, an error number otherwise
  620  * Locks: none
  621  * References: vp must be a valid reference for the duration of the call
  622  */
  623 static int
  624 extattr_list_vp(struct vnode *vp, int attrnamespace, void *data,
  625     size_t nbytes, struct thread *td)
  626 {
  627         struct uio auio, *auiop;
  628         size_t size, *sizep;
  629         struct iovec aiov;
  630         ssize_t cnt;
  631         int error;
  632 
  633         if (nbytes > IOSIZE_MAX)
  634                 return (EINVAL);
  635 
  636         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
  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 #ifdef MAC
  657         error = mac_vnode_check_listextattr(td->td_ucred, vp, attrnamespace);
  658         if (error)
  659                 goto done;
  660 #endif
  661 
  662         error = VOP_LISTEXTATTR(vp, attrnamespace, auiop, sizep,
  663             td->td_ucred, td);
  664 
  665         if (auiop != NULL) {
  666                 cnt -= auio.uio_resid;
  667                 td->td_retval[0] = cnt;
  668         } else
  669                 td->td_retval[0] = size;
  670 #ifdef MAC
  671 done:
  672 #endif
  673         VOP_UNLOCK(vp, 0);
  674         return (error);
  675 }
  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(td, uap->fd,
  696             cap_rights_init(&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, td);
  748         error = namei(&nd);
  749         if (error)
  750                 return (error);
  751         NDFREE(&nd, NDF_ONLY_PNBUF);
  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: f0bea305cb3cf0e1f6a5883a1c5a71b9


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