blob: 260287552ad4d3d7f47ddc9273a53f1bdf9c1b62 [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"
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +100012#include "xfs_inode.h"
13#include "xfs_attr.h"
Darrick J. Wong5f213dd2019-11-06 17:19:33 -080014#include "xfs_acl.h"
Christoph Hellwiga2544622020-02-26 17:30:33 -080015#include "xfs_da_format.h"
16#include "xfs_da_btree.h"
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +100017
18#include <linux/posix_acl_xattr.h>
19#include <linux/xattr.h>
20
21
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +100022static int
Al Virob2968212016-04-10 20:48:24 -040023xfs_xattr_get(const struct xattr_handler *handler, struct dentry *unused,
24 struct inode *inode, const char *name, void *value, size_t size)
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +100025{
Christoph Hellwige5171d72020-02-26 17:30:34 -080026 struct xfs_da_args args = {
27 .dp = XFS_I(inode),
28 .flags = handler->flags,
29 .name = name,
30 .namelen = strlen(name),
31 .value = value,
32 .valuelen = size,
33 };
34 int error;
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +100035
Christoph Hellwige5171d72020-02-26 17:30:34 -080036 error = xfs_attr_get(&args);
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +100037 if (error)
38 return error;
Christoph Hellwige5171d72020-02-26 17:30:34 -080039 return args.valuelen;
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +100040}
41
Andreas Gruenbacher47e1bf62015-11-03 12:56:17 +110042void
43xfs_forget_acl(
44 struct inode *inode,
45 const char *name,
46 int xflags)
47{
48 /*
49 * Invalidate any cached ACLs if the user has bypassed the ACL
50 * interface. We don't validate the content whatsoever so it is caller
51 * responsibility to provide data in valid format and ensure i_mode is
52 * consistent.
53 */
54 if (xflags & ATTR_ROOT) {
55#ifdef CONFIG_XFS_POSIX_ACL
56 if (!strcmp(name, SGI_ACL_FILE))
57 forget_cached_acl(inode, ACL_TYPE_ACCESS);
58 else if (!strcmp(name, SGI_ACL_DEFAULT))
59 forget_cached_acl(inode, ACL_TYPE_DEFAULT);
60#endif
61 }
62}
63
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +100064static int
Al Viro59301222016-05-27 10:19:30 -040065xfs_xattr_set(const struct xattr_handler *handler, struct dentry *unused,
66 struct inode *inode, const char *name, const void *value,
67 size_t size, int flags)
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +100068{
Christoph Hellwiga2544622020-02-26 17:30:33 -080069 struct xfs_da_args args = {
70 .dp = XFS_I(inode),
71 .flags = handler->flags,
72 .name = name,
73 .namelen = strlen(name),
74 .value = (void *)value,
75 .valuelen = size,
76 };
Brian Foster67d8e042015-11-03 12:40:59 +110077 int error;
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +100078
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +100079 /* Convert Linux syscall to XFS internal ATTR flags */
80 if (flags & XATTR_CREATE)
Christoph Hellwiga2544622020-02-26 17:30:33 -080081 args.flags |= ATTR_CREATE;
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +100082 if (flags & XATTR_REPLACE)
Christoph Hellwiga2544622020-02-26 17:30:33 -080083 args.flags |= ATTR_REPLACE;
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +100084
Christoph Hellwiga2544622020-02-26 17:30:33 -080085 error = xfs_attr_set(&args);
Andreas Gruenbacher47e1bf62015-11-03 12:56:17 +110086 if (!error)
Christoph Hellwiga2544622020-02-26 17:30:33 -080087 xfs_forget_acl(inode, name, args.flags);
Brian Foster67d8e042015-11-03 12:40:59 +110088 return error;
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +100089}
90
Stephen Hemminger46e58762010-05-13 17:53:20 -070091static const struct xattr_handler xfs_xattr_user_handler = {
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +100092 .prefix = XATTR_USER_PREFIX,
Christoph Hellwig431547b2009-11-13 09:52:56 +000093 .flags = 0, /* no flags implies user namespace */
94 .get = xfs_xattr_get,
95 .set = xfs_xattr_set,
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +100096};
97
Stephen Hemminger46e58762010-05-13 17:53:20 -070098static const struct xattr_handler xfs_xattr_trusted_handler = {
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +100099 .prefix = XATTR_TRUSTED_PREFIX,
Christoph Hellwig431547b2009-11-13 09:52:56 +0000100 .flags = ATTR_ROOT,
101 .get = xfs_xattr_get,
102 .set = xfs_xattr_set,
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000103};
104
Stephen Hemminger46e58762010-05-13 17:53:20 -0700105static const struct xattr_handler xfs_xattr_security_handler = {
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000106 .prefix = XATTR_SECURITY_PREFIX,
Christoph Hellwig431547b2009-11-13 09:52:56 +0000107 .flags = ATTR_SECURE,
108 .get = xfs_xattr_get,
109 .set = xfs_xattr_set,
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000110};
111
Stephen Hemminger46e58762010-05-13 17:53:20 -0700112const struct xattr_handler *xfs_xattr_handlers[] = {
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000113 &xfs_xattr_user_handler,
114 &xfs_xattr_trusted_handler,
115 &xfs_xattr_security_handler,
Christoph Hellwigef14f0c2009-06-10 17:07:47 +0200116#ifdef CONFIG_XFS_POSIX_ACL
Christoph Hellwig2401dc22013-12-20 05:16:50 -0800117 &posix_acl_access_xattr_handler,
118 &posix_acl_default_xattr_handler,
Christoph Hellwigef14f0c2009-06-10 17:07:47 +0200119#endif
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000120 NULL
121};
122
Eric Sandeenf7a136a2016-12-05 12:32:14 +1100123static void
Andreas Gruenbacher5d92b752015-12-02 14:44:40 +0100124__xfs_xattr_put_listent(
125 struct xfs_attr_list_context *context,
126 char *prefix,
127 int prefix_len,
128 unsigned char *name,
129 int namelen)
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000130{
Andreas Gruenbacher5d92b752015-12-02 14:44:40 +0100131 char *offset;
132 int arraytop;
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000133
Darrick J. Wong3b500862019-02-13 11:15:17 -0800134 if (context->count < 0 || context->seen_enough)
135 return;
136
Christoph Hellwiga9c8c692020-02-26 17:30:37 -0800137 if (!context->buffer)
Andreas Gruenbacher5d92b752015-12-02 14:44:40 +0100138 goto compute_size;
139
140 arraytop = context->count + prefix_len + namelen + 1;
141 if (arraytop > context->firstu) {
142 context->count = -1; /* insufficient space */
Artem Savkov791cc432016-09-14 07:40:35 +1000143 context->seen_enough = 1;
Eric Sandeenf7a136a2016-12-05 12:32:14 +1100144 return;
Andreas Gruenbacher5d92b752015-12-02 14:44:40 +0100145 }
Christoph Hellwiga9c8c692020-02-26 17:30:37 -0800146 offset = context->buffer + context->count;
Andreas Gruenbacher5d92b752015-12-02 14:44:40 +0100147 strncpy(offset, prefix, prefix_len);
148 offset += prefix_len;
149 strncpy(offset, (char *)name, namelen); /* real name */
150 offset += namelen;
151 *offset = '\0';
152
153compute_size:
154 context->count += prefix_len + namelen + 1;
Eric Sandeenf7a136a2016-12-05 12:32:14 +1100155 return;
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000156}
157
Eric Sandeenf7a136a2016-12-05 12:32:14 +1100158static void
Dave Chinnera9273ca2010-01-20 10:47:48 +1100159xfs_xattr_put_listent(
160 struct xfs_attr_list_context *context,
161 int flags,
162 unsigned char *name,
163 int namelen,
Eric Sandeene5bd12b2016-04-06 07:57:32 +1000164 int valuelen)
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000165{
Andreas Gruenbacher5d92b752015-12-02 14:44:40 +0100166 char *prefix;
167 int prefix_len;
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000168
169 ASSERT(context->count >= 0);
170
Andreas Gruenbacher5d92b752015-12-02 14:44:40 +0100171 if (flags & XFS_ATTR_ROOT) {
172#ifdef CONFIG_XFS_POSIX_ACL
173 if (namelen == SGI_ACL_FILE_SIZE &&
174 strncmp(name, SGI_ACL_FILE,
175 SGI_ACL_FILE_SIZE) == 0) {
Eric Sandeenf7a136a2016-12-05 12:32:14 +1100176 __xfs_xattr_put_listent(
Andreas Gruenbacher5d92b752015-12-02 14:44:40 +0100177 context, XATTR_SYSTEM_PREFIX,
178 XATTR_SYSTEM_PREFIX_LEN,
179 XATTR_POSIX_ACL_ACCESS,
180 strlen(XATTR_POSIX_ACL_ACCESS));
Andreas Gruenbacher5d92b752015-12-02 14:44:40 +0100181 } else if (namelen == SGI_ACL_DEFAULT_SIZE &&
182 strncmp(name, SGI_ACL_DEFAULT,
183 SGI_ACL_DEFAULT_SIZE) == 0) {
Eric Sandeenf7a136a2016-12-05 12:32:14 +1100184 __xfs_xattr_put_listent(
Andreas Gruenbacher5d92b752015-12-02 14:44:40 +0100185 context, XATTR_SYSTEM_PREFIX,
186 XATTR_SYSTEM_PREFIX_LEN,
187 XATTR_POSIX_ACL_DEFAULT,
188 strlen(XATTR_POSIX_ACL_DEFAULT));
Andreas Gruenbacher5d92b752015-12-02 14:44:40 +0100189 }
190#endif
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000191
Andreas Gruenbacher5d92b752015-12-02 14:44:40 +0100192 /*
193 * Only show root namespace entries if we are actually allowed to
194 * see them.
195 */
196 if (!capable(CAP_SYS_ADMIN))
Eric Sandeenf7a136a2016-12-05 12:32:14 +1100197 return;
Andreas Gruenbacher5d92b752015-12-02 14:44:40 +0100198
199 prefix = XATTR_TRUSTED_PREFIX;
200 prefix_len = XATTR_TRUSTED_PREFIX_LEN;
201 } else if (flags & XFS_ATTR_SECURE) {
202 prefix = XATTR_SECURITY_PREFIX;
203 prefix_len = XATTR_SECURITY_PREFIX_LEN;
204 } else {
205 prefix = XATTR_USER_PREFIX;
206 prefix_len = XATTR_USER_PREFIX_LEN;
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000207 }
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000208
Eric Sandeenf7a136a2016-12-05 12:32:14 +1100209 __xfs_xattr_put_listent(context, prefix, prefix_len, name,
210 namelen);
211 return;
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000212}
213
214ssize_t
Eric Sandeen2a6fba62016-04-06 07:57:18 +1000215xfs_vn_listxattr(
216 struct dentry *dentry,
217 char *data,
218 size_t size)
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000219{
220 struct xfs_attr_list_context context;
221 struct attrlist_cursor_kern cursor = { 0 };
Eric Sandeen2a6fba62016-04-06 07:57:18 +1000222 struct inode *inode = d_inode(dentry);
223 int error;
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000224
225 /*
226 * First read the regular on-disk attributes.
227 */
228 memset(&context, 0, sizeof(context));
229 context.dp = XFS_I(inode);
230 context.cursor = &cursor;
231 context.resynch = 1;
Christoph Hellwiga9c8c692020-02-26 17:30:37 -0800232 context.buffer = size ? data : NULL;
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000233 context.bufsize = size;
234 context.firstu = context.bufsize;
Andreas Gruenbacher5d92b752015-12-02 14:44:40 +0100235 context.put_listent = xfs_xattr_put_listent;
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000236
Christoph Hellwig17e1dd82020-02-26 17:30:39 -0800237 error = xfs_attr_list(&context);
Eric Sandeen2a6fba62016-04-06 07:57:18 +1000238 if (error)
239 return error;
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000240 if (context.count < 0)
241 return -ERANGE;
242
Lachlan McIlroyf9e09f02008-06-23 13:34:09 +1000243 return context.count;
244}