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