blob: 35e13e125ec6a8ecb85b1c62c497635127ac1888 [file] [log] [blame]
Dave Chinner0b61f8a2018-06-05 19:42:14 -07001// SPDX-License-Identifier: GPL-2.0
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +10002/*
3 * Copyright (C) 2008 Christoph Hellwig.
4 * Portions Copyright (C) 2000-2008 Silicon Graphics, Inc.
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +10005 */
6
7#include "xfs.h"
Darrick J. Wong5467b342019-06-28 19:25:35 -07008#include "xfs_shared.h"
Dave Chinnera4fbe6a2013-10-23 10:51:50 +11009#include "xfs_format.h"
Dave Chinner69432832013-08-12 20:49:23 +100010#include "xfs_log_format.h"
Dave Chinner57062782013-10-15 09:17:51 +110011#include "xfs_da_format.h"
Darrick J. Wong383e32b2021-03-22 09:51:54 -070012#include "xfs_trans_resv.h"
13#include "xfs_mount.h"
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +100014#include "xfs_inode.h"
Dave Chinnere0c41082022-05-12 15:12:52 +100015#include "xfs_da_btree.h"
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +100016#include "xfs_attr.h"
Darrick J. Wong5f213dd2019-11-06 17:19:33 -080017#include "xfs_acl.h"
Darrick J. Wongd9c61cc2022-05-27 10:33:29 +100018#include "xfs_log.h"
19#include "xfs_xattr.h"
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +100020
21#include <linux/posix_acl_xattr.h>
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +100022
Darrick J. Wongd9c61cc2022-05-27 10:33:29 +100023/*
24 * Get permission to use log-assisted atomic exchange of file extents.
25 *
26 * Callers must not be running any transactions or hold any inode locks, and
27 * they must release the permission by calling xlog_drop_incompat_feat
28 * when they're done.
29 */
Darrick J. Wongefc2efe2022-05-27 10:34:04 +100030static inline int
Darrick J. Wongd9c61cc2022-05-27 10:33:29 +100031xfs_attr_grab_log_assist(
32 struct xfs_mount *mp)
33{
34 int error = 0;
35
36 /*
37 * Protect ourselves from an idle log clearing the logged xattrs log
38 * incompat feature bit.
39 */
40 xlog_use_incompat_feat(mp->m_log);
41
42 /*
43 * If log-assisted xattrs are already enabled, the caller can use the
44 * log assisted swap functions with the log-incompat reference we got.
45 */
46 if (xfs_sb_version_haslogxattrs(&mp->m_sb))
47 return 0;
48
49 /* Enable log-assisted xattrs. */
50 error = xfs_add_incompat_log_feature(mp,
51 XFS_SB_FEAT_INCOMPAT_LOG_XATTRS);
52 if (error)
53 goto drop_incompat;
54
55 xfs_warn_mount(mp, XFS_OPSTATE_WARNED_LARP,
56 "EXPERIMENTAL logged extended attributes feature in use. Use at your own risk!");
57
58 return 0;
59drop_incompat:
60 xlog_drop_incompat_feat(mp->m_log);
61 return error;
62}
63
Darrick J. Wongefc2efe2022-05-27 10:34:04 +100064static inline void
Darrick J. Wongd9c61cc2022-05-27 10:33:29 +100065xfs_attr_rele_log_assist(
66 struct xfs_mount *mp)
67{
68 xlog_drop_incompat_feat(mp->m_log);
69}
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +100070
Darrick J. Wongefc2efe2022-05-27 10:34:04 +100071/*
72 * Set or remove an xattr, having grabbed the appropriate logging resources
73 * prior to calling libxfs.
74 */
75int
76xfs_attr_change(
77 struct xfs_da_args *args)
78{
79 struct xfs_mount *mp = args->dp->i_mount;
80 bool use_logging = false;
81 int error;
82
83 if (xfs_has_larp(mp)) {
84 error = xfs_attr_grab_log_assist(mp);
85 if (error)
86 return error;
87
88 use_logging = true;
89 }
90
91 error = xfs_attr_set(args);
92
93 if (use_logging)
94 xfs_attr_rele_log_assist(mp);
95 return error;
96}
97
98
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +100099static int
Al Virob2968212016-04-10 20:48:24 -0400100xfs_xattr_get(const struct xattr_handler *handler, struct dentry *unused,
101 struct inode *inode, const char *name, void *value, size_t size)
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000102{
Christoph Hellwige5171d72020-02-26 17:30:34 -0800103 struct xfs_da_args args = {
104 .dp = XFS_I(inode),
Christoph Hellwigd5f0f492020-02-26 17:30:42 -0800105 .attr_filter = handler->flags,
Christoph Hellwige5171d72020-02-26 17:30:34 -0800106 .name = name,
107 .namelen = strlen(name),
108 .value = value,
109 .valuelen = size,
110 };
111 int error;
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000112
Christoph Hellwige5171d72020-02-26 17:30:34 -0800113 error = xfs_attr_get(&args);
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000114 if (error)
115 return error;
Christoph Hellwige5171d72020-02-26 17:30:34 -0800116 return args.valuelen;
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000117}
118
119static int
Christian Braunere65ce2a2021-01-21 14:19:27 +0100120xfs_xattr_set(const struct xattr_handler *handler,
121 struct user_namespace *mnt_userns, struct dentry *unused,
122 struct inode *inode, const char *name, const void *value,
123 size_t size, int flags)
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000124{
Christoph Hellwiga2544622020-02-26 17:30:33 -0800125 struct xfs_da_args args = {
126 .dp = XFS_I(inode),
Christoph Hellwigd5f0f492020-02-26 17:30:42 -0800127 .attr_filter = handler->flags,
128 .attr_flags = flags,
Christoph Hellwiga2544622020-02-26 17:30:33 -0800129 .name = name,
130 .namelen = strlen(name),
131 .value = (void *)value,
132 .valuelen = size,
133 };
Brian Foster67d8e042015-11-03 12:40:59 +1100134 int error;
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000135
Darrick J. Wongefc2efe2022-05-27 10:34:04 +1000136 error = xfs_attr_change(&args);
Christoph Hellwigd5f0f492020-02-26 17:30:42 -0800137 if (!error && (handler->flags & XFS_ATTR_ROOT))
Christoph Hellwig5a3930e2020-02-26 17:30:41 -0800138 xfs_forget_acl(inode, name);
Brian Foster67d8e042015-11-03 12:40:59 +1100139 return error;
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000140}
141
Stephen Hemminger46e58762010-05-13 17:53:20 -0700142static const struct xattr_handler xfs_xattr_user_handler = {
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000143 .prefix = XATTR_USER_PREFIX,
Christoph Hellwig431547b2009-11-13 09:52:56 +0000144 .flags = 0, /* no flags implies user namespace */
145 .get = xfs_xattr_get,
146 .set = xfs_xattr_set,
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000147};
148
Stephen Hemminger46e58762010-05-13 17:53:20 -0700149static const struct xattr_handler xfs_xattr_trusted_handler = {
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000150 .prefix = XATTR_TRUSTED_PREFIX,
Christoph Hellwigd5f0f492020-02-26 17:30:42 -0800151 .flags = XFS_ATTR_ROOT,
Christoph Hellwig431547b2009-11-13 09:52:56 +0000152 .get = xfs_xattr_get,
153 .set = xfs_xattr_set,
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000154};
155
Stephen Hemminger46e58762010-05-13 17:53:20 -0700156static const struct xattr_handler xfs_xattr_security_handler = {
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000157 .prefix = XATTR_SECURITY_PREFIX,
Christoph Hellwigd5f0f492020-02-26 17:30:42 -0800158 .flags = XFS_ATTR_SECURE,
Christoph Hellwig431547b2009-11-13 09:52:56 +0000159 .get = xfs_xattr_get,
160 .set = xfs_xattr_set,
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000161};
162
Stephen Hemminger46e58762010-05-13 17:53:20 -0700163const struct xattr_handler *xfs_xattr_handlers[] = {
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000164 &xfs_xattr_user_handler,
165 &xfs_xattr_trusted_handler,
166 &xfs_xattr_security_handler,
Christoph Hellwigef14f0c2009-06-10 17:07:47 +0200167#ifdef CONFIG_XFS_POSIX_ACL
Christoph Hellwig2401dc22013-12-20 05:16:50 -0800168 &posix_acl_access_xattr_handler,
169 &posix_acl_default_xattr_handler,
Christoph Hellwigef14f0c2009-06-10 17:07:47 +0200170#endif
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000171 NULL
172};
173
Eric Sandeenf7a136a2016-12-05 12:32:14 +1100174static void
Andreas Gruenbacher5d92b752015-12-02 14:44:40 +0100175__xfs_xattr_put_listent(
176 struct xfs_attr_list_context *context,
177 char *prefix,
178 int prefix_len,
179 unsigned char *name,
180 int namelen)
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000181{
Andreas Gruenbacher5d92b752015-12-02 14:44:40 +0100182 char *offset;
183 int arraytop;
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000184
Darrick J. Wong3b500862019-02-13 11:15:17 -0800185 if (context->count < 0 || context->seen_enough)
186 return;
187
Christoph Hellwiga9c8c692020-02-26 17:30:37 -0800188 if (!context->buffer)
Andreas Gruenbacher5d92b752015-12-02 14:44:40 +0100189 goto compute_size;
190
191 arraytop = context->count + prefix_len + namelen + 1;
192 if (arraytop > context->firstu) {
193 context->count = -1; /* insufficient space */
Artem Savkov791cc432016-09-14 07:40:35 +1000194 context->seen_enough = 1;
Eric Sandeenf7a136a2016-12-05 12:32:14 +1100195 return;
Andreas Gruenbacher5d92b752015-12-02 14:44:40 +0100196 }
Christoph Hellwiga9c8c692020-02-26 17:30:37 -0800197 offset = context->buffer + context->count;
Andreas Gruenbacher5d92b752015-12-02 14:44:40 +0100198 strncpy(offset, prefix, prefix_len);
199 offset += prefix_len;
200 strncpy(offset, (char *)name, namelen); /* real name */
201 offset += namelen;
202 *offset = '\0';
203
204compute_size:
205 context->count += prefix_len + namelen + 1;
Eric Sandeenf7a136a2016-12-05 12:32:14 +1100206 return;
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000207}
208
Eric Sandeenf7a136a2016-12-05 12:32:14 +1100209static void
Dave Chinnera9273ca2010-01-20 10:47:48 +1100210xfs_xattr_put_listent(
211 struct xfs_attr_list_context *context,
212 int flags,
213 unsigned char *name,
214 int namelen,
Eric Sandeene5bd12b2016-04-06 07:57:32 +1000215 int valuelen)
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000216{
Andreas Gruenbacher5d92b752015-12-02 14:44:40 +0100217 char *prefix;
218 int prefix_len;
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000219
220 ASSERT(context->count >= 0);
221
Andreas Gruenbacher5d92b752015-12-02 14:44:40 +0100222 if (flags & XFS_ATTR_ROOT) {
223#ifdef CONFIG_XFS_POSIX_ACL
224 if (namelen == SGI_ACL_FILE_SIZE &&
225 strncmp(name, SGI_ACL_FILE,
226 SGI_ACL_FILE_SIZE) == 0) {
Eric Sandeenf7a136a2016-12-05 12:32:14 +1100227 __xfs_xattr_put_listent(
Andreas Gruenbacher5d92b752015-12-02 14:44:40 +0100228 context, XATTR_SYSTEM_PREFIX,
229 XATTR_SYSTEM_PREFIX_LEN,
230 XATTR_POSIX_ACL_ACCESS,
231 strlen(XATTR_POSIX_ACL_ACCESS));
Andreas Gruenbacher5d92b752015-12-02 14:44:40 +0100232 } else if (namelen == SGI_ACL_DEFAULT_SIZE &&
233 strncmp(name, SGI_ACL_DEFAULT,
234 SGI_ACL_DEFAULT_SIZE) == 0) {
Eric Sandeenf7a136a2016-12-05 12:32:14 +1100235 __xfs_xattr_put_listent(
Andreas Gruenbacher5d92b752015-12-02 14:44:40 +0100236 context, XATTR_SYSTEM_PREFIX,
237 XATTR_SYSTEM_PREFIX_LEN,
238 XATTR_POSIX_ACL_DEFAULT,
239 strlen(XATTR_POSIX_ACL_DEFAULT));
Andreas Gruenbacher5d92b752015-12-02 14:44:40 +0100240 }
241#endif
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000242
Andreas Gruenbacher5d92b752015-12-02 14:44:40 +0100243 /*
244 * Only show root namespace entries if we are actually allowed to
245 * see them.
246 */
247 if (!capable(CAP_SYS_ADMIN))
Eric Sandeenf7a136a2016-12-05 12:32:14 +1100248 return;
Andreas Gruenbacher5d92b752015-12-02 14:44:40 +0100249
250 prefix = XATTR_TRUSTED_PREFIX;
251 prefix_len = XATTR_TRUSTED_PREFIX_LEN;
252 } else if (flags & XFS_ATTR_SECURE) {
253 prefix = XATTR_SECURITY_PREFIX;
254 prefix_len = XATTR_SECURITY_PREFIX_LEN;
255 } else {
256 prefix = XATTR_USER_PREFIX;
257 prefix_len = XATTR_USER_PREFIX_LEN;
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000258 }
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000259
Eric Sandeenf7a136a2016-12-05 12:32:14 +1100260 __xfs_xattr_put_listent(context, prefix, prefix_len, name,
261 namelen);
262 return;
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000263}
264
265ssize_t
Eric Sandeen2a6fba62016-04-06 07:57:18 +1000266xfs_vn_listxattr(
267 struct dentry *dentry,
268 char *data,
269 size_t size)
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000270{
271 struct xfs_attr_list_context context;
Eric Sandeen2a6fba62016-04-06 07:57:18 +1000272 struct inode *inode = d_inode(dentry);
273 int error;
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000274
275 /*
276 * First read the regular on-disk attributes.
277 */
278 memset(&context, 0, sizeof(context));
279 context.dp = XFS_I(inode);
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000280 context.resynch = 1;
Christoph Hellwiga9c8c692020-02-26 17:30:37 -0800281 context.buffer = size ? data : NULL;
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000282 context.bufsize = size;
283 context.firstu = context.bufsize;
Andreas Gruenbacher5d92b752015-12-02 14:44:40 +0100284 context.put_listent = xfs_xattr_put_listent;
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000285
Christoph Hellwig17e1dd82020-02-26 17:30:39 -0800286 error = xfs_attr_list(&context);
Eric Sandeen2a6fba62016-04-06 07:57:18 +1000287 if (error)
288 return error;
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000289 if (context.count < 0)
290 return -ERANGE;
291
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000292 return context.count;
293}