xref: /linux/fs/xfs/xfs_xattr.c (revision 24168c5e6dfbdd5b414f048f47f75d64533296ca)
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
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
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
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 	return xfs_attr_set(args, op, args->attr_filter & XFS_ATTR_ROOT);
114 }
115 
116 
117 static int
118 xfs_xattr_get(const struct xattr_handler *handler, struct dentry *unused,
119 		struct inode *inode, const char *name, void *value, size_t size)
120 {
121 	struct xfs_da_args	args = {
122 		.dp		= XFS_I(inode),
123 		.attr_filter	= handler->flags,
124 		.name		= name,
125 		.namelen	= strlen(name),
126 		.value		= value,
127 		.valuelen	= size,
128 	};
129 	int			error;
130 
131 	if (xfs_ifork_zapped(XFS_I(inode), XFS_ATTR_FORK))
132 		return -EIO;
133 
134 	error = xfs_attr_get(&args);
135 	if (error)
136 		return error;
137 	return args.valuelen;
138 }
139 
140 static inline enum xfs_attr_update
141 xfs_xattr_flags_to_op(
142 	int		flags,
143 	const void	*value)
144 {
145 	if (!value)
146 		return XFS_ATTRUPDATE_REMOVE;
147 	if (flags & XATTR_CREATE)
148 		return XFS_ATTRUPDATE_CREATE;
149 	if (flags & XATTR_REPLACE)
150 		return XFS_ATTRUPDATE_REPLACE;
151 	return XFS_ATTRUPDATE_UPSERT;
152 }
153 
154 static int
155 xfs_xattr_set(const struct xattr_handler *handler,
156 	      struct mnt_idmap *idmap, struct dentry *unused,
157 	      struct inode *inode, const char *name, const void *value,
158 	      size_t size, int flags)
159 {
160 	struct xfs_da_args	args = {
161 		.dp		= XFS_I(inode),
162 		.attr_filter	= handler->flags,
163 		.name		= name,
164 		.namelen	= strlen(name),
165 		.value		= (void *)value,
166 		.valuelen	= size,
167 	};
168 	int			error;
169 
170 	error = xfs_attr_change(&args, xfs_xattr_flags_to_op(flags, value));
171 	if (!error && (handler->flags & XFS_ATTR_ROOT))
172 		xfs_forget_acl(inode, name);
173 	return error;
174 }
175 
176 static const struct xattr_handler xfs_xattr_user_handler = {
177 	.prefix	= XATTR_USER_PREFIX,
178 	.flags	= 0, /* no flags implies user namespace */
179 	.get	= xfs_xattr_get,
180 	.set	= xfs_xattr_set,
181 };
182 
183 static const struct xattr_handler xfs_xattr_trusted_handler = {
184 	.prefix	= XATTR_TRUSTED_PREFIX,
185 	.flags	= XFS_ATTR_ROOT,
186 	.get	= xfs_xattr_get,
187 	.set	= xfs_xattr_set,
188 };
189 
190 static const struct xattr_handler xfs_xattr_security_handler = {
191 	.prefix	= XATTR_SECURITY_PREFIX,
192 	.flags	= XFS_ATTR_SECURE,
193 	.get	= xfs_xattr_get,
194 	.set	= xfs_xattr_set,
195 };
196 
197 const struct xattr_handler * const xfs_xattr_handlers[] = {
198 	&xfs_xattr_user_handler,
199 	&xfs_xattr_trusted_handler,
200 	&xfs_xattr_security_handler,
201 	NULL
202 };
203 
204 static void
205 __xfs_xattr_put_listent(
206 	struct xfs_attr_list_context *context,
207 	char *prefix,
208 	int prefix_len,
209 	unsigned char *name,
210 	int namelen)
211 {
212 	char *offset;
213 	int arraytop;
214 
215 	if (context->count < 0 || context->seen_enough)
216 		return;
217 
218 	if (!context->buffer)
219 		goto compute_size;
220 
221 	arraytop = context->count + prefix_len + namelen + 1;
222 	if (arraytop > context->firstu) {
223 		context->count = -1;	/* insufficient space */
224 		context->seen_enough = 1;
225 		return;
226 	}
227 	offset = context->buffer + context->count;
228 	memcpy(offset, prefix, prefix_len);
229 	offset += prefix_len;
230 	strncpy(offset, (char *)name, namelen);			/* real name */
231 	offset += namelen;
232 	*offset = '\0';
233 
234 compute_size:
235 	context->count += prefix_len + namelen + 1;
236 	return;
237 }
238 
239 static void
240 xfs_xattr_put_listent(
241 	struct xfs_attr_list_context *context,
242 	int		flags,
243 	unsigned char	*name,
244 	int		namelen,
245 	void		*value,
246 	int		valuelen)
247 {
248 	char *prefix;
249 	int prefix_len;
250 
251 	ASSERT(context->count >= 0);
252 
253 	/* Don't expose private xattr namespaces. */
254 	if (flags & XFS_ATTR_PRIVATE_NSP_MASK)
255 		return;
256 
257 	if (flags & XFS_ATTR_ROOT) {
258 #ifdef CONFIG_XFS_POSIX_ACL
259 		if (namelen == SGI_ACL_FILE_SIZE &&
260 		    strncmp(name, SGI_ACL_FILE,
261 			    SGI_ACL_FILE_SIZE) == 0) {
262 			__xfs_xattr_put_listent(
263 					context, XATTR_SYSTEM_PREFIX,
264 					XATTR_SYSTEM_PREFIX_LEN,
265 					XATTR_POSIX_ACL_ACCESS,
266 					strlen(XATTR_POSIX_ACL_ACCESS));
267 		} else if (namelen == SGI_ACL_DEFAULT_SIZE &&
268 			 strncmp(name, SGI_ACL_DEFAULT,
269 				 SGI_ACL_DEFAULT_SIZE) == 0) {
270 			__xfs_xattr_put_listent(
271 					context, XATTR_SYSTEM_PREFIX,
272 					XATTR_SYSTEM_PREFIX_LEN,
273 					XATTR_POSIX_ACL_DEFAULT,
274 					strlen(XATTR_POSIX_ACL_DEFAULT));
275 		}
276 #endif
277 
278 		/*
279 		 * Only show root namespace entries if we are actually allowed to
280 		 * see them.
281 		 */
282 		if (!capable(CAP_SYS_ADMIN))
283 			return;
284 
285 		prefix = XATTR_TRUSTED_PREFIX;
286 		prefix_len = XATTR_TRUSTED_PREFIX_LEN;
287 	} else if (flags & XFS_ATTR_SECURE) {
288 		prefix = XATTR_SECURITY_PREFIX;
289 		prefix_len = XATTR_SECURITY_PREFIX_LEN;
290 	} else {
291 		prefix = XATTR_USER_PREFIX;
292 		prefix_len = XATTR_USER_PREFIX_LEN;
293 	}
294 
295 	__xfs_xattr_put_listent(context, prefix, prefix_len, name,
296 				namelen);
297 	return;
298 }
299 
300 ssize_t
301 xfs_vn_listxattr(
302 	struct dentry	*dentry,
303 	char		*data,
304 	size_t		size)
305 {
306 	struct xfs_attr_list_context context;
307 	struct inode	*inode = d_inode(dentry);
308 	int		error;
309 
310 	if (xfs_ifork_zapped(XFS_I(inode), XFS_ATTR_FORK))
311 		return -EIO;
312 
313 	/*
314 	 * First read the regular on-disk attributes.
315 	 */
316 	memset(&context, 0, sizeof(context));
317 	context.dp = XFS_I(inode);
318 	context.resynch = 1;
319 	context.buffer = size ? data : NULL;
320 	context.bufsize = size;
321 	context.firstu = context.bufsize;
322 	context.put_listent = xfs_xattr_put_listent;
323 
324 	error = xfs_attr_list(&context);
325 	if (error)
326 		return error;
327 	if (context.count < 0)
328 		return -ERANGE;
329 
330 	return context.count;
331 }
332