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 #include "xfs_da_btree.h" 16 17 #include <linux/posix_acl_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 struct xfs_da_args args = { 25 .dp = XFS_I(inode), 26 .attr_filter = handler->flags, 27 .name = name, 28 .namelen = strlen(name), 29 .value = value, 30 .valuelen = size, 31 }; 32 int error; 33 34 error = xfs_attr_get(&args); 35 if (error) 36 return error; 37 return args.valuelen; 38 } 39 40 static int 41 xfs_xattr_set(const struct xattr_handler *handler, struct dentry *unused, 42 struct inode *inode, const char *name, const void *value, 43 size_t size, int flags) 44 { 45 struct xfs_da_args args = { 46 .dp = XFS_I(inode), 47 .attr_filter = handler->flags, 48 .attr_flags = flags, 49 .name = name, 50 .namelen = strlen(name), 51 .value = (void *)value, 52 .valuelen = size, 53 }; 54 int error; 55 56 error = xfs_attr_set(&args); 57 if (!error && (handler->flags & XFS_ATTR_ROOT)) 58 xfs_forget_acl(inode, name); 59 return error; 60 } 61 62 static const struct xattr_handler xfs_xattr_user_handler = { 63 .prefix = XATTR_USER_PREFIX, 64 .flags = 0, /* no flags implies user namespace */ 65 .get = xfs_xattr_get, 66 .set = xfs_xattr_set, 67 }; 68 69 static const struct xattr_handler xfs_xattr_trusted_handler = { 70 .prefix = XATTR_TRUSTED_PREFIX, 71 .flags = XFS_ATTR_ROOT, 72 .get = xfs_xattr_get, 73 .set = xfs_xattr_set, 74 }; 75 76 static const struct xattr_handler xfs_xattr_security_handler = { 77 .prefix = XATTR_SECURITY_PREFIX, 78 .flags = XFS_ATTR_SECURE, 79 .get = xfs_xattr_get, 80 .set = xfs_xattr_set, 81 }; 82 83 const struct xattr_handler *xfs_xattr_handlers[] = { 84 &xfs_xattr_user_handler, 85 &xfs_xattr_trusted_handler, 86 &xfs_xattr_security_handler, 87 #ifdef CONFIG_XFS_POSIX_ACL 88 &posix_acl_access_xattr_handler, 89 &posix_acl_default_xattr_handler, 90 #endif 91 NULL 92 }; 93 94 static void 95 __xfs_xattr_put_listent( 96 struct xfs_attr_list_context *context, 97 char *prefix, 98 int prefix_len, 99 unsigned char *name, 100 int namelen) 101 { 102 char *offset; 103 int arraytop; 104 105 if (context->count < 0 || context->seen_enough) 106 return; 107 108 if (!context->buffer) 109 goto compute_size; 110 111 arraytop = context->count + prefix_len + namelen + 1; 112 if (arraytop > context->firstu) { 113 context->count = -1; /* insufficient space */ 114 context->seen_enough = 1; 115 return; 116 } 117 offset = context->buffer + context->count; 118 strncpy(offset, prefix, prefix_len); 119 offset += prefix_len; 120 strncpy(offset, (char *)name, namelen); /* real name */ 121 offset += namelen; 122 *offset = '\0'; 123 124 compute_size: 125 context->count += prefix_len + namelen + 1; 126 return; 127 } 128 129 static void 130 xfs_xattr_put_listent( 131 struct xfs_attr_list_context *context, 132 int flags, 133 unsigned char *name, 134 int namelen, 135 int valuelen) 136 { 137 char *prefix; 138 int prefix_len; 139 140 ASSERT(context->count >= 0); 141 142 if (flags & XFS_ATTR_ROOT) { 143 #ifdef CONFIG_XFS_POSIX_ACL 144 if (namelen == SGI_ACL_FILE_SIZE && 145 strncmp(name, SGI_ACL_FILE, 146 SGI_ACL_FILE_SIZE) == 0) { 147 __xfs_xattr_put_listent( 148 context, XATTR_SYSTEM_PREFIX, 149 XATTR_SYSTEM_PREFIX_LEN, 150 XATTR_POSIX_ACL_ACCESS, 151 strlen(XATTR_POSIX_ACL_ACCESS)); 152 } else if (namelen == SGI_ACL_DEFAULT_SIZE && 153 strncmp(name, SGI_ACL_DEFAULT, 154 SGI_ACL_DEFAULT_SIZE) == 0) { 155 __xfs_xattr_put_listent( 156 context, XATTR_SYSTEM_PREFIX, 157 XATTR_SYSTEM_PREFIX_LEN, 158 XATTR_POSIX_ACL_DEFAULT, 159 strlen(XATTR_POSIX_ACL_DEFAULT)); 160 } 161 #endif 162 163 /* 164 * Only show root namespace entries if we are actually allowed to 165 * see them. 166 */ 167 if (!capable(CAP_SYS_ADMIN)) 168 return; 169 170 prefix = XATTR_TRUSTED_PREFIX; 171 prefix_len = XATTR_TRUSTED_PREFIX_LEN; 172 } else if (flags & XFS_ATTR_SECURE) { 173 prefix = XATTR_SECURITY_PREFIX; 174 prefix_len = XATTR_SECURITY_PREFIX_LEN; 175 } else { 176 prefix = XATTR_USER_PREFIX; 177 prefix_len = XATTR_USER_PREFIX_LEN; 178 } 179 180 __xfs_xattr_put_listent(context, prefix, prefix_len, name, 181 namelen); 182 return; 183 } 184 185 ssize_t 186 xfs_vn_listxattr( 187 struct dentry *dentry, 188 char *data, 189 size_t size) 190 { 191 struct xfs_attr_list_context context; 192 struct inode *inode = d_inode(dentry); 193 int error; 194 195 /* 196 * First read the regular on-disk attributes. 197 */ 198 memset(&context, 0, sizeof(context)); 199 context.dp = XFS_I(inode); 200 context.resynch = 1; 201 context.buffer = size ? data : NULL; 202 context.bufsize = size; 203 context.firstu = context.bufsize; 204 context.put_listent = xfs_xattr_put_listent; 205 206 error = xfs_attr_list(&context); 207 if (error) 208 return error; 209 if (context.count < 0) 210 return -ERANGE; 211 212 return context.count; 213 } 214