LCOV - code coverage report
Current view: top level - fs/xfs - xfs_xattr.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-achx @ Mon Jul 31 20:08:12 PDT 2023 Lines: 100 102 98.0 %
Date: 2023-07-31 20:08:12 Functions: 9 9 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   227749403 : xfs_attr_grab_log_assist(
      32             :         struct xfs_mount        *mp)
      33             : {
      34   227749403 :         int                     error = 0;
      35             : 
      36             :         /*
      37             :          * Protect ourselves from an idle log clearing the logged xattrs log
      38             :          * incompat feature bit.
      39             :          */
      40   227749403 :         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   456064368 :         if (xfs_sb_version_haslogxattrs(&mp->m_sb))
      47             :                 return 0;
      48             : 
      49             :         /* Enable log-assisted xattrs. */
      50      162662 :         error = xfs_add_incompat_log_feature(mp,
      51             :                         XFS_SB_FEAT_INCOMPAT_LOG_XATTRS);
      52      162782 :         if (error)
      53         177 :                 goto drop_incompat;
      54             : 
      55      162605 :         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         177 :         xlog_drop_incompat_feat(mp->m_log, XLOG_INCOMPAT_FEAT_XATTRS);
      61         177 :         return error;
      62             : }
      63             : 
      64             : void
      65    11330561 : xfs_attr_rele_log_assist(
      66             :         struct xfs_mount        *mp)
      67             : {
      68    11330561 :         xlog_drop_incompat_feat(mp->m_log, XLOG_INCOMPAT_FEAT_XATTRS);
      69     3991291 : }
      70             : 
      71             : static inline bool
      72   184275330 : 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   184275330 :         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   184341593 : xfs_attr_change(
      89             :         struct xfs_da_args      *args)
      90             : {
      91   184341593 :         struct xfs_mount        *mp = args->dp->i_mount;
      92   184341593 :         bool                    use_logging = false;
      93   184341593 :         int                     error;
      94             : 
      95   184341593 :         ASSERT(!(args->op_flags & XFS_DA_OP_LOGGED));
      96             : 
      97   184341593 :         if (xfs_attr_want_log_assist(mp)) {
      98     3985022 :                 error = xfs_attr_grab_log_assist(mp);
      99     3991008 :                 if (error)
     100             :                         return error;
     101             : 
     102     3991008 :                 args->op_flags |= XFS_DA_OP_LOGGED;
     103     3991008 :                 use_logging = true;
     104             :         }
     105             : 
     106   184416596 :         if (args->value)
     107   121083039 :                 args->op_flags &= ~XFS_DA_OP_REMOVE;
     108             :         else
     109    63333557 :                 args->op_flags |= XFS_DA_OP_REMOVE;
     110             : 
     111   184416596 :         error = xfs_attr_set(args);
     112             : 
     113   184439372 :         if (use_logging)
     114     3990642 :                 xfs_attr_rele_log_assist(mp);
     115             :         return error;
     116             : }
     117             : 
     118             : 
     119             : static int
     120    57838487 : 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    57838487 :         struct xfs_da_args      args = {
     124             :                 .dp             = XFS_I(inode),
     125    57838487 :                 .attr_filter    = handler->flags,
     126             :                 .name           = name,
     127             :                 .namelen        = strlen(name),
     128             :                 .value          = value,
     129             :                 .valuelen       = size,
     130    57838487 :                 .owner          = XFS_I(inode)->i_ino,
     131             :         };
     132    57838487 :         int                     error;
     133             : 
     134    57838487 :         error = xfs_attr_get(&args);
     135    57760465 :         if (error)
     136             :                 return error;
     137    13200538 :         return args.valuelen;
     138             : }
     139             : 
     140             : static int
     141   173999807 : 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   173999807 :         struct xfs_da_args      args = {
     147             :                 .dp             = XFS_I(inode),
     148   173999807 :                 .attr_filter    = handler->flags,
     149             :                 .attr_flags     = flags,
     150             :                 .name           = name,
     151             :                 .namelen        = strlen(name),
     152             :                 .value          = (void *)value,
     153             :                 .valuelen       = size,
     154   173999807 :                 .owner          = XFS_I(inode)->i_ino,
     155             :         };
     156   173999807 :         int                     error;
     157             : 
     158   173999807 :         error = xfs_attr_change(&args);
     159   173973481 :         if (!error && (handler->flags & XFS_ATTR_ROOT))
     160      462021 :                 xfs_forget_acl(inode, name);
     161   173973411 :         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   811981479 : __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   811981479 :         char *offset;
     201   811981479 :         int arraytop;
     202             : 
     203   811981479 :         if (context->count < 0 || context->seen_enough)
     204             :                 return;
     205             : 
     206   811981468 :         if (!context->buffer)
     207   203510414 :                 goto compute_size;
     208             : 
     209   608471054 :         arraytop = context->count + prefix_len + namelen + 1;
     210   608471054 :         if (arraytop > context->firstu) {
     211          44 :                 context->count = -1; /* insufficient space */
     212          44 :                 context->seen_enough = 1;
     213          44 :                 return;
     214             :         }
     215   608471010 :         offset = context->buffer + context->count;
     216  1216942020 :         memcpy(offset, prefix, prefix_len);
     217   608471010 :         offset += prefix_len;
     218   608471010 :         strncpy(offset, (char *)name, namelen);                 /* real name */
     219   608471010 :         offset += namelen;
     220   608471010 :         *offset = '\0';
     221             : 
     222   811981424 : compute_size:
     223   811981424 :         context->count += prefix_len + namelen + 1;
     224   811981424 :         return;
     225             : }
     226             : 
     227             : static void
     228   871060161 : 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   871060161 :         char *prefix;
     237   871060161 :         int prefix_len;
     238             : 
     239   871060161 :         ASSERT(context->count >= 0);
     240             : 
     241   871060161 :         if (flags & XFS_ATTR_PARENT)
     242             :                 return;
     243             : 
     244   811567918 :         if (flags & XFS_ATTR_ROOT) {
     245             : #ifdef CONFIG_XFS_POSIX_ACL
     246        4561 :                 if (namelen == SGI_ACL_FILE_SIZE &&
     247          11 :                     strncmp(name, SGI_ACL_FILE,
     248             :                             SGI_ACL_FILE_SIZE) == 0) {
     249          11 :                         __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        4550 :                 } 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        4561 :                 if (!capable(CAP_SYS_ADMIN))
     270             :                         return;
     271             : 
     272             :                 prefix = XATTR_TRUSTED_PREFIX;
     273             :                 prefix_len = XATTR_TRUSTED_PREFIX_LEN;
     274   811563357 :         } else if (flags & XFS_ATTR_SECURE) {
     275             :                 prefix = XATTR_SECURITY_PREFIX;
     276             :                 prefix_len = XATTR_SECURITY_PREFIX_LEN;
     277             :         } else {
     278   811556213 :                 prefix = XATTR_USER_PREFIX;
     279   811556213 :                 prefix_len = XATTR_USER_PREFIX_LEN;
     280             :         }
     281             : 
     282   811567918 :         __xfs_xattr_put_listent(context, prefix, prefix_len, name,
     283             :                                 namelen);
     284   811567918 :         return;
     285             : }
     286             : 
     287             : ssize_t
     288    59725524 : xfs_vn_listxattr(
     289             :         struct dentry   *dentry,
     290             :         char            *data,
     291             :         size_t          size)
     292             : {
     293    59725524 :         struct xfs_attr_list_context context;
     294    59725524 :         struct inode    *inode = d_inode(dentry);
     295    59725524 :         int             error;
     296             : 
     297             :         /*
     298             :          * First read the regular on-disk attributes.
     299             :          */
     300    59725524 :         memset(&context, 0, sizeof(context));
     301    59725524 :         context.dp = XFS_I(inode);
     302    59725524 :         context.resynch = 1;
     303    59725524 :         context.buffer = size ? data : NULL;
     304    59725524 :         context.bufsize = size;
     305    59725524 :         context.firstu = context.bufsize;
     306    59725524 :         context.put_listent = xfs_xattr_put_listent;
     307             : 
     308    59725524 :         error = xfs_attr_list(&context);
     309    59728794 :         if (error)
     310          12 :                 return error;
     311    59728782 :         if (context.count < 0)
     312          44 :                 return -ERANGE;
     313             : 
     314             :         return context.count;
     315             : }

Generated by: LCOV version 1.14