Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.17-rc7 216 lines 4.9 kB view raw
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 22static int 23xfs_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 42static int 43xfs_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 65static 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 72static 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 79static 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 86const 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 97static 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 127compute_size: 128 context->count += prefix_len + namelen + 1; 129 return; 130} 131 132static void 133xfs_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 188ssize_t 189xfs_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}