LCOV - code coverage report
Current view: top level - fs - xattr.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 99 343 28.9 %
Date: 2014-02-18 Functions: 15 37 40.5 %
Branches: 54 276 19.6 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :   File: fs/xattr.c
       3                 :            : 
       4                 :            :   Extended attribute handling.
       5                 :            : 
       6                 :            :   Copyright (C) 2001 by Andreas Gruenbacher <a.gruenbacher@computer.org>
       7                 :            :   Copyright (C) 2001 SGI - Silicon Graphics, Inc <linux-xfs@oss.sgi.com>
       8                 :            :   Copyright (c) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com>
       9                 :            :  */
      10                 :            : #include <linux/fs.h>
      11                 :            : #include <linux/slab.h>
      12                 :            : #include <linux/file.h>
      13                 :            : #include <linux/xattr.h>
      14                 :            : #include <linux/mount.h>
      15                 :            : #include <linux/namei.h>
      16                 :            : #include <linux/security.h>
      17                 :            : #include <linux/evm.h>
      18                 :            : #include <linux/syscalls.h>
      19                 :            : #include <linux/export.h>
      20                 :            : #include <linux/fsnotify.h>
      21                 :            : #include <linux/audit.h>
      22                 :            : #include <linux/vmalloc.h>
      23                 :            : #include <linux/posix_acl_xattr.h>
      24                 :            : 
      25                 :            : #include <asm/uaccess.h>
      26                 :            : 
      27                 :            : /*
      28                 :            :  * Check permissions for extended attribute access.  This is a bit complicated
      29                 :            :  * because different namespaces have very different rules.
      30                 :            :  */
      31                 :            : static int
      32                 :          0 : xattr_permission(struct inode *inode, const char *name, int mask)
      33                 :            : {
      34                 :            :         /*
      35                 :            :          * We can never set or remove an extended attribute on a read-only
      36                 :            :          * filesystem  or on an immutable / append-only inode.
      37                 :            :          */
      38         [ +  + ]:       2855 :         if (mask & MAY_WRITE) {
      39         [ +  - ]:       2636 :                 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
      40                 :            :                         return -EPERM;
      41                 :            :         }
      42                 :            : 
      43                 :            :         /*
      44                 :            :          * No restriction for security.* and system.* from the VFS.  Decision
      45                 :            :          * on these is left to the underlying filesystem / security module.
      46                 :            :          */
      47 [ +  + ][ -  + ]:       2855 :         if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) ||
      48                 :       2770 :             !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
      49                 :            :                 return 0;
      50                 :            : 
      51                 :            :         /*
      52                 :            :          * The trusted.* namespace can only be accessed by privileged users.
      53                 :            :          */
      54         [ #  # ]:          0 :         if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) {
      55         [ #  # ]:          0 :                 if (!capable(CAP_SYS_ADMIN))
      56         [ #  # ]:          0 :                         return (mask & MAY_WRITE) ? -EPERM : -ENODATA;
      57                 :            :                 return 0;
      58                 :            :         }
      59                 :            : 
      60                 :            :         /*
      61                 :            :          * In the user.* namespace, only regular files and directories can have
      62                 :            :          * extended attributes. For sticky directories, only the owner and
      63                 :            :          * privileged users can write attributes.
      64                 :            :          */
      65         [ #  # ]:          0 :         if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) {
      66         [ #  # ]:          0 :                 if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode))
      67         [ #  # ]:          0 :                         return (mask & MAY_WRITE) ? -EPERM : -ENODATA;
      68 [ #  # ][ #  # ]:          0 :                 if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) &&
      69         [ #  # ]:          0 :                     (mask & MAY_WRITE) && !inode_owner_or_capable(inode))
      70                 :            :                         return -EPERM;
      71                 :            :         }
      72                 :            : 
      73                 :          0 :         return inode_permission(inode, mask);
      74                 :            : }
      75                 :            : 
      76                 :            : /**
      77                 :            :  *  __vfs_setxattr_noperm - perform setxattr operation without performing
      78                 :            :  *  permission checks.
      79                 :            :  *
      80                 :            :  *  @dentry - object to perform setxattr on
      81                 :            :  *  @name - xattr name to set
      82                 :            :  *  @value - value to set @name to
      83                 :            :  *  @size - size of @value
      84                 :            :  *  @flags - flags to pass into filesystem operations
      85                 :            :  *
      86                 :            :  *  returns the result of the internal setxattr or setsecurity operations.
      87                 :            :  *
      88                 :            :  *  This function requires the caller to lock the inode's i_mutex before it
      89                 :            :  *  is executed. It also assumes that the caller will make the appropriate
      90                 :            :  *  permission checks.
      91                 :            :  */
      92                 :          0 : int __vfs_setxattr_noperm(struct dentry *dentry, const char *name,
      93                 :            :                 const void *value, size_t size, int flags)
      94                 :            : {
      95                 :       2636 :         struct inode *inode = dentry->d_inode;
      96                 :            :         int error = -EOPNOTSUPP;
      97                 :       2636 :         int issec = !strncmp(name, XATTR_SECURITY_PREFIX,
      98                 :            :                                    XATTR_SECURITY_PREFIX_LEN);
      99                 :            : 
     100         [ -  + ]:       2636 :         if (issec)
     101                 :          0 :                 inode->i_flags &= ~S_NOSEC;
     102         [ +  - ]:       2636 :         if (inode->i_op->setxattr) {
     103                 :       2636 :                 error = inode->i_op->setxattr(dentry, name, value, size, flags);
     104         [ -  + ]:       2636 :                 if (!error) {
     105                 :            :                         fsnotify_xattr(dentry);
     106                 :          0 :                         security_inode_post_setxattr(dentry, name, value,
     107                 :            :                                                      size, flags);
     108                 :            :                 }
     109         [ #  # ]:          0 :         } else if (issec) {
     110                 :          0 :                 const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
     111                 :          0 :                 error = security_inode_setsecurity(inode, suffix, value,
     112                 :            :                                                    size, flags);
     113         [ #  # ]:          0 :                 if (!error)
     114                 :            :                         fsnotify_xattr(dentry);
     115                 :            :         }
     116                 :            : 
     117                 :       2636 :         return error;
     118                 :            : }
     119                 :            : 
     120                 :            : 
     121                 :            : int
     122                 :          0 : vfs_setxattr(struct dentry *dentry, const char *name, const void *value,
     123                 :            :                 size_t size, int flags)
     124                 :            : {
     125                 :       2636 :         struct inode *inode = dentry->d_inode;
     126                 :            :         int error;
     127                 :            : 
     128                 :       2636 :         error = xattr_permission(inode, name, MAY_WRITE);
     129         [ +  - ]:       2636 :         if (error)
     130                 :            :                 return error;
     131                 :            : 
     132                 :       2636 :         mutex_lock(&inode->i_mutex);
     133                 :       2636 :         error = security_inode_setxattr(dentry, name, value, size, flags);
     134         [ +  - ]:       2636 :         if (error)
     135                 :            :                 goto out;
     136                 :            : 
     137                 :       2636 :         error = __vfs_setxattr_noperm(dentry, name, value, size, flags);
     138                 :            : 
     139                 :            : out:
     140                 :       2636 :         mutex_unlock(&inode->i_mutex);
     141                 :       2636 :         return error;
     142                 :            : }
     143                 :            : EXPORT_SYMBOL_GPL(vfs_setxattr);
     144                 :            : 
     145                 :            : ssize_t
     146                 :          0 : xattr_getsecurity(struct inode *inode, const char *name, void *value,
     147                 :            :                         size_t size)
     148                 :            : {
     149                 :         85 :         void *buffer = NULL;
     150                 :            :         ssize_t len;
     151                 :            : 
     152         [ -  + ]:         85 :         if (!value || !size) {
     153                 :          0 :                 len = security_inode_getsecurity(inode, name, &buffer, false);
     154                 :          0 :                 goto out_noalloc;
     155                 :            :         }
     156                 :            : 
     157                 :         85 :         len = security_inode_getsecurity(inode, name, &buffer, true);
     158         [ -  + ]:         85 :         if (len < 0)
     159                 :            :                 return len;
     160         [ #  # ]:          0 :         if (size < len) {
     161                 :            :                 len = -ERANGE;
     162                 :            :                 goto out;
     163                 :            :         }
     164                 :          0 :         memcpy(value, buffer, len);
     165                 :            : out:
     166                 :          0 :         security_release_secctx(buffer, len);
     167                 :            : out_noalloc:
     168                 :          0 :         return len;
     169                 :            : }
     170                 :            : EXPORT_SYMBOL_GPL(xattr_getsecurity);
     171                 :            : 
     172                 :            : /*
     173                 :            :  * vfs_getxattr_alloc - allocate memory, if necessary, before calling getxattr
     174                 :            :  *
     175                 :            :  * Allocate memory, if not already allocated, or re-allocate correct size,
     176                 :            :  * before retrieving the extended attribute.
     177                 :            :  *
     178                 :            :  * Returns the result of alloc, if failed, or the getxattr operation.
     179                 :            :  */
     180                 :            : ssize_t
     181                 :          0 : vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
     182                 :            :                    size_t xattr_size, gfp_t flags)
     183                 :            : {
     184                 :          0 :         struct inode *inode = dentry->d_inode;
     185                 :          0 :         char *value = *xattr_value;
     186                 :            :         int error;
     187                 :            : 
     188                 :          0 :         error = xattr_permission(inode, name, MAY_READ);
     189         [ #  # ]:          0 :         if (error)
     190                 :            :                 return error;
     191                 :            : 
     192         [ #  # ]:          0 :         if (!inode->i_op->getxattr)
     193                 :            :                 return -EOPNOTSUPP;
     194                 :            : 
     195                 :          0 :         error = inode->i_op->getxattr(dentry, name, NULL, 0);
     196         [ #  # ]:          0 :         if (error < 0)
     197                 :            :                 return error;
     198                 :            : 
     199         [ #  # ]:          0 :         if (!value || (error > xattr_size)) {
     200                 :          0 :                 value = krealloc(*xattr_value, error + 1, flags);
     201         [ #  # ]:          0 :                 if (!value)
     202                 :            :                         return -ENOMEM;
     203         [ #  # ]:          0 :                 memset(value, 0, error + 1);
     204                 :            :         }
     205                 :            : 
     206                 :          0 :         error = inode->i_op->getxattr(dentry, name, value, error);
     207                 :          0 :         *xattr_value = value;
     208                 :          0 :         return error;
     209                 :            : }
     210                 :            : 
     211                 :            : /* Compare an extended attribute value with the given value */
     212                 :          0 : int vfs_xattr_cmp(struct dentry *dentry, const char *xattr_name,
     213                 :            :                   const char *value, size_t size, gfp_t flags)
     214                 :            : {
     215                 :          0 :         char *xattr_value = NULL;
     216                 :            :         int rc;
     217                 :            : 
     218                 :          0 :         rc = vfs_getxattr_alloc(dentry, xattr_name, &xattr_value, 0, flags);
     219         [ #  # ]:          0 :         if (rc < 0)
     220                 :            :                 return rc;
     221                 :            : 
     222 [ #  # ][ #  # ]:          0 :         if ((rc != size) || (memcmp(xattr_value, value, rc) != 0))
     223                 :            :                 rc = -EINVAL;
     224                 :            :         else
     225                 :            :                 rc = 0;
     226                 :          0 :         kfree(xattr_value);
     227                 :          0 :         return rc;
     228                 :            : }
     229                 :            : 
     230                 :            : ssize_t
     231                 :          0 : vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
     232                 :            : {
     233                 :        219 :         struct inode *inode = dentry->d_inode;
     234                 :            :         int error;
     235                 :            : 
     236                 :        219 :         error = xattr_permission(inode, name, MAY_READ);
     237         [ +  - ]:        219 :         if (error)
     238                 :            :                 return error;
     239                 :            : 
     240                 :        219 :         error = security_inode_getxattr(dentry, name);
     241         [ +  - ]:        219 :         if (error)
     242                 :            :                 return error;
     243                 :            : 
     244         [ +  + ]:        219 :         if (!strncmp(name, XATTR_SECURITY_PREFIX,
     245                 :            :                                 XATTR_SECURITY_PREFIX_LEN)) {
     246                 :         85 :                 const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
     247                 :         85 :                 int ret = xattr_getsecurity(inode, suffix, value, size);
     248                 :            :                 /*
     249                 :            :                  * Only overwrite the return value if a security module
     250                 :            :                  * is actually active.
     251                 :            :                  */
     252            [ + ]:         85 :                 if (ret == -EOPNOTSUPP)
     253                 :            :                         goto nolsm;
     254                 :            :                 return ret;
     255                 :            :         }
     256                 :            : nolsm:
     257         [ +  - ]:        438 :         if (inode->i_op->getxattr)
     258                 :        219 :                 error = inode->i_op->getxattr(dentry, name, value, size);
     259                 :            :         else
     260                 :            :                 error = -EOPNOTSUPP;
     261                 :            : 
     262                 :        219 :         return error;
     263                 :            : }
     264                 :            : EXPORT_SYMBOL_GPL(vfs_getxattr);
     265                 :            : 
     266                 :            : ssize_t
     267                 :          0 : vfs_listxattr(struct dentry *d, char *list, size_t size)
     268                 :            : {
     269                 :            :         ssize_t error;
     270                 :            : 
     271                 :          0 :         error = security_inode_listxattr(d);
     272         [ #  # ]:          0 :         if (error)
     273                 :            :                 return error;
     274                 :            :         error = -EOPNOTSUPP;
     275         [ #  # ]:          0 :         if (d->d_inode->i_op->listxattr) {
     276                 :          0 :                 error = d->d_inode->i_op->listxattr(d, list, size);
     277                 :            :         } else {
     278                 :          0 :                 error = security_inode_listsecurity(d->d_inode, list, size);
     279         [ #  # ]:          0 :                 if (size && error > size)
     280                 :            :                         error = -ERANGE;
     281                 :            :         }
     282                 :          0 :         return error;
     283                 :            : }
     284                 :            : EXPORT_SYMBOL_GPL(vfs_listxattr);
     285                 :            : 
     286                 :            : int
     287                 :          0 : vfs_removexattr(struct dentry *dentry, const char *name)
     288                 :            : {
     289                 :          0 :         struct inode *inode = dentry->d_inode;
     290                 :            :         int error;
     291                 :            : 
     292         [ #  # ]:          0 :         if (!inode->i_op->removexattr)
     293                 :            :                 return -EOPNOTSUPP;
     294                 :            : 
     295                 :          0 :         error = xattr_permission(inode, name, MAY_WRITE);
     296         [ #  # ]:          0 :         if (error)
     297                 :            :                 return error;
     298                 :            : 
     299                 :          0 :         mutex_lock(&inode->i_mutex);
     300                 :          0 :         error = security_inode_removexattr(dentry, name);
     301         [ #  # ]:          0 :         if (error) {
     302                 :          0 :                 mutex_unlock(&inode->i_mutex);
     303                 :          0 :                 return error;
     304                 :            :         }
     305                 :            : 
     306                 :          0 :         error = inode->i_op->removexattr(dentry, name);
     307                 :          0 :         mutex_unlock(&inode->i_mutex);
     308                 :            : 
     309         [ #  # ]:          0 :         if (!error) {
     310                 :            :                 fsnotify_xattr(dentry);
     311                 :            :                 evm_inode_post_removexattr(dentry, name);
     312                 :            :         }
     313                 :          0 :         return error;
     314                 :            : }
     315                 :            : EXPORT_SYMBOL_GPL(vfs_removexattr);
     316                 :            : 
     317                 :            : 
     318                 :            : /*
     319                 :            :  * Extended attribute SET operations
     320                 :            :  */
     321                 :            : static long
     322                 :          0 : setxattr(struct dentry *d, const char __user *name, const void __user *value,
     323                 :            :          size_t size, int flags)
     324                 :            : {
     325                 :            :         int error;
     326                 :            :         void *kvalue = NULL;
     327                 :            :         void *vvalue = NULL;    /* If non-NULL, we used vmalloc() */
     328                 :            :         char kname[XATTR_NAME_MAX + 1];
     329                 :            : 
     330         [ +  - ]:       2636 :         if (flags & ~(XATTR_CREATE|XATTR_REPLACE))
     331                 :            :                 return -EINVAL;
     332                 :            : 
     333                 :       2636 :         error = strncpy_from_user(kname, name, sizeof(kname));
     334         [ -  + ]:       2636 :         if (error == 0 || error == sizeof(kname))
     335                 :            :                 error = -ERANGE;
     336         [ +  - ]:       2636 :         if (error < 0)
     337                 :            :                 return error;
     338                 :            : 
     339         [ +  - ]:       2636 :         if (size) {
     340            [ + ]:       2636 :                 if (size > XATTR_SIZE_MAX)
     341                 :            :                         return -E2BIG;
     342                 :            :                 kvalue = kmalloc(size, GFP_KERNEL | __GFP_NOWARN);
     343         [ -  + ]:       2636 :                 if (!kvalue) {
     344                 :          0 :                         vvalue = vmalloc(size);
     345         [ #  # ]:          0 :                         if (!vvalue)
     346                 :            :                                 return -ENOMEM;
     347                 :            :                         kvalue = vvalue;
     348                 :            :                 }
     349         [ +  - ]:       2636 :                 if (copy_from_user(kvalue, value, size)) {
     350                 :            :                         error = -EFAULT;
     351                 :            :                         goto out;
     352                 :            :                 }
     353 [ -  + ][ #  # ]:       2636 :                 if ((strcmp(kname, XATTR_NAME_POSIX_ACL_ACCESS) == 0) ||
     354                 :          0 :                     (strcmp(kname, XATTR_NAME_POSIX_ACL_DEFAULT) == 0))
     355                 :       2636 :                         posix_acl_fix_xattr_from_user(kvalue, size);
     356                 :            :         }
     357                 :            : 
     358                 :       2636 :         error = vfs_setxattr(d, kname, kvalue, size, flags);
     359                 :            : out:
     360         [ -  + ]:       2636 :         if (vvalue)
     361                 :          0 :                 vfree(vvalue);
     362                 :            :         else
     363                 :       2636 :                 kfree(kvalue);
     364                 :       2636 :         return error;
     365                 :            : }
     366                 :            : 
     367                 :          0 : SYSCALL_DEFINE5(setxattr, const char __user *, pathname,
     368                 :            :                 const char __user *, name, const void __user *, value,
     369                 :            :                 size_t, size, int, flags)
     370                 :            : {
     371                 :            :         struct path path;
     372                 :            :         int error;
     373                 :            :         unsigned int lookup_flags = LOOKUP_FOLLOW;
     374                 :            : retry:
     375                 :          0 :         error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
     376         [ #  # ]:          0 :         if (error)
     377                 :            :                 return error;
     378                 :          0 :         error = mnt_want_write(path.mnt);
     379         [ #  # ]:          0 :         if (!error) {
     380                 :          0 :                 error = setxattr(path.dentry, name, value, size, flags);
     381                 :          0 :                 mnt_drop_write(path.mnt);
     382                 :            :         }
     383                 :          0 :         path_put(&path);
     384         [ #  # ]:          0 :         if (retry_estale(error, lookup_flags)) {
     385                 :            :                 lookup_flags |= LOOKUP_REVAL;
     386                 :            :                 goto retry;
     387                 :            :         }
     388                 :            :         return error;
     389                 :            : }
     390                 :            : 
     391                 :          0 : SYSCALL_DEFINE5(lsetxattr, const char __user *, pathname,
     392                 :            :                 const char __user *, name, const void __user *, value,
     393                 :            :                 size_t, size, int, flags)
     394                 :            : {
     395                 :            :         struct path path;
     396                 :            :         int error;
     397                 :            :         unsigned int lookup_flags = 0;
     398                 :            : retry:
     399                 :          0 :         error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
     400         [ #  # ]:          0 :         if (error)
     401                 :            :                 return error;
     402                 :          0 :         error = mnt_want_write(path.mnt);
     403         [ #  # ]:          0 :         if (!error) {
     404                 :          0 :                 error = setxattr(path.dentry, name, value, size, flags);
     405                 :          0 :                 mnt_drop_write(path.mnt);
     406                 :            :         }
     407                 :          0 :         path_put(&path);
     408         [ #  # ]:          0 :         if (retry_estale(error, lookup_flags)) {
     409                 :            :                 lookup_flags |= LOOKUP_REVAL;
     410                 :            :                 goto retry;
     411                 :            :         }
     412                 :            :         return error;
     413                 :            : }
     414                 :            : 
     415                 :          0 : SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name,
     416                 :            :                 const void __user *,value, size_t, size, int, flags)
     417                 :            : {
     418                 :       2636 :         struct fd f = fdget(fd);
     419                 :            :         struct dentry *dentry;
     420                 :            :         int error = -EBADF;
     421                 :            : 
     422         [ +  - ]:       2636 :         if (!f.file)
     423                 :            :                 return error;
     424                 :       2636 :         dentry = f.file->f_path.dentry;
     425                 :            :         audit_inode(NULL, dentry, 0);
     426                 :       2636 :         error = mnt_want_write_file(f.file);
     427         [ +  - ]:       2636 :         if (!error) {
     428                 :       2636 :                 error = setxattr(dentry, name, value, size, flags);
     429                 :       2636 :                 mnt_drop_write_file(f.file);
     430                 :            :         }
     431                 :            :         fdput(f);
     432                 :            :         return error;
     433                 :            : }
     434                 :            : 
     435                 :            : /*
     436                 :            :  * Extended attribute GET operations
     437                 :            :  */
     438                 :            : static ssize_t
     439                 :          0 : getxattr(struct dentry *d, const char __user *name, void __user *value,
     440                 :            :          size_t size)
     441                 :            : {
     442                 :            :         ssize_t error;
     443                 :            :         void *kvalue = NULL;
     444                 :            :         void *vvalue = NULL;
     445                 :            :         char kname[XATTR_NAME_MAX + 1];
     446                 :            : 
     447                 :        219 :         error = strncpy_from_user(kname, name, sizeof(kname));
     448         [ -  + ]:        219 :         if (error == 0 || error == sizeof(kname))
     449                 :            :                 error = -ERANGE;
     450         [ +  - ]:        219 :         if (error < 0)
     451                 :            :                 return error;
     452                 :            : 
     453            [ + ]:        219 :         if (size) {
     454         [ -  + ]:        354 :                 if (size > XATTR_SIZE_MAX)
     455                 :            :                         size = XATTR_SIZE_MAX;
     456                 :            :                 kvalue = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
     457         [ -  + ]:        135 :                 if (!kvalue) {
     458                 :          0 :                         vvalue = vmalloc(size);
     459         [ #  # ]:          0 :                         if (!vvalue)
     460                 :            :                                 return -ENOMEM;
     461                 :            :                         kvalue = vvalue;
     462                 :            :                 }
     463                 :            :         }
     464                 :            : 
     465                 :          0 :         error = vfs_getxattr(d, kname, kvalue, size);
     466         [ -  + ]:        219 :         if (error > 0) {
     467 [ #  # ][ #  # ]:          0 :                 if ((strcmp(kname, XATTR_NAME_POSIX_ACL_ACCESS) == 0) ||
     468                 :          0 :                     (strcmp(kname, XATTR_NAME_POSIX_ACL_DEFAULT) == 0))
     469                 :          0 :                         posix_acl_fix_xattr_to_user(kvalue, size);
     470 [ #  # ][ #  # ]:          0 :                 if (size && copy_to_user(value, kvalue, error))
     471                 :            :                         error = -EFAULT;
     472         [ -  + ]:        219 :         } else if (error == -ERANGE && size >= XATTR_SIZE_MAX) {
     473                 :            :                 /* The file system tried to returned a value bigger
     474                 :            :                    than XATTR_SIZE_MAX bytes. Not possible. */
     475                 :            :                 error = -E2BIG;
     476                 :            :         }
     477         [ -  + ]:        219 :         if (vvalue)
     478                 :          0 :                 vfree(vvalue);
     479                 :            :         else
     480                 :        219 :                 kfree(kvalue);
     481                 :        219 :         return error;
     482                 :            : }
     483                 :            : 
     484                 :        109 : SYSCALL_DEFINE4(getxattr, const char __user *, pathname,
     485                 :            :                 const char __user *, name, void __user *, value, size_t, size)
     486                 :            : {
     487                 :            :         struct path path;
     488                 :            :         ssize_t error;
     489                 :            :         unsigned int lookup_flags = LOOKUP_FOLLOW;
     490                 :            : retry:
     491                 :        109 :         error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
     492         [ +  - ]:        109 :         if (error)
     493                 :            :                 return error;
     494                 :        109 :         error = getxattr(path.dentry, name, value, size);
     495                 :        109 :         path_put(&path);
     496         [ -  - ]:        109 :         if (retry_estale(error, lookup_flags)) {
     497                 :            :                 lookup_flags |= LOOKUP_REVAL;
     498                 :            :                 goto retry;
     499                 :            :         }
     500                 :            :         return error;
     501                 :            : }
     502                 :            : 
     503                 :         85 : SYSCALL_DEFINE4(lgetxattr, const char __user *, pathname,
     504                 :            :                 const char __user *, name, void __user *, value, size_t, size)
     505                 :            : {
     506                 :            :         struct path path;
     507                 :            :         ssize_t error;
     508                 :            :         unsigned int lookup_flags = 0;
     509                 :            : retry:
     510                 :         85 :         error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
     511         [ +  - ]:         85 :         if (error)
     512                 :            :                 return error;
     513                 :         85 :         error = getxattr(path.dentry, name, value, size);
     514                 :         85 :         path_put(&path);
     515         [ -  - ]:         85 :         if (retry_estale(error, lookup_flags)) {
     516                 :            :                 lookup_flags |= LOOKUP_REVAL;
     517                 :            :                 goto retry;
     518                 :            :         }
     519                 :            :         return error;
     520                 :            : }
     521                 :            : 
     522                 :          0 : SYSCALL_DEFINE4(fgetxattr, int, fd, const char __user *, name,
     523                 :            :                 void __user *, value, size_t, size)
     524                 :            : {
     525                 :         25 :         struct fd f = fdget(fd);
     526                 :            :         ssize_t error = -EBADF;
     527                 :            : 
     528         [ +  - ]:         25 :         if (!f.file)
     529                 :            :                 return error;
     530                 :         25 :         audit_inode(NULL, f.file->f_path.dentry, 0);
     531                 :         25 :         error = getxattr(f.file->f_path.dentry, name, value, size);
     532                 :            :         fdput(f);
     533                 :            :         return error;
     534                 :            : }
     535                 :            : 
     536                 :            : /*
     537                 :            :  * Extended attribute LIST operations
     538                 :            :  */
     539                 :            : static ssize_t
     540                 :          0 : listxattr(struct dentry *d, char __user *list, size_t size)
     541                 :            : {
     542                 :            :         ssize_t error;
     543                 :            :         char *klist = NULL;
     544                 :            :         char *vlist = NULL;     /* If non-NULL, we used vmalloc() */
     545                 :            : 
     546         [ #  # ]:          0 :         if (size) {
     547         [ #  # ]:          0 :                 if (size > XATTR_LIST_MAX)
     548                 :            :                         size = XATTR_LIST_MAX;
     549                 :            :                 klist = kmalloc(size, __GFP_NOWARN | GFP_KERNEL);
     550         [ #  # ]:          0 :                 if (!klist) {
     551                 :          0 :                         vlist = vmalloc(size);
     552         [ #  # ]:          0 :                         if (!vlist)
     553                 :            :                                 return -ENOMEM;
     554                 :            :                         klist = vlist;
     555                 :            :                 }
     556                 :            :         }
     557                 :            : 
     558                 :          0 :         error = vfs_listxattr(d, klist, size);
     559         [ #  # ]:          0 :         if (error > 0) {
     560 [ #  # ][ #  # ]:          0 :                 if (size && copy_to_user(list, klist, error))
     561                 :            :                         error = -EFAULT;
     562         [ #  # ]:          0 :         } else if (error == -ERANGE && size >= XATTR_LIST_MAX) {
     563                 :            :                 /* The file system tried to returned a list bigger
     564                 :            :                    than XATTR_LIST_MAX bytes. Not possible. */
     565                 :            :                 error = -E2BIG;
     566                 :            :         }
     567         [ #  # ]:          0 :         if (vlist)
     568                 :          0 :                 vfree(vlist);
     569                 :            :         else
     570                 :          0 :                 kfree(klist);
     571                 :          0 :         return error;
     572                 :            : }
     573                 :            : 
     574                 :          0 : SYSCALL_DEFINE3(listxattr, const char __user *, pathname, char __user *, list,
     575                 :            :                 size_t, size)
     576                 :            : {
     577                 :            :         struct path path;
     578                 :            :         ssize_t error;
     579                 :            :         unsigned int lookup_flags = LOOKUP_FOLLOW;
     580                 :            : retry:
     581                 :          0 :         error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
     582         [ #  # ]:          0 :         if (error)
     583                 :            :                 return error;
     584                 :          0 :         error = listxattr(path.dentry, list, size);
     585                 :          0 :         path_put(&path);
     586         [ #  # ]:          0 :         if (retry_estale(error, lookup_flags)) {
     587                 :            :                 lookup_flags |= LOOKUP_REVAL;
     588                 :            :                 goto retry;
     589                 :            :         }
     590                 :            :         return error;
     591                 :            : }
     592                 :            : 
     593                 :          0 : SYSCALL_DEFINE3(llistxattr, const char __user *, pathname, char __user *, list,
     594                 :            :                 size_t, size)
     595                 :            : {
     596                 :            :         struct path path;
     597                 :            :         ssize_t error;
     598                 :            :         unsigned int lookup_flags = 0;
     599                 :            : retry:
     600                 :          0 :         error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
     601         [ #  # ]:          0 :         if (error)
     602                 :            :                 return error;
     603                 :          0 :         error = listxattr(path.dentry, list, size);
     604                 :          0 :         path_put(&path);
     605         [ #  # ]:          0 :         if (retry_estale(error, lookup_flags)) {
     606                 :            :                 lookup_flags |= LOOKUP_REVAL;
     607                 :            :                 goto retry;
     608                 :            :         }
     609                 :            :         return error;
     610                 :            : }
     611                 :            : 
     612                 :          0 : SYSCALL_DEFINE3(flistxattr, int, fd, char __user *, list, size_t, size)
     613                 :            : {
     614                 :          0 :         struct fd f = fdget(fd);
     615                 :            :         ssize_t error = -EBADF;
     616                 :            : 
     617         [ #  # ]:          0 :         if (!f.file)
     618                 :            :                 return error;
     619                 :          0 :         audit_inode(NULL, f.file->f_path.dentry, 0);
     620                 :          0 :         error = listxattr(f.file->f_path.dentry, list, size);
     621                 :            :         fdput(f);
     622                 :            :         return error;
     623                 :            : }
     624                 :            : 
     625                 :            : /*
     626                 :            :  * Extended attribute REMOVE operations
     627                 :            :  */
     628                 :            : static long
     629                 :          0 : removexattr(struct dentry *d, const char __user *name)
     630                 :            : {
     631                 :            :         int error;
     632                 :            :         char kname[XATTR_NAME_MAX + 1];
     633                 :            : 
     634                 :          0 :         error = strncpy_from_user(kname, name, sizeof(kname));
     635         [ #  # ]:          0 :         if (error == 0 || error == sizeof(kname))
     636                 :            :                 error = -ERANGE;
     637         [ #  # ]:          0 :         if (error < 0)
     638                 :            :                 return error;
     639                 :            : 
     640                 :          0 :         return vfs_removexattr(d, kname);
     641                 :            : }
     642                 :            : 
     643                 :          0 : SYSCALL_DEFINE2(removexattr, const char __user *, pathname,
     644                 :            :                 const char __user *, name)
     645                 :            : {
     646                 :            :         struct path path;
     647                 :            :         int error;
     648                 :            :         unsigned int lookup_flags = LOOKUP_FOLLOW;
     649                 :            : retry:
     650                 :          0 :         error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
     651         [ #  # ]:          0 :         if (error)
     652                 :            :                 return error;
     653                 :          0 :         error = mnt_want_write(path.mnt);
     654         [ #  # ]:          0 :         if (!error) {
     655                 :          0 :                 error = removexattr(path.dentry, name);
     656                 :          0 :                 mnt_drop_write(path.mnt);
     657                 :            :         }
     658                 :          0 :         path_put(&path);
     659         [ #  # ]:          0 :         if (retry_estale(error, lookup_flags)) {
     660                 :            :                 lookup_flags |= LOOKUP_REVAL;
     661                 :            :                 goto retry;
     662                 :            :         }
     663                 :            :         return error;
     664                 :            : }
     665                 :            : 
     666                 :          0 : SYSCALL_DEFINE2(lremovexattr, const char __user *, pathname,
     667                 :            :                 const char __user *, name)
     668                 :            : {
     669                 :            :         struct path path;
     670                 :            :         int error;
     671                 :            :         unsigned int lookup_flags = 0;
     672                 :            : retry:
     673                 :          0 :         error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
     674         [ #  # ]:          0 :         if (error)
     675                 :            :                 return error;
     676                 :          0 :         error = mnt_want_write(path.mnt);
     677         [ #  # ]:          0 :         if (!error) {
     678                 :          0 :                 error = removexattr(path.dentry, name);
     679                 :          0 :                 mnt_drop_write(path.mnt);
     680                 :            :         }
     681                 :          0 :         path_put(&path);
     682         [ #  # ]:          0 :         if (retry_estale(error, lookup_flags)) {
     683                 :            :                 lookup_flags |= LOOKUP_REVAL;
     684                 :            :                 goto retry;
     685                 :            :         }
     686                 :            :         return error;
     687                 :            : }
     688                 :            : 
     689                 :          0 : SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name)
     690                 :            : {
     691                 :          0 :         struct fd f = fdget(fd);
     692                 :            :         struct dentry *dentry;
     693                 :            :         int error = -EBADF;
     694                 :            : 
     695         [ #  # ]:          0 :         if (!f.file)
     696                 :            :                 return error;
     697                 :          0 :         dentry = f.file->f_path.dentry;
     698                 :            :         audit_inode(NULL, dentry, 0);
     699                 :          0 :         error = mnt_want_write_file(f.file);
     700         [ #  # ]:          0 :         if (!error) {
     701                 :          0 :                 error = removexattr(dentry, name);
     702                 :          0 :                 mnt_drop_write_file(f.file);
     703                 :            :         }
     704                 :            :         fdput(f);
     705                 :            :         return error;
     706                 :            : }
     707                 :            : 
     708                 :            : 
     709                 :            : static const char *
     710                 :            : strcmp_prefix(const char *a, const char *a_prefix)
     711                 :            : {
     712 [ +  + ][ -  + ]:     219617 :         while (*a_prefix && *a == *a_prefix) {
     713                 :          0 :                 a++;
     714                 :          0 :                 a_prefix++;
     715                 :            :         }
     716         [ -  + ]:     219617 :         return *a_prefix ? NULL : a;
     717                 :            : }
     718                 :            : 
     719                 :            : /*
     720                 :            :  * In order to implement different sets of xattr operations for each xattr
     721                 :            :  * prefix with the generic xattr API, a filesystem should create a
     722                 :            :  * null-terminated array of struct xattr_handler (one for each prefix) and
     723                 :            :  * hang a pointer to it off of the s_xattr field of the superblock.
     724                 :            :  *
     725                 :            :  * The generic_fooxattr() functions will use this list to dispatch xattr
     726                 :            :  * operations to the correct xattr_handler.
     727                 :            :  */
     728                 :            : #define for_each_xattr_handler(handlers, handler)               \
     729                 :            :                 for ((handler) = *(handlers)++;                 \
     730                 :            :                         (handler) != NULL;                      \
     731                 :            :                         (handler) = *(handlers)++)
     732                 :            : 
     733                 :            : /*
     734                 :            :  * Find the xattr_handler with the matching prefix.
     735                 :            :  */
     736                 :            : static const struct xattr_handler *
     737                 :          0 : xattr_resolve_name(const struct xattr_handler **handlers, const char **name)
     738                 :            : {
     739                 :            :         const struct xattr_handler *handler;
     740                 :            : 
     741            [ + ]:     109929 :         if (!*name)
     742                 :            :                 return NULL;
     743                 :            : 
     744         [ +  + ]:     439344 :         for_each_xattr_handler(handlers, handler) {
     745                 :     219617 :                 const char *n = strcmp_prefix(*name, handler->prefix);
     746         [ +  + ]:     219617 :                 if (n) {
     747                 :          0 :                         *name = n;
     748                 :          9 :                         break;
     749                 :            :                 }
     750                 :            :         }
     751                 :     109807 :         return handler;
     752                 :            : }
     753                 :            : 
     754                 :            : /*
     755                 :            :  * Find the handler for the prefix and dispatch its get() operation.
     756                 :            :  */
     757                 :            : ssize_t
     758                 :          0 : generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size)
     759                 :            : {
     760                 :            :         const struct xattr_handler *handler;
     761                 :            : 
     762                 :     107238 :         handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
     763         [ -  + ]:     107171 :         if (!handler)
     764                 :            :                 return -EOPNOTSUPP;
     765                 :          0 :         return handler->get(dentry, name, buffer, size, handler->flags);
     766                 :            : }
     767                 :            : 
     768                 :            : /*
     769                 :            :  * Combine the results of the list() operation from every xattr_handler in the
     770                 :            :  * list.
     771                 :            :  */
     772                 :            : ssize_t
     773                 :          0 : generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
     774                 :            : {
     775                 :          0 :         const struct xattr_handler *handler, **handlers = dentry->d_sb->s_xattr;
     776                 :            :         unsigned int size = 0;
     777                 :            : 
     778         [ #  # ]:          0 :         if (!buffer) {
     779         [ #  # ]:          0 :                 for_each_xattr_handler(handlers, handler) {
     780                 :          0 :                         size += handler->list(dentry, NULL, 0, NULL, 0,
     781                 :            :                                               handler->flags);
     782                 :            :                 }
     783                 :            :         } else {
     784                 :            :                 char *buf = buffer;
     785                 :            : 
     786         [ #  # ]:          0 :                 for_each_xattr_handler(handlers, handler) {
     787                 :          0 :                         size = handler->list(dentry, buf, buffer_size,
     788                 :            :                                              NULL, 0, handler->flags);
     789         [ #  # ]:          0 :                         if (size > buffer_size)
     790                 :            :                                 return -ERANGE;
     791                 :          0 :                         buf += size;
     792                 :          0 :                         buffer_size -= size;
     793                 :            :                 }
     794                 :          0 :                 size = buf - buffer;
     795                 :            :         }
     796                 :          0 :         return size;
     797                 :            : }
     798                 :            : 
     799                 :            : /*
     800                 :            :  * Find the handler for the prefix and dispatch its set() operation.
     801                 :            :  */
     802                 :            : int
     803                 :          0 : generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags)
     804                 :            : {
     805                 :            :         const struct xattr_handler *handler;
     806                 :            : 
     807         [ -  + ]:       2636 :         if (size == 0)
     808                 :            :                 value = "";  /* empty EA, do not remove */
     809                 :       2636 :         handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
     810         [ -  + ]:       2636 :         if (!handler)
     811                 :            :                 return -EOPNOTSUPP;
     812                 :          0 :         return handler->set(dentry, name, value, size, flags, handler->flags);
     813                 :            : }
     814                 :            : 
     815                 :            : /*
     816                 :            :  * Find the handler for the prefix and dispatch its set() operation to remove
     817                 :            :  * any associated extended attribute.
     818                 :            :  */
     819                 :            : int
     820                 :          0 : generic_removexattr(struct dentry *dentry, const char *name)
     821                 :            : {
     822                 :            :         const struct xattr_handler *handler;
     823                 :            : 
     824                 :          0 :         handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
     825         [ #  # ]:          0 :         if (!handler)
     826                 :            :                 return -EOPNOTSUPP;
     827                 :          0 :         return handler->set(dentry, name, NULL, 0,
     828                 :            :                             XATTR_REPLACE, handler->flags);
     829                 :            : }
     830                 :            : 
     831                 :            : EXPORT_SYMBOL(generic_getxattr);
     832                 :            : EXPORT_SYMBOL(generic_listxattr);
     833                 :            : EXPORT_SYMBOL(generic_setxattr);
     834                 :            : EXPORT_SYMBOL(generic_removexattr);
     835                 :            : 
     836                 :            : /*
     837                 :            :  * Allocate new xattr and copy in the value; but leave the name to callers.
     838                 :            :  */
     839                 :          0 : struct simple_xattr *simple_xattr_alloc(const void *value, size_t size)
     840                 :            : {
     841                 :            :         struct simple_xattr *new_xattr;
     842                 :            :         size_t len;
     843                 :            : 
     844                 :            :         /* wrap around? */
     845                 :          0 :         len = sizeof(*new_xattr) + size;
     846         [ #  # ]:          0 :         if (len <= sizeof(*new_xattr))
     847                 :            :                 return NULL;
     848                 :            : 
     849                 :            :         new_xattr = kmalloc(len, GFP_KERNEL);
     850         [ #  # ]:          0 :         if (!new_xattr)
     851                 :            :                 return NULL;
     852                 :            : 
     853                 :          0 :         new_xattr->size = size;
     854                 :          0 :         memcpy(new_xattr->value, value, size);
     855                 :          0 :         return new_xattr;
     856                 :            : }
     857                 :            : 
     858                 :            : /*
     859                 :            :  * xattr GET operation for in-memory/pseudo filesystems
     860                 :            :  */
     861                 :          0 : int simple_xattr_get(struct simple_xattrs *xattrs, const char *name,
     862                 :            :                      void *buffer, size_t size)
     863                 :            : {
     864                 :            :         struct simple_xattr *xattr;
     865                 :            :         int ret = -ENODATA;
     866                 :            : 
     867                 :            :         spin_lock(&xattrs->lock);
     868         [ -  + ]:        236 :         list_for_each_entry(xattr, &xattrs->head, list) {
     869         [ #  # ]:          0 :                 if (strcmp(name, xattr->name))
     870                 :          0 :                         continue;
     871                 :            : 
     872                 :          0 :                 ret = xattr->size;
     873         [ #  # ]:          0 :                 if (buffer) {
     874         [ #  # ]:          0 :                         if (size < xattr->size)
     875                 :            :                                 ret = -ERANGE;
     876                 :            :                         else
     877                 :          0 :                                 memcpy(buffer, xattr->value, xattr->size);
     878                 :            :                 }
     879                 :            :                 break;
     880                 :            :         }
     881                 :            :         spin_unlock(&xattrs->lock);
     882                 :        236 :         return ret;
     883                 :            : }
     884                 :            : 
     885                 :          0 : static int __simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
     886                 :            :                               const void *value, size_t size, int flags)
     887                 :            : {
     888                 :            :         struct simple_xattr *xattr;
     889                 :            :         struct simple_xattr *new_xattr = NULL;
     890                 :            :         int err = 0;
     891                 :            : 
     892                 :            :         /* value == NULL means remove */
     893         [ #  # ]:          0 :         if (value) {
     894                 :          0 :                 new_xattr = simple_xattr_alloc(value, size);
     895         [ #  # ]:          0 :                 if (!new_xattr)
     896                 :            :                         return -ENOMEM;
     897                 :            : 
     898                 :          0 :                 new_xattr->name = kstrdup(name, GFP_KERNEL);
     899         [ #  # ]:          0 :                 if (!new_xattr->name) {
     900                 :          0 :                         kfree(new_xattr);
     901                 :          0 :                         return -ENOMEM;
     902                 :            :                 }
     903                 :            :         }
     904                 :            : 
     905                 :            :         spin_lock(&xattrs->lock);
     906         [ #  # ]:          0 :         list_for_each_entry(xattr, &xattrs->head, list) {
     907         [ #  # ]:          0 :                 if (!strcmp(name, xattr->name)) {
     908         [ #  # ]:          0 :                         if (flags & XATTR_CREATE) {
     909                 :            :                                 xattr = new_xattr;
     910                 :            :                                 err = -EEXIST;
     911         [ #  # ]:          0 :                         } else if (new_xattr) {
     912                 :          0 :                                 list_replace(&xattr->list, &new_xattr->list);
     913                 :            :                         } else {
     914                 :            :                                 list_del(&xattr->list);
     915                 :            :                         }
     916                 :            :                         goto out;
     917                 :            :                 }
     918                 :            :         }
     919         [ #  # ]:          0 :         if (flags & XATTR_REPLACE) {
     920                 :            :                 xattr = new_xattr;
     921                 :            :                 err = -ENODATA;
     922                 :            :         } else {
     923                 :          0 :                 list_add(&new_xattr->list, &xattrs->head);
     924                 :            :                 xattr = NULL;
     925                 :            :         }
     926                 :            : out:
     927                 :            :         spin_unlock(&xattrs->lock);
     928         [ #  # ]:          0 :         if (xattr) {
     929                 :          0 :                 kfree(xattr->name);
     930                 :          0 :                 kfree(xattr);
     931                 :            :         }
     932                 :          0 :         return err;
     933                 :            : 
     934                 :            : }
     935                 :            : 
     936                 :            : /**
     937                 :            :  * simple_xattr_set - xattr SET operation for in-memory/pseudo filesystems
     938                 :            :  * @xattrs: target simple_xattr list
     939                 :            :  * @name: name of the new extended attribute
     940                 :            :  * @value: value of the new xattr. If %NULL, will remove the attribute
     941                 :            :  * @size: size of the new xattr
     942                 :            :  * @flags: %XATTR_{CREATE|REPLACE}
     943                 :            :  *
     944                 :            :  * %XATTR_CREATE is set, the xattr shouldn't exist already; otherwise fails
     945                 :            :  * with -EEXIST.  If %XATTR_REPLACE is set, the xattr should exist;
     946                 :            :  * otherwise, fails with -ENODATA.
     947                 :            :  *
     948                 :            :  * Returns 0 on success, -errno on failure.
     949                 :            :  */
     950                 :          0 : int simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
     951                 :            :                      const void *value, size_t size, int flags)
     952                 :            : {
     953         [ #  # ]:          0 :         if (size == 0)
     954                 :            :                 value = ""; /* empty EA, do not remove */
     955                 :          0 :         return __simple_xattr_set(xattrs, name, value, size, flags);
     956                 :            : }
     957                 :            : 
     958                 :            : /*
     959                 :            :  * xattr REMOVE operation for in-memory/pseudo filesystems
     960                 :            :  */
     961                 :          0 : int simple_xattr_remove(struct simple_xattrs *xattrs, const char *name)
     962                 :            : {
     963                 :          0 :         return __simple_xattr_set(xattrs, name, NULL, 0, XATTR_REPLACE);
     964                 :            : }
     965                 :            : 
     966                 :            : static bool xattr_is_trusted(const char *name)
     967                 :            : {
     968                 :          0 :         return !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
     969                 :            : }
     970                 :            : 
     971                 :            : /*
     972                 :            :  * xattr LIST operation for in-memory/pseudo filesystems
     973                 :            :  */
     974                 :          0 : ssize_t simple_xattr_list(struct simple_xattrs *xattrs, char *buffer,
     975                 :            :                           size_t size)
     976                 :            : {
     977                 :          0 :         bool trusted = capable(CAP_SYS_ADMIN);
     978                 :            :         struct simple_xattr *xattr;
     979                 :            :         size_t used = 0;
     980                 :            : 
     981                 :            :         spin_lock(&xattrs->lock);
     982         [ #  # ]:          0 :         list_for_each_entry(xattr, &xattrs->head, list) {
     983                 :            :                 size_t len;
     984                 :            : 
     985                 :            :                 /* skip "trusted." attributes for unprivileged callers */
     986 [ #  # ][ #  # ]:          0 :                 if (!trusted && xattr_is_trusted(xattr->name))
     987                 :          0 :                         continue;
     988                 :            : 
     989                 :          0 :                 len = strlen(xattr->name) + 1;
     990                 :          0 :                 used += len;
     991         [ #  # ]:          0 :                 if (buffer) {
     992         [ #  # ]:          0 :                         if (size < used) {
     993                 :            :                                 used = -ERANGE;
     994                 :            :                                 break;
     995                 :            :                         }
     996                 :          0 :                         memcpy(buffer, xattr->name, len);
     997                 :          0 :                         buffer += len;
     998                 :            :                 }
     999                 :            :         }
    1000                 :            :         spin_unlock(&xattrs->lock);
    1001                 :            : 
    1002                 :          0 :         return used;
    1003                 :            : }
    1004                 :            : 
    1005                 :            : /*
    1006                 :            :  * Adds an extended attribute to the list
    1007                 :            :  */
    1008                 :          0 : void simple_xattr_list_add(struct simple_xattrs *xattrs,
    1009                 :            :                            struct simple_xattr *new_xattr)
    1010                 :            : {
    1011                 :            :         spin_lock(&xattrs->lock);
    1012                 :          0 :         list_add(&new_xattr->list, &xattrs->head);
    1013                 :            :         spin_unlock(&xattrs->lock);
    1014                 :          0 : }

Generated by: LCOV version 1.9