LCOV - code coverage report
Current view: top level - fs/xfs - xfs_xattr.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc4-xfsa @ Mon Jul 31 20:08:27 PDT 2023 Lines: 99 101 98.0 %
Date: 2023-07-31 20:08:27 Functions: 8 8 100.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * Copyright (C) 2008 Christoph Hellwig.
       4             :  * Portions Copyright (C) 2000-2008 Silicon Graphics, Inc.
       5             :  */
       6             : 
       7             : #include "xfs.h"
       8             : #include "xfs_shared.h"
       9             : #include "xfs_format.h"
      10             : #include "xfs_log_format.h"
      11             : #include "xfs_da_format.h"
      12             : #include "xfs_trans_resv.h"
      13             : #include "xfs_mount.h"
      14             : #include "xfs_inode.h"
      15             : #include "xfs_da_btree.h"
      16             : #include "xfs_attr.h"
      17             : #include "xfs_acl.h"
      18             : #include "xfs_log.h"
      19             : #include "xfs_xattr.h"
      20             : 
      21             : #include <linux/posix_acl_xattr.h>
      22             : 
      23             : /*
      24             :  * Get permission to use log-assisted atomic exchange of file extents.
      25             :  *
      26             :  * Callers must not be running any transactions or hold any inode locks, and
      27             :  * they must release the permission by calling xlog_drop_incompat_feat
      28             :  * when they're done.
      29             :  */
      30             : int
      31   139526706 : xfs_attr_grab_log_assist(
      32             :         struct xfs_mount        *mp)
      33             : {
      34   139526706 :         int                     error = 0;
      35             : 
      36             :         /*
      37             :          * Protect ourselves from an idle log clearing the logged xattrs log
      38             :          * incompat feature bit.
      39             :          */
      40   139526706 :         xlog_use_incompat_feat(mp->m_log, XLOG_INCOMPAT_FEAT_XATTRS);
      41             : 
      42             :         /*
      43             :          * If log-assisted xattrs are already enabled, the caller can use the
      44             :          * log assisted swap functions with the log-incompat reference we got.
      45             :          */
      46   279070168 :         if (xfs_sb_version_haslogxattrs(&mp->m_sb))
      47             :                 return 0;
      48             : 
      49             :         /* Enable log-assisted xattrs. */
      50      110536 :         error = xfs_add_incompat_log_feature(mp,
      51             :                         XFS_SB_FEAT_INCOMPAT_LOG_XATTRS);
      52      110540 :         if (error)
      53         101 :                 goto drop_incompat;
      54             : 
      55      110439 :         xfs_warn_mount(mp, XFS_OPSTATE_WARNED_LARP,
      56             :  "EXPERIMENTAL logged extended attributes feature in use. Use at your own risk!");
      57             : 
      58             :         return 0;
      59             : drop_incompat:
      60         101 :         xlog_drop_incompat_feat(mp->m_log, XLOG_INCOMPAT_FEAT_XATTRS);
      61         101 :         return error;
      62             : }
      63             : 
      64             : void
      65      363945 : xfs_attr_rele_log_assist(
      66             :         struct xfs_mount        *mp)
      67             : {
      68      363945 :         xlog_drop_incompat_feat(mp->m_log, XLOG_INCOMPAT_FEAT_XATTRS);
      69          98 : }
      70             : 
      71             : static inline bool
      72             : xfs_attr_want_log_assist(
      73             :         struct xfs_mount        *mp)
      74             : {
      75             : #ifdef DEBUG
      76             :         /* Logged xattrs require a V5 super for log_incompat */
      77   339395354 :         return xfs_has_crc(mp) && xfs_globals.larp;
      78             : #else
      79             :         return false;
      80             : #endif
      81             : }
      82             : 
      83             : /*
      84             :  * Set or remove an xattr, having grabbed the appropriate logging resources
      85             :  * prior to calling libxfs.
      86             :  */
      87             : int
      88   339469099 : xfs_attr_change(
      89             :         struct xfs_da_args      *args)
      90             : {
      91   339469099 :         struct xfs_mount        *mp = args->dp->i_mount;
      92   339469099 :         bool                    use_logging = false;
      93   339469099 :         int                     error;
      94             : 
      95   339469099 :         ASSERT(!(args->op_flags & XFS_DA_OP_LOGGED));
      96             : 
      97   678938198 :         if (xfs_attr_want_log_assist(mp)) {
      98          98 :                 error = xfs_attr_grab_log_assist(mp);
      99          98 :                 if (error)
     100             :                         return error;
     101             : 
     102          98 :                 args->op_flags |= XFS_DA_OP_LOGGED;
     103          98 :                 use_logging = true;
     104             :         }
     105             : 
     106   339469099 :         if (args->value)
     107   233431797 :                 args->op_flags &= ~XFS_DA_OP_REMOVE;
     108             :         else
     109   106037302 :                 args->op_flags |= XFS_DA_OP_REMOVE;
     110             : 
     111   339469099 :         error = xfs_attr_set(args);
     112             : 
     113   339464658 :         if (use_logging)
     114          98 :                 xfs_attr_rele_log_assist(mp);
     115             :         return error;
     116             : }
     117             : 
     118             : 
     119             : static int
     120    60810966 : xfs_xattr_get(const struct xattr_handler *handler, struct dentry *unused,
     121             :                 struct inode *inode, const char *name, void *value, size_t size)
     122             : {
     123    60810966 :         struct xfs_da_args      args = {
     124             :                 .dp             = XFS_I(inode),
     125    60810966 :                 .attr_filter    = handler->flags,
     126             :                 .name           = name,
     127             :                 .namelen        = strlen(name),
     128             :                 .value          = value,
     129             :                 .valuelen       = size,
     130    60810966 :                 .owner          = XFS_I(inode)->i_ino,
     131             :         };
     132    60810966 :         int                     error;
     133             : 
     134    60810966 :         error = xfs_attr_get(&args);
     135    60810355 :         if (error)
     136             :                 return error;
     137    25225117 :         return args.valuelen;
     138             : }
     139             : 
     140             : static int
     141   337501493 : xfs_xattr_set(const struct xattr_handler *handler,
     142             :               struct mnt_idmap *idmap, struct dentry *unused,
     143             :               struct inode *inode, const char *name, const void *value,
     144             :               size_t size, int flags)
     145             : {
     146   337501493 :         struct xfs_da_args      args = {
     147             :                 .dp             = XFS_I(inode),
     148   337501493 :                 .attr_filter    = handler->flags,
     149             :                 .attr_flags     = flags,
     150             :                 .name           = name,
     151             :                 .namelen        = strlen(name),
     152             :                 .value          = (void *)value,
     153             :                 .valuelen       = size,
     154   337501493 :                 .owner          = XFS_I(inode)->i_ino,
     155             :         };
     156   337501493 :         int                     error;
     157             : 
     158   337501493 :         error = xfs_attr_change(&args);
     159   337559438 :         if (!error && (handler->flags & XFS_ATTR_ROOT))
     160       83808 :                 xfs_forget_acl(inode, name);
     161   337559438 :         return error;
     162             : }
     163             : 
     164             : static const struct xattr_handler xfs_xattr_user_handler = {
     165             :         .prefix = XATTR_USER_PREFIX,
     166             :         .flags  = 0, /* no flags implies user namespace */
     167             :         .get    = xfs_xattr_get,
     168             :         .set    = xfs_xattr_set,
     169             : };
     170             : 
     171             : static const struct xattr_handler xfs_xattr_trusted_handler = {
     172             :         .prefix = XATTR_TRUSTED_PREFIX,
     173             :         .flags  = XFS_ATTR_ROOT,
     174             :         .get    = xfs_xattr_get,
     175             :         .set    = xfs_xattr_set,
     176             : };
     177             : 
     178             : static const struct xattr_handler xfs_xattr_security_handler = {
     179             :         .prefix = XATTR_SECURITY_PREFIX,
     180             :         .flags  = XFS_ATTR_SECURE,
     181             :         .get    = xfs_xattr_get,
     182             :         .set    = xfs_xattr_set,
     183             : };
     184             : 
     185             : const struct xattr_handler *xfs_xattr_handlers[] = {
     186             :         &xfs_xattr_user_handler,
     187             :         &xfs_xattr_trusted_handler,
     188             :         &xfs_xattr_security_handler,
     189             :         NULL
     190             : };
     191             : 
     192             : static void
     193  1650589051 : __xfs_xattr_put_listent(
     194             :         struct xfs_attr_list_context *context,
     195             :         char *prefix,
     196             :         int prefix_len,
     197             :         unsigned char *name,
     198             :         int namelen)
     199             : {
     200  1650589051 :         char *offset;
     201  1650589051 :         int arraytop;
     202             : 
     203  1650589051 :         if (context->count < 0 || context->seen_enough)
     204             :                 return;
     205             : 
     206  1650589049 :         if (!context->buffer)
     207   413072333 :                 goto compute_size;
     208             : 
     209  1237516716 :         arraytop = context->count + prefix_len + namelen + 1;
     210  1237516716 :         if (arraytop > context->firstu) {
     211           8 :                 context->count = -1; /* insufficient space */
     212           8 :                 context->seen_enough = 1;
     213           8 :                 return;
     214             :         }
     215  1237516708 :         offset = context->buffer + context->count;
     216  2475033416 :         memcpy(offset, prefix, prefix_len);
     217  1237516708 :         offset += prefix_len;
     218  1237516708 :         strncpy(offset, (char *)name, namelen);                 /* real name */
     219  1237516708 :         offset += namelen;
     220  1237516708 :         *offset = '\0';
     221             : 
     222  1650589041 : compute_size:
     223  1650589041 :         context->count += prefix_len + namelen + 1;
     224  1650589041 :         return;
     225             : }
     226             : 
     227             : static void
     228  1764974465 : xfs_xattr_put_listent(
     229             :         struct xfs_attr_list_context *context,
     230             :         int             flags,
     231             :         unsigned char   *name,
     232             :         int             namelen,
     233             :         void            *value,
     234             :         int             valuelen)
     235             : {
     236  1764974465 :         char *prefix;
     237  1764974465 :         int prefix_len;
     238             : 
     239  1764974465 :         ASSERT(context->count >= 0);
     240             : 
     241  1764974465 :         if (flags & XFS_ATTR_PARENT)
     242             :                 return;
     243             : 
     244  1648670687 :         if (flags & XFS_ATTR_ROOT) {
     245             : #ifdef CONFIG_XFS_POSIX_ACL
     246         830 :                 if (namelen == SGI_ACL_FILE_SIZE &&
     247           2 :                     strncmp(name, SGI_ACL_FILE,
     248             :                             SGI_ACL_FILE_SIZE) == 0) {
     249           2 :                         __xfs_xattr_put_listent(
     250             :                                         context, XATTR_SYSTEM_PREFIX,
     251             :                                         XATTR_SYSTEM_PREFIX_LEN,
     252             :                                         XATTR_POSIX_ACL_ACCESS,
     253             :                                         strlen(XATTR_POSIX_ACL_ACCESS));
     254         828 :                 } else if (namelen == SGI_ACL_DEFAULT_SIZE &&
     255           0 :                          strncmp(name, SGI_ACL_DEFAULT,
     256             :                                  SGI_ACL_DEFAULT_SIZE) == 0) {
     257           0 :                         __xfs_xattr_put_listent(
     258             :                                         context, XATTR_SYSTEM_PREFIX,
     259             :                                         XATTR_SYSTEM_PREFIX_LEN,
     260             :                                         XATTR_POSIX_ACL_DEFAULT,
     261             :                                         strlen(XATTR_POSIX_ACL_DEFAULT));
     262             :                 }
     263             : #endif
     264             : 
     265             :                 /*
     266             :                  * Only show root namespace entries if we are actually allowed to
     267             :                  * see them.
     268             :                  */
     269         830 :                 if (!capable(CAP_SYS_ADMIN))
     270             :                         return;
     271             : 
     272             :                 prefix = XATTR_TRUSTED_PREFIX;
     273             :                 prefix_len = XATTR_TRUSTED_PREFIX_LEN;
     274  1648669857 :         } else if (flags & XFS_ATTR_SECURE) {
     275             :                 prefix = XATTR_SECURITY_PREFIX;
     276             :                 prefix_len = XATTR_SECURITY_PREFIX_LEN;
     277             :         } else {
     278  1648674337 :                 prefix = XATTR_USER_PREFIX;
     279  1648674337 :                 prefix_len = XATTR_USER_PREFIX_LEN;
     280             :         }
     281             : 
     282  1648670687 :         __xfs_xattr_put_listent(context, prefix, prefix_len, name,
     283             :                                 namelen);
     284  1648670687 :         return;
     285             : }
     286             : 
     287             : ssize_t
     288   115944588 : xfs_vn_listxattr(
     289             :         struct dentry   *dentry,
     290             :         char            *data,
     291             :         size_t          size)
     292             : {
     293   115944588 :         struct xfs_attr_list_context context;
     294   115944588 :         struct inode    *inode = d_inode(dentry);
     295   115944588 :         int             error;
     296             : 
     297             :         /*
     298             :          * First read the regular on-disk attributes.
     299             :          */
     300   115944588 :         memset(&context, 0, sizeof(context));
     301   115944588 :         context.dp = XFS_I(inode);
     302   115944588 :         context.resynch = 1;
     303   115944588 :         context.buffer = size ? data : NULL;
     304   115944588 :         context.bufsize = size;
     305   115944588 :         context.firstu = context.bufsize;
     306   115944588 :         context.put_listent = xfs_xattr_put_listent;
     307             : 
     308   115944588 :         error = xfs_attr_list(&context);
     309   115960746 :         if (error)
     310           2 :                 return error;
     311   115960744 :         if (context.count < 0)
     312           8 :                 return -ERANGE;
     313             : 
     314             :         return context.count;
     315             : }

Generated by: LCOV version 1.14