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