root/fs/xfs/xfs_xattr.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. xfs_xattr_get
  2. xfs_forget_acl
  3. xfs_xattr_set
  4. __xfs_xattr_put_listent
  5. xfs_xattr_put_listent
  6. xfs_vn_listxattr

   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_inode.h"
  13 #include "xfs_attr.h"
  14 
  15 #include <linux/posix_acl_xattr.h>
  16 #include <linux/xattr.h>
  17 
  18 
  19 static int
  20 xfs_xattr_get(const struct xattr_handler *handler, struct dentry *unused,
  21                 struct inode *inode, const char *name, void *value, size_t size)
  22 {
  23         int xflags = handler->flags;
  24         struct xfs_inode *ip = XFS_I(inode);
  25         int error, asize = size;
  26 
  27         /* Convert Linux syscall to XFS internal ATTR flags */
  28         if (!size) {
  29                 xflags |= ATTR_KERNOVAL;
  30                 value = NULL;
  31         }
  32 
  33         error = xfs_attr_get(ip, name, (unsigned char **)&value, &asize, xflags);
  34         if (error)
  35                 return error;
  36         return asize;
  37 }
  38 
  39 void
  40 xfs_forget_acl(
  41         struct inode            *inode,
  42         const char              *name,
  43         int                     xflags)
  44 {
  45         /*
  46          * Invalidate any cached ACLs if the user has bypassed the ACL
  47          * interface. We don't validate the content whatsoever so it is caller
  48          * responsibility to provide data in valid format and ensure i_mode is
  49          * consistent.
  50          */
  51         if (xflags & ATTR_ROOT) {
  52 #ifdef CONFIG_XFS_POSIX_ACL
  53                 if (!strcmp(name, SGI_ACL_FILE))
  54                         forget_cached_acl(inode, ACL_TYPE_ACCESS);
  55                 else if (!strcmp(name, SGI_ACL_DEFAULT))
  56                         forget_cached_acl(inode, ACL_TYPE_DEFAULT);
  57 #endif
  58         }
  59 }
  60 
  61 static int
  62 xfs_xattr_set(const struct xattr_handler *handler, struct dentry *unused,
  63                 struct inode *inode, const char *name, const void *value,
  64                 size_t size, int flags)
  65 {
  66         int                     xflags = handler->flags;
  67         struct xfs_inode        *ip = XFS_I(inode);
  68         int                     error;
  69 
  70         /* Convert Linux syscall to XFS internal ATTR flags */
  71         if (flags & XATTR_CREATE)
  72                 xflags |= ATTR_CREATE;
  73         if (flags & XATTR_REPLACE)
  74                 xflags |= ATTR_REPLACE;
  75 
  76         if (!value)
  77                 return xfs_attr_remove(ip, (unsigned char *)name, xflags);
  78         error = xfs_attr_set(ip, (unsigned char *)name,
  79                                 (void *)value, size, xflags);
  80         if (!error)
  81                 xfs_forget_acl(inode, name, xflags);
  82 
  83         return error;
  84 }
  85 
  86 static const struct xattr_handler xfs_xattr_user_handler = {
  87         .prefix = XATTR_USER_PREFIX,
  88         .flags  = 0, /* no flags implies user namespace */
  89         .get    = xfs_xattr_get,
  90         .set    = xfs_xattr_set,
  91 };
  92 
  93 static const struct xattr_handler xfs_xattr_trusted_handler = {
  94         .prefix = XATTR_TRUSTED_PREFIX,
  95         .flags  = ATTR_ROOT,
  96         .get    = xfs_xattr_get,
  97         .set    = xfs_xattr_set,
  98 };
  99 
 100 static const struct xattr_handler xfs_xattr_security_handler = {
 101         .prefix = XATTR_SECURITY_PREFIX,
 102         .flags  = ATTR_SECURE,
 103         .get    = xfs_xattr_get,
 104         .set    = xfs_xattr_set,
 105 };
 106 
 107 const struct xattr_handler *xfs_xattr_handlers[] = {
 108         &xfs_xattr_user_handler,
 109         &xfs_xattr_trusted_handler,
 110         &xfs_xattr_security_handler,
 111 #ifdef CONFIG_XFS_POSIX_ACL
 112         &posix_acl_access_xattr_handler,
 113         &posix_acl_default_xattr_handler,
 114 #endif
 115         NULL
 116 };
 117 
 118 static void
 119 __xfs_xattr_put_listent(
 120         struct xfs_attr_list_context *context,
 121         char *prefix,
 122         int prefix_len,
 123         unsigned char *name,
 124         int namelen)
 125 {
 126         char *offset;
 127         int arraytop;
 128 
 129         if (context->count < 0 || context->seen_enough)
 130                 return;
 131 
 132         if (!context->alist)
 133                 goto compute_size;
 134 
 135         arraytop = context->count + prefix_len + namelen + 1;
 136         if (arraytop > context->firstu) {
 137                 context->count = -1;    /* insufficient space */
 138                 context->seen_enough = 1;
 139                 return;
 140         }
 141         offset = (char *)context->alist + context->count;
 142         strncpy(offset, prefix, prefix_len);
 143         offset += prefix_len;
 144         strncpy(offset, (char *)name, namelen);                 /* real name */
 145         offset += namelen;
 146         *offset = '\0';
 147 
 148 compute_size:
 149         context->count += prefix_len + namelen + 1;
 150         return;
 151 }
 152 
 153 static void
 154 xfs_xattr_put_listent(
 155         struct xfs_attr_list_context *context,
 156         int             flags,
 157         unsigned char   *name,
 158         int             namelen,
 159         int             valuelen)
 160 {
 161         char *prefix;
 162         int prefix_len;
 163 
 164         ASSERT(context->count >= 0);
 165 
 166         if (flags & XFS_ATTR_ROOT) {
 167 #ifdef CONFIG_XFS_POSIX_ACL
 168                 if (namelen == SGI_ACL_FILE_SIZE &&
 169                     strncmp(name, SGI_ACL_FILE,
 170                             SGI_ACL_FILE_SIZE) == 0) {
 171                         __xfs_xattr_put_listent(
 172                                         context, XATTR_SYSTEM_PREFIX,
 173                                         XATTR_SYSTEM_PREFIX_LEN,
 174                                         XATTR_POSIX_ACL_ACCESS,
 175                                         strlen(XATTR_POSIX_ACL_ACCESS));
 176                 } else if (namelen == SGI_ACL_DEFAULT_SIZE &&
 177                          strncmp(name, SGI_ACL_DEFAULT,
 178                                  SGI_ACL_DEFAULT_SIZE) == 0) {
 179                         __xfs_xattr_put_listent(
 180                                         context, XATTR_SYSTEM_PREFIX,
 181                                         XATTR_SYSTEM_PREFIX_LEN,
 182                                         XATTR_POSIX_ACL_DEFAULT,
 183                                         strlen(XATTR_POSIX_ACL_DEFAULT));
 184                 }
 185 #endif
 186 
 187                 /*
 188                  * Only show root namespace entries if we are actually allowed to
 189                  * see them.
 190                  */
 191                 if (!capable(CAP_SYS_ADMIN))
 192                         return;
 193 
 194                 prefix = XATTR_TRUSTED_PREFIX;
 195                 prefix_len = XATTR_TRUSTED_PREFIX_LEN;
 196         } else if (flags & XFS_ATTR_SECURE) {
 197                 prefix = XATTR_SECURITY_PREFIX;
 198                 prefix_len = XATTR_SECURITY_PREFIX_LEN;
 199         } else {
 200                 prefix = XATTR_USER_PREFIX;
 201                 prefix_len = XATTR_USER_PREFIX_LEN;
 202         }
 203 
 204         __xfs_xattr_put_listent(context, prefix, prefix_len, name,
 205                                 namelen);
 206         return;
 207 }
 208 
 209 ssize_t
 210 xfs_vn_listxattr(
 211         struct dentry   *dentry,
 212         char            *data,
 213         size_t          size)
 214 {
 215         struct xfs_attr_list_context context;
 216         struct attrlist_cursor_kern cursor = { 0 };
 217         struct inode    *inode = d_inode(dentry);
 218         int             error;
 219 
 220         /*
 221          * First read the regular on-disk attributes.
 222          */
 223         memset(&context, 0, sizeof(context));
 224         context.dp = XFS_I(inode);
 225         context.cursor = &cursor;
 226         context.resynch = 1;
 227         context.alist = size ? data : NULL;
 228         context.bufsize = size;
 229         context.firstu = context.bufsize;
 230         context.put_listent = xfs_xattr_put_listent;
 231 
 232         error = xfs_attr_list_int(&context);
 233         if (error)
 234                 return error;
 235         if (context.count < 0)
 236                 return -ERANGE;
 237 
 238         return context.count;
 239 }

/* [<][>][^][v][top][bottom][index][help] */