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_xattr.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 /*      $NetBSD: vfs_xattr.c,v 1.38 2022/10/25 23:22:36 riastradh Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 2005, 2008 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Jason R. Thorpe.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   29  * POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 /*
   33  * Copyright (c) 1989, 1993
   34  *      The Regents of the University of California.  All rights reserved.
   35  * (c) UNIX System Laboratories, Inc.
   36  * All or some portions of this file are derived from material licensed
   37  * to the University of California by American Telephone and Telegraph
   38  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
   39  * the permission of UNIX System Laboratories, Inc.
   40  *
   41  * Redistribution and use in source and binary forms, with or without
   42  * modification, are permitted provided that the following conditions
   43  * are met:
   44  * 1. Redistributions of source code must retain the above copyright
   45  *    notice, this list of conditions and the following disclaimer.
   46  * 2. Redistributions in binary form must reproduce the above copyright
   47  *    notice, this list of conditions and the following disclaimer in the
   48  *    documentation and/or other materials provided with the distribution.
   49  * 3. Neither the name of the University nor the names of its contributors
   50  *    may be used to endorse or promote products derived from this software
   51  *    without specific prior written permission.
   52  *
   53  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   54  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   55  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   56  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   57  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   58  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   59  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   60  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   61  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   62  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   63  * SUCH DAMAGE.
   64  */
   65 
   66 /*
   67  * VFS extended attribute support.
   68  */
   69 
   70 #include <sys/cdefs.h>
   71 __KERNEL_RCSID(0, "$NetBSD: vfs_xattr.c,v 1.38 2022/10/25 23:22:36 riastradh Exp $");
   72 
   73 #include <sys/param.h>
   74 #include <sys/systm.h>
   75 #include <sys/namei.h>
   76 #include <sys/filedesc.h>
   77 #include <sys/kernel.h>
   78 #include <sys/file.h>
   79 #include <sys/vnode.h>
   80 #include <sys/mount.h>
   81 #include <sys/proc.h>
   82 #include <sys/uio.h>
   83 #include <sys/extattr.h>
   84 #include <sys/xattr.h>
   85 #include <sys/sysctl.h>
   86 #include <sys/syscallargs.h>
   87 #include <sys/kauth.h>
   88 #include <sys/ktrace.h>
   89 
   90 #include <miscfs/genfs/genfs.h>
   91 
   92 static void
   93 ktr_xattr_name(const char *str)
   94 {
   95         ktrkuser("xattr-name", (void *)__UNCONST(str), strlen(str));
   96 }
   97 
   98 static void
   99 ktr_xattr_val(const void *data, size_t cnt)
  100 {
  101         ktruser("xattr-val", __UNCONST(data), cnt, 0);
  102 }
  103 
  104 /*
  105  * Credential check based on process requesting service, and per-attribute
  106  * permissions.
  107  *
  108  * NOTE: Vnode must be locked.
  109  */
  110 int
  111 extattr_check_cred(struct vnode *vp, int attrspace, kauth_cred_t cred,
  112     int access)
  113 {
  114 
  115         if (cred == NOCRED)
  116                 return 0;
  117 
  118         return kauth_authorize_vnode(cred, kauth_extattr_action(access), vp,
  119             NULL, genfs_can_extattr(vp, cred, access, attrspace));
  120 }
  121 
  122 /*
  123  * Default vfs_extattrctl routine for file systems that do not support
  124  * it.
  125  */
  126 /*ARGSUSED*/
  127 int
  128 vfs_stdextattrctl(struct mount *mp, int cmt, struct vnode *vp,
  129     int attrnamespace, const char *attrname)
  130 {
  131 
  132         if (vp != NULL)
  133                 VOP_UNLOCK(vp);
  134         return EOPNOTSUPP;
  135 }
  136 
  137 /*
  138  * Push extended attribute configuration information into the file
  139  * system.
  140  *
  141  * NOTE: Not all file systems that support extended attributes will
  142  * require the use of this system call.
  143  */
  144 int
  145 sys_extattrctl(struct lwp *l, const struct sys_extattrctl_args *uap, register_t *retval)
  146 {
  147         /* {
  148                 syscallarg(const char *) path;
  149                 syscallarg(int) cmd;
  150                 syscallarg(const char *) filename;
  151                 syscallarg(int) attrnamespace;
  152                 syscallarg(const char *) attrname;
  153         } */
  154         struct vnode *path_vp, *file_vp;
  155         struct pathbuf *file_pb;
  156         struct nameidata file_nd;
  157         char attrname[EXTATTR_MAXNAMELEN];
  158         int error;
  159 
  160         if (SCARG(uap, attrname) != NULL) {
  161                 error = copyinstr(SCARG(uap, attrname), attrname,
  162                     sizeof(attrname), NULL);
  163                 if (error)
  164                         return error;
  165         }
  166 
  167         error = namei_simple_user(SCARG(uap, path), NSM_FOLLOW_NOEMULROOT,
  168             &path_vp);
  169         if (error)
  170                 return error;
  171 
  172         file_vp = NULL;
  173         if (SCARG(uap, filename) != NULL) {
  174                 error = pathbuf_copyin(SCARG(uap, filename), &file_pb);
  175                 if (error) {
  176                         vrele(path_vp);
  177                         return error;
  178                 }
  179                 NDINIT(&file_nd, LOOKUP, FOLLOW | LOCKLEAF, file_pb);
  180                 error = namei(&file_nd);
  181                 if (error) {
  182                         pathbuf_destroy(file_pb);
  183                         vrele(path_vp);
  184                         return error;
  185                 }
  186                 file_vp = file_nd.ni_vp;
  187                 pathbuf_destroy(file_pb);
  188         }
  189 
  190         error = VFS_EXTATTRCTL(path_vp->v_mount, SCARG(uap, cmd), file_vp,
  191             SCARG(uap, attrnamespace),
  192             SCARG(uap, attrname) != NULL ? attrname : NULL);
  193 
  194         if (file_vp != NULL)
  195                 vrele(file_vp);
  196         vrele(path_vp);
  197 
  198         return error;
  199 }
  200 
  201 /*****************************************************************************
  202  * Internal routines to manipulate file system extended attributes:
  203  *      - set
  204  *      - get
  205  *      - delete
  206  *      - list
  207  *****************************************************************************/
  208 
  209 /*
  210  * extattr_set_vp:
  211  *
  212  *      Set a named extended attribute on a file or directory.
  213  */
  214 static int
  215 extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname,
  216     const void *data, size_t nbytes, struct lwp *l, register_t *retval,
  217     int flag)
  218 {
  219         struct uio auio;
  220         struct iovec aiov;
  221         ssize_t cnt;
  222         int error;
  223 
  224         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
  225 
  226         if (flag) {
  227                 size_t attrlen;
  228 
  229                 error = VOP_GETEXTATTR(vp, attrnamespace, attrname, NULL,
  230                     &attrlen, l->l_cred);
  231 
  232                 switch (error) {
  233                 case ENODATA:
  234                         if (flag & XATTR_REPLACE)
  235                                 goto done;
  236                         break;
  237                 case 0:
  238                         if (flag & XATTR_CREATE) {
  239                                 error = EEXIST;
  240                                 goto done;
  241                         }
  242                         break;
  243                 default:
  244                         goto done;
  245                         break;
  246                 }
  247         }
  248 
  249         aiov.iov_base = __UNCONST(data);        /* XXXUNCONST kills const */
  250         aiov.iov_len = nbytes;
  251         auio.uio_iov = &aiov;
  252         auio.uio_iovcnt = 1;
  253         auio.uio_offset = 0;
  254         if (nbytes > INT_MAX) {
  255                 error = EINVAL;
  256                 goto done;
  257         }
  258         auio.uio_resid = nbytes;
  259         auio.uio_rw = UIO_WRITE;
  260         KASSERT(l == curlwp);
  261         auio.uio_vmspace = l->l_proc->p_vmspace;
  262         cnt = nbytes;
  263 
  264         ktr_xattr_name(attrname);
  265         ktr_xattr_val(data, nbytes);
  266 
  267         error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio, l->l_cred);
  268         cnt -= auio.uio_resid;
  269         retval[0] = cnt;
  270 
  271  done:
  272         VOP_UNLOCK(vp);
  273         return error;
  274 }
  275 
  276 /*
  277  * extattr_get_vp:
  278  *
  279  *      Get a named extended attribute on a file or directory.
  280  */
  281 static int
  282 extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname,
  283     void *data, size_t nbytes, struct lwp *l, register_t *retval)
  284 {
  285         struct uio auio, *auiop;
  286         struct iovec aiov;
  287         ssize_t cnt;
  288         size_t size, *sizep;
  289         int error;
  290 
  291         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
  292 
  293         /*
  294          * Slightly unusual semantics: if the user provides a NULL data
  295          * pointer, they don't want to receive the data, just the maximum
  296          * read length.
  297          */
  298         auiop = NULL;
  299         sizep = NULL;
  300         cnt = 0;
  301         if (data != NULL) {
  302                 aiov.iov_base = data;
  303                 aiov.iov_len = nbytes;
  304                 auio.uio_iov = &aiov;
  305                 auio.uio_iovcnt = 1;
  306                 auio.uio_offset = 0;
  307                 if (nbytes > INT_MAX) {
  308                         error = EINVAL;
  309                         goto done;
  310                 }
  311                 auio.uio_resid = nbytes;
  312                 auio.uio_rw = UIO_READ;
  313                 KASSERT(l == curlwp);
  314                 auio.uio_vmspace = l->l_proc->p_vmspace;
  315                 auiop = &auio;
  316                 cnt = nbytes;
  317         } else
  318                 sizep = &size;
  319 
  320         ktr_xattr_name(attrname);
  321 
  322         error = VOP_GETEXTATTR(vp, attrnamespace, attrname, auiop, sizep,
  323             l->l_cred);
  324 
  325         if (auiop != NULL) {
  326                 cnt -= auio.uio_resid;
  327                 retval[0] = cnt;
  328 
  329                 ktr_xattr_val(data, cnt);
  330         } else
  331                 retval[0] = size;
  332 
  333  done:
  334         VOP_UNLOCK(vp);
  335         return error;
  336 }
  337 
  338 /*
  339  * extattr_delete_vp:
  340  *
  341  *      Delete a named extended attribute on a file or directory.
  342  */
  343 static int
  344 extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname,
  345     struct lwp *l)
  346 {
  347         int error;
  348 
  349         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
  350 
  351         ktr_xattr_name(attrname);
  352 
  353         error = VOP_DELETEEXTATTR(vp, attrnamespace, attrname, l->l_cred);
  354         if (error == EOPNOTSUPP)
  355                 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL,
  356                     l->l_cred);
  357 
  358         VOP_UNLOCK(vp);
  359         return error;
  360 }
  361 
  362 /*
  363  * extattr_list_vp:
  364  *
  365  *      Retrieve a list of extended attributes on a file or directory.
  366  */
  367 static int
  368 extattr_list_vp(struct vnode *vp, int attrnamespace, void *data, size_t nbytes,
  369     int flag, struct lwp *l, register_t *retval)
  370 {
  371         struct uio auio, *auiop;
  372         size_t size, *sizep;
  373         struct iovec aiov;
  374         ssize_t cnt;
  375         int error;
  376 
  377         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
  378 
  379         auiop = NULL;
  380         sizep = NULL;
  381         cnt = 0;
  382         if (data != NULL) {
  383                 aiov.iov_base = data;
  384                 aiov.iov_len = nbytes;
  385                 auio.uio_iov = &aiov;
  386                 auio.uio_iovcnt = 1;
  387                 auio.uio_offset = 0;
  388                 if (nbytes > INT_MAX) {
  389                         error = EINVAL;
  390                         goto done;
  391                 }
  392                 auio.uio_resid = nbytes;
  393                 auio.uio_rw = UIO_READ;
  394                 KASSERT(l == curlwp);
  395                 auio.uio_vmspace = l->l_proc->p_vmspace;
  396                 auiop = &auio;
  397                 cnt = nbytes;
  398         } else
  399                 sizep = &size;
  400 
  401         error = VOP_LISTEXTATTR(vp, attrnamespace, auiop, sizep, flag,
  402             l->l_cred);
  403 
  404         if (auiop != NULL) {
  405                 cnt -= auio.uio_resid;
  406                 retval[0] = cnt;
  407 
  408                 ktruser("xattr-list", data, cnt, 0);
  409         } else
  410                 retval[0] = size;
  411 
  412  done:
  413         VOP_UNLOCK(vp);
  414         return error;
  415 }
  416 
  417 /*****************************************************************************
  418  * BSD <sys/extattr.h> API for file system extended attributes
  419  *****************************************************************************/
  420 
  421 int
  422 sys_extattr_set_fd(struct lwp *l, const struct sys_extattr_set_fd_args *uap,
  423     register_t *retval)
  424 {
  425         /* {
  426                 syscallarg(int) fd;
  427                 syscallarg(int) attrnamespace;
  428                 syscallarg(const char *) attrname;
  429                 syscallarg(const void *) data;
  430                 syscallarg(size_t) nbytes;
  431         } */
  432         struct file *fp;
  433         struct vnode *vp;
  434         char attrname[EXTATTR_MAXNAMELEN];
  435         int error;
  436 
  437         error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
  438             NULL);
  439         if (error)
  440                 return error;
  441 
  442         error = fd_getvnode(SCARG(uap, fd), &fp);
  443         if (error)
  444                 return error;
  445         vp = fp->f_vnode;
  446 
  447         error = extattr_set_vp(vp, SCARG(uap, attrnamespace), attrname,
  448             SCARG(uap, data), SCARG(uap, nbytes), l, retval, 0);
  449 
  450         fd_putfile(SCARG(uap, fd));
  451         return error;
  452 }
  453 
  454 int
  455 sys_extattr_set_file(struct lwp *l,
  456     const struct sys_extattr_set_file_args *uap,
  457     register_t *retval)
  458 {
  459         /* {
  460                 syscallarg(const char *) path;
  461                 syscallarg(int) attrnamespace;
  462                 syscallarg(const char *) attrname;
  463                 syscallarg(const void *) data;
  464                 syscallarg(size_t) nbytes;
  465         } */
  466         struct vnode *vp;
  467         char attrname[EXTATTR_MAXNAMELEN];
  468         int error;
  469 
  470         error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
  471             NULL);
  472         if (error)
  473                 return error;
  474 
  475         error = namei_simple_user(SCARG(uap, path), NSM_FOLLOW_NOEMULROOT,
  476             &vp);
  477         if (error)
  478                 return error;
  479 
  480         error = extattr_set_vp(vp, SCARG(uap, attrnamespace), attrname,
  481             SCARG(uap, data), SCARG(uap, nbytes), l, retval, 0);
  482 
  483         vrele(vp);
  484         return error;
  485 }
  486 
  487 int
  488 sys_extattr_set_link(struct lwp *l,
  489     const struct sys_extattr_set_link_args *uap,
  490     register_t *retval)
  491 {
  492         /* {
  493                 syscallarg(const char *) path;
  494                 syscallarg(int) attrnamespace;
  495                 syscallarg(const char *) attrname;
  496                 syscallarg(const void *) data;
  497                 syscallarg(size_t) nbytes;
  498         } */
  499         struct vnode *vp;
  500         char attrname[EXTATTR_MAXNAMELEN];
  501         int error;
  502 
  503         error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
  504             NULL);
  505         if (error)
  506                 return error;
  507 
  508         error = namei_simple_user(SCARG(uap, path), NSM_NOFOLLOW_NOEMULROOT,
  509             &vp);
  510         if (error)
  511                 return error;
  512 
  513         error = extattr_set_vp(vp, SCARG(uap, attrnamespace), attrname,
  514             SCARG(uap, data), SCARG(uap, nbytes), l, retval, 0);
  515 
  516         vrele(vp);
  517         return error;
  518 }
  519 
  520 int
  521 sys_extattr_get_fd(struct lwp *l,
  522     const struct sys_extattr_get_fd_args *uap,
  523     register_t *retval)
  524 {
  525         /* {
  526                 syscallarg(int) fd;
  527                 syscallarg(int) attrnamespace;
  528                 syscallarg(const char *) attrname;
  529                 syscallarg(void *) data;
  530                 syscallarg(size_t) nbytes;
  531         } */
  532         struct file *fp;
  533         struct vnode *vp;
  534         char attrname[EXTATTR_MAXNAMELEN];
  535         int error;
  536 
  537         error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
  538             NULL);
  539         if (error)
  540                 return error;
  541 
  542         error = fd_getvnode(SCARG(uap, fd), &fp);
  543         if (error)
  544                 return error;
  545         vp = fp->f_vnode;
  546 
  547         error = extattr_get_vp(vp, SCARG(uap, attrnamespace), attrname,
  548             SCARG(uap, data), SCARG(uap, nbytes), l, retval);
  549 
  550         fd_putfile(SCARG(uap, fd));
  551         return error;
  552 }
  553 
  554 int
  555 sys_extattr_get_file(struct lwp *l,
  556     const struct sys_extattr_get_file_args *uap,
  557     register_t *retval)
  558 {
  559         /* {
  560                 syscallarg(const char *) path;
  561                 syscallarg(int) attrnamespace;
  562                 syscallarg(const char *) attrname;
  563                 syscallarg(void *) data;
  564                 syscallarg(size_t) nbytes;
  565         } */
  566         struct vnode *vp;
  567         char attrname[EXTATTR_MAXNAMELEN];
  568         int error;
  569 
  570         error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
  571             NULL);
  572         if (error)
  573                 return error;
  574 
  575         error = namei_simple_user(SCARG(uap, path), NSM_FOLLOW_NOEMULROOT,
  576             &vp);
  577         if (error)
  578                 return error;
  579 
  580         error = extattr_get_vp(vp, SCARG(uap, attrnamespace), attrname,
  581             SCARG(uap, data), SCARG(uap, nbytes), l, retval);
  582 
  583         vrele(vp);
  584         return error;
  585 }
  586 
  587 int
  588 sys_extattr_get_link(struct lwp *l,
  589     const struct sys_extattr_get_link_args *uap,
  590     register_t *retval)
  591 {
  592         /* {
  593                 syscallarg(const char *) path;
  594                 syscallarg(int) attrnamespace;
  595                 syscallarg(const char *) attrname;
  596                 syscallarg(void *) data;
  597                 syscallarg(size_t) nbytes;
  598         } */
  599         struct vnode *vp;
  600         char attrname[EXTATTR_MAXNAMELEN];
  601         int error;
  602 
  603         error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
  604             NULL);
  605         if (error)
  606                 return error;
  607 
  608         error = namei_simple_user(SCARG(uap, path), NSM_NOFOLLOW_NOEMULROOT,
  609             &vp);
  610         if (error)
  611                 return error;
  612 
  613         error = extattr_get_vp(vp, SCARG(uap, attrnamespace), attrname,
  614             SCARG(uap, data), SCARG(uap, nbytes), l, retval);
  615 
  616         vrele(vp);
  617         return error;
  618 }
  619 
  620 int
  621 sys_extattr_delete_fd(struct lwp *l,
  622     const struct sys_extattr_delete_fd_args *uap,
  623     register_t *retval)
  624 {
  625         /* {
  626                 syscallarg(int) fd;
  627                 syscallarg(int) attrnamespace;
  628                 syscallarg(const char *) attrname;
  629         } */
  630         struct file *fp;
  631         struct vnode *vp;
  632         char attrname[EXTATTR_MAXNAMELEN];
  633         int error;
  634 
  635         error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
  636             NULL);
  637         if (error)
  638                 return error;
  639 
  640         error = fd_getvnode(SCARG(uap, fd), &fp);
  641         if (error)
  642                 return error;
  643         vp = fp->f_vnode;
  644 
  645         error = extattr_delete_vp(vp, SCARG(uap, attrnamespace), attrname, l);
  646 
  647         fd_putfile(SCARG(uap, fd));
  648         return error;
  649 }
  650 
  651 int
  652 sys_extattr_delete_file(struct lwp *l,
  653     const struct sys_extattr_delete_file_args *uap,
  654     register_t *retval)
  655 {
  656         /* {
  657                 syscallarg(const char *) path;
  658                 syscallarg(int) attrnamespace;
  659                 syscallarg(const char *) attrname;
  660         } */
  661         struct vnode *vp;
  662         char attrname[EXTATTR_MAXNAMELEN];
  663         int error;
  664 
  665         error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
  666             NULL);
  667         if (error)
  668                 return error;
  669 
  670         error = namei_simple_user(SCARG(uap, path), NSM_FOLLOW_NOEMULROOT,
  671             &vp);
  672         if (error)
  673                 return error;
  674 
  675         error = extattr_delete_vp(vp, SCARG(uap, attrnamespace), attrname, l);
  676 
  677         vrele(vp);
  678         return error;
  679 }
  680 
  681 int
  682 sys_extattr_delete_link(struct lwp *l,
  683     const struct sys_extattr_delete_link_args *uap,
  684     register_t *retval)
  685 {
  686         /* {
  687                 syscallarg(const char *) path;
  688                 syscallarg(int) attrnamespace;
  689                 syscallarg(const char *) attrname;
  690         } */
  691         struct vnode *vp;
  692         char attrname[EXTATTR_MAXNAMELEN];
  693         int error;
  694 
  695         error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
  696             NULL);
  697         if (error)
  698                 return error;
  699 
  700         error = namei_simple_user(SCARG(uap, path), NSM_NOFOLLOW_NOEMULROOT,
  701             &vp);
  702         if (error)
  703                 return error;
  704 
  705         error = extattr_delete_vp(vp, SCARG(uap, attrnamespace), attrname, l);
  706 
  707         vrele(vp);
  708         return error;
  709 }
  710 
  711 int
  712 sys_extattr_list_fd(struct lwp *l,
  713     const struct sys_extattr_list_fd_args *uap,
  714     register_t *retval)
  715 {
  716         /* {
  717                 syscallarg(int) fd;
  718                 syscallarg(int) attrnamespace;
  719                 syscallarg(void *) data;
  720                 syscallarg(size_t) nbytes;
  721         } */
  722         struct file *fp;
  723         struct vnode *vp;
  724         int error;
  725 
  726         error = fd_getvnode(SCARG(uap, fd), &fp);
  727         if (error)
  728                 return error;
  729         vp = fp->f_vnode;
  730 
  731         error = extattr_list_vp(vp, SCARG(uap, attrnamespace),
  732             SCARG(uap, data), SCARG(uap, nbytes),
  733             EXTATTR_LIST_LENPREFIX, l, retval);
  734 
  735         fd_putfile(SCARG(uap, fd));
  736         return error;
  737 }
  738 
  739 int
  740 sys_extattr_list_file(struct lwp *l,
  741     const struct sys_extattr_list_file_args *uap,
  742     register_t *retval)
  743 {
  744         /* {
  745                 syscallarg(const char *) path;
  746                 syscallarg(int) attrnamespace;
  747                 syscallarg(void *) data;
  748                 syscallarg(size_t) nbytes;
  749         } */
  750         struct vnode *vp;
  751         int error;
  752 
  753         error = namei_simple_user(SCARG(uap, path), NSM_FOLLOW_NOEMULROOT,
  754             &vp);
  755         if (error)
  756                 return error;
  757 
  758         error = extattr_list_vp(vp, SCARG(uap, attrnamespace),
  759             SCARG(uap, data), SCARG(uap, nbytes),
  760             EXTATTR_LIST_LENPREFIX, l, retval);
  761 
  762         vrele(vp);
  763         return error;
  764 }
  765 
  766 int
  767 sys_extattr_list_link(struct lwp *l,
  768     const struct sys_extattr_list_link_args *uap,
  769     register_t *retval)
  770 {
  771         /* {
  772                 syscallarg(const char *) path;
  773                 syscallarg(int) attrnamespace;
  774                 syscallarg(void *) data;
  775                 syscallarg(size_t) nbytes;
  776         } */
  777         struct vnode *vp;
  778         int error;
  779 
  780         error = namei_simple_user(SCARG(uap, path), NSM_NOFOLLOW_NOEMULROOT,
  781             &vp);
  782         if (error)
  783                 return error;
  784 
  785         error = extattr_list_vp(vp, SCARG(uap, attrnamespace),
  786             SCARG(uap, data), SCARG(uap, nbytes),
  787             EXTATTR_LIST_LENPREFIX, l, retval);
  788 
  789         vrele(vp);
  790         return error;
  791 }
  792 
  793 /*****************************************************************************
  794  * Linux-compatible <sys/xattr.h> API for file system extended attributes
  795  *****************************************************************************/
  796 
  797 #define MATCH_NS(ns, key) (strncmp(ns, key, sizeof(ns) - 1) == 0)
  798 static int
  799 xattr_native(const char *key)
  800 {
  801 
  802         if (MATCH_NS("system.", key))
  803                 return EXTATTR_NAMESPACE_SYSTEM;
  804         else if (MATCH_NS("user.", key))
  805                 return EXTATTR_NAMESPACE_USER;
  806         else if (MATCH_NS("security.", key))
  807                 return EXTATTR_NAMESPACE_SYSTEM;
  808         else if (MATCH_NS("trusted.", key))
  809                 return EXTATTR_NAMESPACE_SYSTEM;
  810         else
  811                 return EXTATTR_NAMESPACE_USER;
  812 }
  813 #undef MATCH_NS
  814 
  815 #define XATTR_ERRNO(e) ((e) == EOPNOTSUPP ? ENOTSUP : (e))
  816 
  817 int
  818 sys_setxattr(struct lwp *l,
  819     const struct sys_setxattr_args *uap,
  820     register_t *retval)
  821 {
  822         /* {
  823                 syscallarg(const char *) path;
  824                 syscallarg(const char *) name;
  825                 syscallarg(void *) value;
  826                 syscallarg(size_t) size;
  827                 syscallarg(int) flags;
  828         } */
  829         struct vnode *vp;
  830         char attrname[XATTR_NAME_MAX];
  831         int attrnamespace;
  832         register_t attrlen;
  833         int error;
  834 
  835         error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
  836             NULL);
  837         if (error)
  838                 goto out;
  839 
  840         error = namei_simple_user(SCARG(uap, path),
  841             NSM_FOLLOW_NOEMULROOT, &vp);
  842         if (error)
  843                 goto out;
  844 
  845         attrnamespace = xattr_native(attrname);
  846 
  847         error = extattr_set_vp(vp, attrnamespace,
  848             attrname, SCARG(uap, value), SCARG(uap, size), l,
  849             &attrlen, SCARG(uap, flags));
  850 
  851         vrele(vp);
  852 out:
  853         *retval = (error == 0 ? 0 : -1);
  854         return XATTR_ERRNO(error);
  855 }
  856 
  857 int
  858 sys_lsetxattr(struct lwp *l,
  859     const struct sys_lsetxattr_args *uap,
  860     register_t *retval)
  861 {
  862         /* {
  863                 syscallarg(const char *) path;
  864                 syscallarg(const char *) name;
  865                 syscallarg(void *) value;
  866                 syscallarg(size_t) size;
  867                 syscallarg(int) flags;
  868         } */
  869         struct vnode *vp;
  870         char attrname[XATTR_NAME_MAX];
  871         int attrnamespace;
  872         register_t attrlen;
  873         int error;
  874 
  875         error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
  876             NULL);
  877         if (error)
  878                 goto out;
  879 
  880         error = namei_simple_user(SCARG(uap, path), NSM_NOFOLLOW_NOEMULROOT,
  881             &vp);
  882         if (error)
  883                 goto out;
  884 
  885         attrnamespace = xattr_native(attrname);
  886 
  887         error = extattr_set_vp(vp, attrnamespace,
  888             attrname, SCARG(uap, value), SCARG(uap, size), l,
  889             &attrlen, SCARG(uap, flags));
  890 
  891         vrele(vp);
  892 out:
  893         *retval = (error == 0 ? 0 : -1);
  894         return XATTR_ERRNO(error);
  895 }
  896 
  897 int
  898 sys_fsetxattr(struct lwp *l,
  899     const struct sys_fsetxattr_args *uap,
  900     register_t *retval)
  901 {
  902         /* {
  903                 syscallarg(int) fd;
  904                 syscallarg(const char *) name;
  905                 syscallarg(void *) value;
  906                 syscallarg(size_t) size;
  907                 syscallarg(int) flags;
  908         } */
  909         struct file *fp;
  910         struct vnode *vp;
  911         char attrname[XATTR_NAME_MAX];
  912         int attrnamespace;
  913         register_t attrlen;
  914         int error;
  915 
  916         error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
  917             NULL);
  918         if (error)
  919                 goto out;
  920 
  921         error = fd_getvnode(SCARG(uap, fd), &fp);
  922         if (error)
  923                 goto out;
  924         vp = fp->f_vnode;
  925 
  926         attrnamespace = xattr_native(attrname);
  927 
  928         error = extattr_set_vp(vp, attrnamespace,
  929             attrname, SCARG(uap, value), SCARG(uap, size), l,
  930             &attrlen, SCARG(uap, flags));
  931 
  932         fd_putfile(SCARG(uap, fd));
  933 out:
  934         *retval = (error == 0 ? 0 : -1);
  935         return XATTR_ERRNO(error);
  936 }
  937 
  938 int
  939 sys_getxattr(struct lwp *l,
  940     const struct sys_getxattr_args *uap,
  941     register_t *retval)
  942 {
  943         /* {
  944                 syscallarg(const char *) path;
  945                 syscallarg(const char *) name;
  946                 syscallarg(void *) value;
  947                 syscallarg(size_t) size;
  948         } */
  949         struct vnode *vp;
  950         char attrname[XATTR_NAME_MAX];
  951         int attrnamespace;
  952         int error;
  953 
  954         error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
  955             NULL);
  956         if (error)
  957                 return error;
  958 
  959         error = namei_simple_user(SCARG(uap, path), NSM_FOLLOW_NOEMULROOT,
  960             &vp);
  961         if (error)
  962                 return error;
  963 
  964         attrnamespace = xattr_native(attrname);
  965 
  966         error = extattr_get_vp(vp, attrnamespace,
  967             attrname, SCARG(uap, value), SCARG(uap, size), l, retval);
  968 
  969         vrele(vp);
  970         return XATTR_ERRNO(error);
  971 }
  972 
  973 int
  974 sys_lgetxattr(struct lwp *l,
  975     const struct sys_lgetxattr_args *uap,
  976     register_t *retval)
  977 {
  978         /* {
  979                 syscallarg(const char *) path;
  980                 syscallarg(const char *) name;
  981                 syscallarg(void *) value;
  982                 syscallarg(size_t) size;
  983         } */
  984         struct vnode *vp;
  985         char attrname[XATTR_NAME_MAX];
  986         int attrnamespace;
  987         int error;
  988 
  989         error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
  990             NULL);
  991         if (error)
  992                 return error;
  993 
  994         error = namei_simple_user(SCARG(uap, path), NSM_NOFOLLOW_NOEMULROOT,
  995             &vp);
  996         if (error)
  997                 return error;
  998 
  999         attrnamespace = xattr_native(attrname);
 1000 
 1001         error = extattr_get_vp(vp, attrnamespace,
 1002             attrname, SCARG(uap, value), SCARG(uap, size), l, retval);
 1003 
 1004         vrele(vp);
 1005         return XATTR_ERRNO(error);
 1006 }
 1007 
 1008 int
 1009 sys_fgetxattr(struct lwp *l,
 1010     const struct sys_fgetxattr_args *uap,
 1011     register_t *retval)
 1012 {
 1013         /* {
 1014                 syscallarg(int) fd;
 1015                 syscallarg(const char *) name;
 1016                 syscallarg(void *) value;
 1017                 syscallarg(size_t) size;
 1018         } */
 1019         struct file *fp;
 1020         struct vnode *vp;
 1021         char attrname[XATTR_NAME_MAX];
 1022         int attrnamespace;
 1023         int error;
 1024 
 1025         error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
 1026             NULL);
 1027         if (error)
 1028                 return error;
 1029 
 1030         error = fd_getvnode(SCARG(uap, fd), &fp);
 1031         if (error)
 1032                 return error;
 1033         vp = fp->f_vnode;
 1034 
 1035         attrnamespace = xattr_native(attrname);
 1036 
 1037         error = extattr_get_vp(vp, attrnamespace,
 1038             attrname, SCARG(uap, value), SCARG(uap, size), l, retval);
 1039 
 1040         fd_putfile(SCARG(uap, fd));
 1041         return XATTR_ERRNO(error);
 1042 }
 1043 
 1044 int
 1045 sys_listxattr(struct lwp *l,
 1046     const struct sys_listxattr_args *uap,
 1047     register_t *retval)
 1048 {
 1049         /* {
 1050                 syscallarg(const char *) path;
 1051                 syscallarg(char *) list;
 1052                 syscallarg(size_t) size;
 1053         } */
 1054         struct vnode *vp;
 1055         char *list;
 1056         size_t size;
 1057         register_t listsize_usr, listsize_sys;
 1058         int error;
 1059 
 1060         error = namei_simple_user(SCARG(uap, path), NSM_FOLLOW_NOEMULROOT,
 1061             &vp);
 1062         if (error)
 1063                 return error;
 1064 
 1065         list = SCARG(uap, list);
 1066         size = SCARG(uap, size);
 1067 
 1068         error = extattr_list_vp(vp, EXTATTR_NAMESPACE_USER,
 1069             list, size, 0, l, &listsize_usr);
 1070         if (error)
 1071                 goto out;
 1072 
 1073         if (list)
 1074                 list += listsize_usr;
 1075         if (size)
 1076                 size -= listsize_usr;
 1077 
 1078         error = extattr_list_vp(vp, EXTATTR_NAMESPACE_SYSTEM,
 1079             list, size, 0, l, &listsize_sys);
 1080         switch (error) {
 1081         case EPERM:
 1082                 error = 0; /* Ignore and just skip system EA */
 1083                 listsize_sys = 0;
 1084                 break;
 1085         case 0:
 1086                 break;
 1087         default:
 1088                 goto out;
 1089                 break;
 1090         }
 1091 
 1092         *retval = listsize_usr + listsize_sys;
 1093 out:
 1094         vrele(vp);
 1095         return XATTR_ERRNO(error);
 1096 }
 1097 
 1098 int
 1099 sys_llistxattr(struct lwp *l,
 1100     const struct sys_llistxattr_args *uap,
 1101     register_t *retval)
 1102 {
 1103         /* {
 1104                 syscallarg(const char *) path;
 1105                 syscallarg(char *) list;
 1106                 syscallarg(size_t) size;
 1107         } */
 1108         struct vnode *vp;
 1109         char *list;
 1110         size_t size;
 1111         register_t listsize_usr, listsize_sys;
 1112         int error;
 1113 
 1114         error = namei_simple_user(SCARG(uap, path), NSM_NOFOLLOW_NOEMULROOT,
 1115             &vp);
 1116         if (error)
 1117                 return error;
 1118 
 1119         list = SCARG(uap, list);
 1120         size = SCARG(uap, size);
 1121 
 1122         error = extattr_list_vp(vp, EXTATTR_NAMESPACE_USER,
 1123             list, size, 0, l, &listsize_usr);
 1124         if (error)
 1125                 goto out;
 1126         if (list)
 1127                 list += listsize_usr;
 1128         if (size)
 1129                 size -= listsize_usr;
 1130 
 1131         error = extattr_list_vp(vp, EXTATTR_NAMESPACE_SYSTEM,
 1132             list, size, 0, l, &listsize_sys);
 1133         switch (error) {
 1134         case EPERM:
 1135                 error = 0; /* Ignore and just skip system EA */
 1136                 listsize_sys = 0;
 1137                 break;
 1138         case 0:
 1139                 break;
 1140         default:
 1141                 goto out;
 1142                 break;
 1143         }
 1144 
 1145         *retval = listsize_usr + listsize_sys;
 1146 out:
 1147         vrele(vp);
 1148         return XATTR_ERRNO(error);
 1149 }
 1150 
 1151 int
 1152 sys_flistxattr(struct lwp *l,
 1153     const struct sys_flistxattr_args *uap,
 1154     register_t *retval)
 1155 {
 1156         /* {
 1157                 syscallarg(int) fd;
 1158                 syscallarg(char *) list;
 1159                 syscallarg(size_t) size;
 1160         } */
 1161         struct file *fp;
 1162         struct vnode *vp;
 1163         char *list;
 1164         size_t size;
 1165         register_t listsize_usr, listsize_sys;
 1166         int error;
 1167 
 1168         error = fd_getvnode(SCARG(uap, fd), &fp);
 1169         if (error)
 1170                 return error;
 1171         vp = fp->f_vnode;
 1172 
 1173         list = SCARG(uap, list);
 1174         size = SCARG(uap, size);
 1175 
 1176         error = extattr_list_vp(vp, EXTATTR_NAMESPACE_USER,
 1177             list, size, 0, l, &listsize_usr);
 1178         if (error)
 1179                 goto out;
 1180 
 1181         if (list)
 1182                 list += listsize_usr;
 1183         if (size)
 1184                 size -= listsize_usr;
 1185 
 1186         error = extattr_list_vp(vp, EXTATTR_NAMESPACE_SYSTEM,
 1187             list, size, 0, l, &listsize_sys);
 1188         switch (error) {
 1189         case EPERM:
 1190                 error = 0; /* Ignore and just skip system EA */
 1191                 listsize_sys = 0;
 1192                 break;
 1193         case 0:
 1194                 break;
 1195         default:
 1196                 goto out;
 1197                 break;
 1198         }
 1199 
 1200         *retval = listsize_usr + listsize_sys;
 1201 out:
 1202         fd_putfile(SCARG(uap, fd));
 1203         return XATTR_ERRNO(error);
 1204 }
 1205 
 1206 int
 1207 sys_removexattr(struct lwp *l,
 1208     const struct sys_removexattr_args *uap,
 1209     register_t *retval)
 1210 {
 1211         /* {
 1212                 syscallarg(const char *) path;
 1213                 syscallarg(const char *) name;
 1214         } */
 1215         struct vnode *vp;
 1216         char attrname[XATTR_NAME_MAX];
 1217         int attrnamespace;
 1218         int error;
 1219 
 1220         error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
 1221             NULL);
 1222         if (error)
 1223                 return error;
 1224 
 1225         error = namei_simple_user(SCARG(uap, path), NSM_FOLLOW_NOEMULROOT,
 1226             &vp);
 1227         if (error)
 1228                 return error;
 1229 
 1230         attrnamespace = xattr_native(attrname);
 1231 
 1232         error = extattr_delete_vp(vp, attrnamespace, attrname, l);
 1233 
 1234         vrele(vp);
 1235         return XATTR_ERRNO(error);
 1236 }
 1237 
 1238 int
 1239 sys_lremovexattr(struct lwp *l,
 1240     const struct sys_lremovexattr_args *uap,
 1241     register_t *retval)
 1242 {
 1243         /* {
 1244                 syscallarg(const char *) path;
 1245                 syscallarg(const char *) name;
 1246         } */
 1247         struct vnode *vp;
 1248         char attrname[XATTR_NAME_MAX];
 1249         int attrnamespace;
 1250         int error;
 1251 
 1252         error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
 1253             NULL);
 1254         if (error)
 1255                 return error;
 1256 
 1257         error = namei_simple_user(SCARG(uap, path), NSM_NOFOLLOW_NOEMULROOT,
 1258             &vp);
 1259         if (error)
 1260                 return error;
 1261 
 1262         attrnamespace = xattr_native(attrname);
 1263 
 1264         error = extattr_delete_vp(vp, attrnamespace, attrname, l);
 1265 
 1266         vrele(vp);
 1267         return XATTR_ERRNO(error);
 1268 }
 1269 
 1270 int
 1271 sys_fremovexattr(struct lwp *l,
 1272     const struct sys_fremovexattr_args *uap,
 1273     register_t *retval)
 1274 {
 1275         /* {
 1276                 syscallarg(int) fd;
 1277                 syscallarg(const char *) name;
 1278         } */
 1279         struct file *fp;
 1280         struct vnode *vp;
 1281         char attrname[XATTR_NAME_MAX];
 1282         int attrnamespace;
 1283         int error;
 1284 
 1285         error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
 1286             NULL);
 1287         if (error)
 1288                 return error;
 1289 
 1290         error = fd_getvnode(SCARG(uap, fd), &fp);
 1291         if (error)
 1292                 return error;
 1293         vp = fp->f_vnode;
 1294 
 1295         attrnamespace = xattr_native(attrname);
 1296 
 1297         error = extattr_delete_vp(vp, attrnamespace, attrname, l);
 1298 
 1299         fd_putfile(SCARG(uap, fd));
 1300         return XATTR_ERRNO(error);
 1301 }

Cache object: 59a9df4ce9fad27b441e1e96f898e3fd


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