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 #include "xfs_quota.h"
21
22 #include <linux/posix_acl_xattr.h>
23
24 /*
25 * Get permission to use log-assisted atomic exchange of file extents.
26 * Callers must not be running any transactions or hold any ILOCKs.
27 */
28 static inline int
xfs_attr_grab_log_assist(struct xfs_mount * mp)29 xfs_attr_grab_log_assist(
30 struct xfs_mount *mp)
31 {
32 int error = 0;
33
34 /* xattr update log intent items are already enabled */
35 if (xfs_is_using_logged_xattrs(mp))
36 return 0;
37
38 /*
39 * Check if the filesystem featureset is new enough to set this log
40 * incompat feature bit. Strictly speaking, the minimum requirement is
41 * a V5 filesystem for the superblock field, but we'll require rmap
42 * or reflink to avoid having to deal with really old kernels.
43 */
44 if (!xfs_has_reflink(mp) && !xfs_has_rmapbt(mp))
45 return -EOPNOTSUPP;
46
47 /* Enable log-assisted xattrs. */
48 error = xfs_add_incompat_log_feature(mp,
49 XFS_SB_FEAT_INCOMPAT_LOG_XATTRS);
50 if (error)
51 return error;
52 xfs_set_using_logged_xattrs(mp);
53
54 xfs_warn_mount(mp, XFS_OPSTATE_WARNED_LARP,
55 "EXPERIMENTAL logged extended attributes feature in use. Use at your own risk!");
56
57 return 0;
58 }
59
60 static inline bool
xfs_attr_want_log_assist(struct xfs_mount * mp)61 xfs_attr_want_log_assist(
62 struct xfs_mount *mp)
63 {
64 #ifdef DEBUG
65 /* Logged xattrs require a V5 super for log_incompat */
66 return xfs_has_crc(mp) && xfs_globals.larp;
67 #else
68 return false;
69 #endif
70 }
71
72 /*
73 * Set or remove an xattr, having grabbed the appropriate logging resources
74 * prior to calling libxfs. Callers of this function are only required to
75 * initialize the inode, attr_filter, name, namelen, value, and valuelen fields
76 * of @args.
77 */
78 int
xfs_attr_change(struct xfs_da_args * args,enum xfs_attr_update op)79 xfs_attr_change(
80 struct xfs_da_args *args,
81 enum xfs_attr_update op)
82 {
83 struct xfs_mount *mp = args->dp->i_mount;
84 int error;
85
86 if (xfs_is_shutdown(mp))
87 return -EIO;
88
89 error = xfs_qm_dqattach(args->dp);
90 if (error)
91 return error;
92
93 /*
94 * We have no control over the attribute names that userspace passes us
95 * to remove, so we have to allow the name lookup prior to attribute
96 * removal to fail as well.
97 */
98 args->op_flags = XFS_DA_OP_OKNOENT;
99
100 if (xfs_attr_want_log_assist(mp)) {
101 error = xfs_attr_grab_log_assist(mp);
102 if (error)
103 return error;
104
105 args->op_flags |= XFS_DA_OP_LOGGED;
106 }
107
108 args->owner = args->dp->i_ino;
109 args->geo = mp->m_attr_geo;
110 args->whichfork = XFS_ATTR_FORK;
111 xfs_attr_sethash(args);
112
113 /*
114 * Some xattrs must be resistant to allocation failure at ENOSPC, e.g.
115 * creating an inode with ACLs or security attributes requires the
116 * allocation of the xattr holding that information to succeed. Hence
117 * we allow xattrs in the VFS TRUSTED, SYSTEM, POSIX_ACL and SECURITY
118 * (LSM xattr) namespaces to dip into the reserve block pool to allow
119 * manipulation of these xattrs when at ENOSPC. These VFS xattr
120 * namespaces translate to the XFS_ATTR_ROOT and XFS_ATTR_SECURE on-disk
121 * namespaces.
122 *
123 * For most of these cases, these special xattrs will fit in the inode
124 * itself and so consume no extra space or only require temporary extra
125 * space while an overwrite is being made. Hence the use of the reserved
126 * pool is largely to avoid the worst case reservation from preventing
127 * the xattr from being created at ENOSPC.
128 */
129 return xfs_attr_set(args, op,
130 args->attr_filter & (XFS_ATTR_ROOT | XFS_ATTR_SECURE));
131 }
132
133
134 static int
xfs_xattr_get(const struct xattr_handler * handler,struct dentry * unused,struct inode * inode,const char * name,void * value,size_t size)135 xfs_xattr_get(const struct xattr_handler *handler, struct dentry *unused,
136 struct inode *inode, const char *name, void *value, size_t size)
137 {
138 struct xfs_da_args args = {
139 .dp = XFS_I(inode),
140 .attr_filter = handler->flags,
141 .name = name,
142 .namelen = strlen(name),
143 .value = value,
144 .valuelen = size,
145 };
146 int error;
147
148 if (xfs_ifork_zapped(XFS_I(inode), XFS_ATTR_FORK))
149 return -EIO;
150
151 error = xfs_attr_get(&args);
152 if (error)
153 return error;
154 return args.valuelen;
155 }
156
157 static inline enum xfs_attr_update
xfs_xattr_flags_to_op(int flags,const void * value)158 xfs_xattr_flags_to_op(
159 int flags,
160 const void *value)
161 {
162 if (!value)
163 return XFS_ATTRUPDATE_REMOVE;
164 if (flags & XATTR_CREATE)
165 return XFS_ATTRUPDATE_CREATE;
166 if (flags & XATTR_REPLACE)
167 return XFS_ATTRUPDATE_REPLACE;
168 return XFS_ATTRUPDATE_UPSERT;
169 }
170
171 static int
xfs_xattr_set(const struct xattr_handler * handler,struct mnt_idmap * idmap,struct dentry * unused,struct inode * inode,const char * name,const void * value,size_t size,int flags)172 xfs_xattr_set(const struct xattr_handler *handler,
173 struct mnt_idmap *idmap, struct dentry *unused,
174 struct inode *inode, const char *name, const void *value,
175 size_t size, int flags)
176 {
177 struct xfs_da_args args = {
178 .dp = XFS_I(inode),
179 .attr_filter = handler->flags,
180 .name = name,
181 .namelen = strlen(name),
182 .value = (void *)value,
183 .valuelen = size,
184 };
185 int error;
186
187 error = xfs_attr_change(&args, xfs_xattr_flags_to_op(flags, value));
188 if (!error && (handler->flags & XFS_ATTR_ROOT))
189 xfs_forget_acl(inode, name);
190 return error;
191 }
192
193 static const struct xattr_handler xfs_xattr_user_handler = {
194 .prefix = XATTR_USER_PREFIX,
195 .flags = 0, /* no flags implies user namespace */
196 .get = xfs_xattr_get,
197 .set = xfs_xattr_set,
198 };
199
200 static const struct xattr_handler xfs_xattr_trusted_handler = {
201 .prefix = XATTR_TRUSTED_PREFIX,
202 .flags = XFS_ATTR_ROOT,
203 .get = xfs_xattr_get,
204 .set = xfs_xattr_set,
205 };
206
207 static const struct xattr_handler xfs_xattr_security_handler = {
208 .prefix = XATTR_SECURITY_PREFIX,
209 .flags = XFS_ATTR_SECURE,
210 .get = xfs_xattr_get,
211 .set = xfs_xattr_set,
212 };
213
214 const struct xattr_handler * const xfs_xattr_handlers[] = {
215 &xfs_xattr_user_handler,
216 &xfs_xattr_trusted_handler,
217 &xfs_xattr_security_handler,
218 NULL
219 };
220
221 static void
__xfs_xattr_put_listent(struct xfs_attr_list_context * context,char * prefix,int prefix_len,unsigned char * name,int namelen)222 __xfs_xattr_put_listent(
223 struct xfs_attr_list_context *context,
224 char *prefix,
225 int prefix_len,
226 unsigned char *name,
227 int namelen)
228 {
229 char *offset;
230 int arraytop;
231
232 if (context->count < 0 || context->seen_enough)
233 return;
234
235 if (!context->buffer)
236 goto compute_size;
237
238 arraytop = context->count + prefix_len + namelen + 1;
239 if (arraytop > context->firstu) {
240 context->count = -1; /* insufficient space */
241 context->seen_enough = 1;
242 return;
243 }
244 offset = context->buffer + context->count;
245 memcpy(offset, prefix, prefix_len);
246 offset += prefix_len;
247 strncpy(offset, (char *)name, namelen); /* real name */
248 offset += namelen;
249 *offset = '\0';
250
251 compute_size:
252 context->count += prefix_len + namelen + 1;
253 return;
254 }
255
256 static void
xfs_xattr_put_listent(struct xfs_attr_list_context * context,int flags,unsigned char * name,int namelen,void * value,int valuelen)257 xfs_xattr_put_listent(
258 struct xfs_attr_list_context *context,
259 int flags,
260 unsigned char *name,
261 int namelen,
262 void *value,
263 int valuelen)
264 {
265 char *prefix;
266 int prefix_len;
267
268 ASSERT(context->count >= 0);
269
270 /* Don't expose private xattr namespaces. */
271 if (flags & XFS_ATTR_PRIVATE_NSP_MASK)
272 return;
273
274 if (flags & XFS_ATTR_ROOT) {
275 #ifdef CONFIG_XFS_POSIX_ACL
276 if (namelen == SGI_ACL_FILE_SIZE &&
277 strncmp(name, SGI_ACL_FILE,
278 SGI_ACL_FILE_SIZE) == 0) {
279 __xfs_xattr_put_listent(
280 context, XATTR_SYSTEM_PREFIX,
281 XATTR_SYSTEM_PREFIX_LEN,
282 XATTR_POSIX_ACL_ACCESS,
283 strlen(XATTR_POSIX_ACL_ACCESS));
284 } else if (namelen == SGI_ACL_DEFAULT_SIZE &&
285 strncmp(name, SGI_ACL_DEFAULT,
286 SGI_ACL_DEFAULT_SIZE) == 0) {
287 __xfs_xattr_put_listent(
288 context, XATTR_SYSTEM_PREFIX,
289 XATTR_SYSTEM_PREFIX_LEN,
290 XATTR_POSIX_ACL_DEFAULT,
291 strlen(XATTR_POSIX_ACL_DEFAULT));
292 }
293 #endif
294
295 /*
296 * Only show root namespace entries if we are actually allowed to
297 * see them.
298 */
299 if (!capable(CAP_SYS_ADMIN))
300 return;
301
302 prefix = XATTR_TRUSTED_PREFIX;
303 prefix_len = XATTR_TRUSTED_PREFIX_LEN;
304 } else if (flags & XFS_ATTR_SECURE) {
305 prefix = XATTR_SECURITY_PREFIX;
306 prefix_len = XATTR_SECURITY_PREFIX_LEN;
307 } else {
308 prefix = XATTR_USER_PREFIX;
309 prefix_len = XATTR_USER_PREFIX_LEN;
310 }
311
312 __xfs_xattr_put_listent(context, prefix, prefix_len, name,
313 namelen);
314 return;
315 }
316
317 ssize_t
xfs_vn_listxattr(struct dentry * dentry,char * data,size_t size)318 xfs_vn_listxattr(
319 struct dentry *dentry,
320 char *data,
321 size_t size)
322 {
323 struct xfs_attr_list_context context;
324 struct inode *inode = d_inode(dentry);
325 int error;
326
327 if (xfs_ifork_zapped(XFS_I(inode), XFS_ATTR_FORK))
328 return -EIO;
329
330 /*
331 * First read the regular on-disk attributes.
332 */
333 memset(&context, 0, sizeof(context));
334 context.dp = XFS_I(inode);
335 context.resynch = 1;
336 context.buffer = size ? data : NULL;
337 context.bufsize = size;
338 context.firstu = context.bufsize;
339 context.put_listent = xfs_xattr_put_listent;
340
341 error = xfs_attr_list(&context);
342 if (error)
343 return error;
344 if (context.count < 0)
345 return -ERANGE;
346
347 return context.count;
348 }
349