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_da_btree.h" 16 #include "xfs_attr.h" 17 #include "xfs_acl.h" 18 #include "xfs_log.h" 19 #include "xfs_xattr.h" 20 21 #include <linux/posix_acl_xattr.h> 22 23 /* 24 * Get permission to use log-assisted atomic exchange of file extents. 25 * Callers must not be running any transactions or hold any ILOCKs. 26 */ 27 static inline int 28 xfs_attr_grab_log_assist( 29 struct xfs_mount *mp) 30 { 31 int error = 0; 32 33 /* xattr update log intent items are already enabled */ 34 if (xfs_sb_version_haslogxattrs(&mp->m_sb)) 35 return 0; 36 37 /* 38 * Check if the filesystem featureset is new enough to set this log 39 * incompat feature bit. Strictly speaking, the minimum requirement is 40 * a V5 filesystem for the superblock field, but we'll require rmap 41 * or reflink to avoid having to deal with really old kernels. 42 */ 43 if (!xfs_has_reflink(mp) && !xfs_has_rmapbt(mp)) 44 return -EOPNOTSUPP; 45 46 /* Enable log-assisted xattrs. */ 47 error = xfs_add_incompat_log_feature(mp, 48 XFS_SB_FEAT_INCOMPAT_LOG_XATTRS); 49 if (error) 50 return error; 51 52 xfs_warn_mount(mp, XFS_OPSTATE_WARNED_LARP, 53 "EXPERIMENTAL logged extended attributes feature in use. Use at your own risk!"); 54 55 return 0; 56 } 57 58 static inline bool 59 xfs_attr_want_log_assist( 60 struct xfs_mount *mp) 61 { 62 #ifdef DEBUG 63 /* Logged xattrs require a V5 super for log_incompat */ 64 return xfs_has_crc(mp) && xfs_globals.larp; 65 #else 66 return false; 67 #endif 68 } 69 70 /* 71 * Set or remove an xattr, having grabbed the appropriate logging resources 72 * prior to calling libxfs. 73 */ 74 int 75 xfs_attr_change( 76 struct xfs_da_args *args) 77 { 78 struct xfs_mount *mp = args->dp->i_mount; 79 int error; 80 81 ASSERT(!(args->op_flags & XFS_DA_OP_LOGGED)); 82 83 if (xfs_attr_want_log_assist(mp)) { 84 error = xfs_attr_grab_log_assist(mp); 85 if (error) 86 return error; 87 88 args->op_flags |= XFS_DA_OP_LOGGED; 89 } 90 91 return xfs_attr_set(args); 92 } 93 94 95 static int 96 xfs_xattr_get(const struct xattr_handler *handler, struct dentry *unused, 97 struct inode *inode, const char *name, void *value, size_t size) 98 { 99 struct xfs_da_args args = { 100 .dp = XFS_I(inode), 101 .attr_filter = handler->flags, 102 .name = name, 103 .namelen = strlen(name), 104 .value = value, 105 .valuelen = size, 106 }; 107 int error; 108 109 if (xfs_ifork_zapped(XFS_I(inode), XFS_ATTR_FORK)) 110 return -EIO; 111 112 error = xfs_attr_get(&args); 113 if (error) 114 return error; 115 return args.valuelen; 116 } 117 118 static int 119 xfs_xattr_set(const struct xattr_handler *handler, 120 struct mnt_idmap *idmap, struct dentry *unused, 121 struct inode *inode, const char *name, const void *value, 122 size_t size, int flags) 123 { 124 struct xfs_da_args args = { 125 .dp = XFS_I(inode), 126 .attr_filter = handler->flags, 127 .attr_flags = flags, 128 .name = name, 129 .namelen = strlen(name), 130 .value = (void *)value, 131 .valuelen = size, 132 }; 133 int error; 134 135 error = xfs_attr_change(&args); 136 if (!error && (handler->flags & XFS_ATTR_ROOT)) 137 xfs_forget_acl(inode, name); 138 return error; 139 } 140 141 static const struct xattr_handler xfs_xattr_user_handler = { 142 .prefix = XATTR_USER_PREFIX, 143 .flags = 0, /* no flags implies user namespace */ 144 .get = xfs_xattr_get, 145 .set = xfs_xattr_set, 146 }; 147 148 static const struct xattr_handler xfs_xattr_trusted_handler = { 149 .prefix = XATTR_TRUSTED_PREFIX, 150 .flags = XFS_ATTR_ROOT, 151 .get = xfs_xattr_get, 152 .set = xfs_xattr_set, 153 }; 154 155 static const struct xattr_handler xfs_xattr_security_handler = { 156 .prefix = XATTR_SECURITY_PREFIX, 157 .flags = XFS_ATTR_SECURE, 158 .get = xfs_xattr_get, 159 .set = xfs_xattr_set, 160 }; 161 162 const struct xattr_handler * const xfs_xattr_handlers[] = { 163 &xfs_xattr_user_handler, 164 &xfs_xattr_trusted_handler, 165 &xfs_xattr_security_handler, 166 NULL 167 }; 168 169 static void 170 __xfs_xattr_put_listent( 171 struct xfs_attr_list_context *context, 172 char *prefix, 173 int prefix_len, 174 unsigned char *name, 175 int namelen) 176 { 177 char *offset; 178 int arraytop; 179 180 if (context->count < 0 || context->seen_enough) 181 return; 182 183 if (!context->buffer) 184 goto compute_size; 185 186 arraytop = context->count + prefix_len + namelen + 1; 187 if (arraytop > context->firstu) { 188 context->count = -1; /* insufficient space */ 189 context->seen_enough = 1; 190 return; 191 } 192 offset = context->buffer + context->count; 193 memcpy(offset, prefix, prefix_len); 194 offset += prefix_len; 195 strncpy(offset, (char *)name, namelen); /* real name */ 196 offset += namelen; 197 *offset = '\0'; 198 199 compute_size: 200 context->count += prefix_len + namelen + 1; 201 return; 202 } 203 204 static void 205 xfs_xattr_put_listent( 206 struct xfs_attr_list_context *context, 207 int flags, 208 unsigned char *name, 209 int namelen, 210 int valuelen) 211 { 212 char *prefix; 213 int prefix_len; 214 215 ASSERT(context->count >= 0); 216 217 if (flags & XFS_ATTR_ROOT) { 218 #ifdef CONFIG_XFS_POSIX_ACL 219 if (namelen == SGI_ACL_FILE_SIZE && 220 strncmp(name, SGI_ACL_FILE, 221 SGI_ACL_FILE_SIZE) == 0) { 222 __xfs_xattr_put_listent( 223 context, XATTR_SYSTEM_PREFIX, 224 XATTR_SYSTEM_PREFIX_LEN, 225 XATTR_POSIX_ACL_ACCESS, 226 strlen(XATTR_POSIX_ACL_ACCESS)); 227 } else if (namelen == SGI_ACL_DEFAULT_SIZE && 228 strncmp(name, SGI_ACL_DEFAULT, 229 SGI_ACL_DEFAULT_SIZE) == 0) { 230 __xfs_xattr_put_listent( 231 context, XATTR_SYSTEM_PREFIX, 232 XATTR_SYSTEM_PREFIX_LEN, 233 XATTR_POSIX_ACL_DEFAULT, 234 strlen(XATTR_POSIX_ACL_DEFAULT)); 235 } 236 #endif 237 238 /* 239 * Only show root namespace entries if we are actually allowed to 240 * see them. 241 */ 242 if (!capable(CAP_SYS_ADMIN)) 243 return; 244 245 prefix = XATTR_TRUSTED_PREFIX; 246 prefix_len = XATTR_TRUSTED_PREFIX_LEN; 247 } else if (flags & XFS_ATTR_SECURE) { 248 prefix = XATTR_SECURITY_PREFIX; 249 prefix_len = XATTR_SECURITY_PREFIX_LEN; 250 } else { 251 prefix = XATTR_USER_PREFIX; 252 prefix_len = XATTR_USER_PREFIX_LEN; 253 } 254 255 __xfs_xattr_put_listent(context, prefix, prefix_len, name, 256 namelen); 257 return; 258 } 259 260 ssize_t 261 xfs_vn_listxattr( 262 struct dentry *dentry, 263 char *data, 264 size_t size) 265 { 266 struct xfs_attr_list_context context; 267 struct inode *inode = d_inode(dentry); 268 int error; 269 270 if (xfs_ifork_zapped(XFS_I(inode), XFS_ATTR_FORK)) 271 return -EIO; 272 273 /* 274 * First read the regular on-disk attributes. 275 */ 276 memset(&context, 0, sizeof(context)); 277 context.dp = XFS_I(inode); 278 context.resynch = 1; 279 context.buffer = size ? data : NULL; 280 context.bufsize = size; 281 context.firstu = context.bufsize; 282 context.put_listent = xfs_xattr_put_listent; 283 284 error = xfs_attr_list(&context); 285 if (error) 286 return error; 287 if (context.count < 0) 288 return -ERANGE; 289 290 return context.count; 291 } 292