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