hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/fs/xfs/xfs_acl.c
....@@ -4,18 +4,20 @@
44 * All Rights Reserved.
55 */
66 #include "xfs.h"
7
+#include "xfs_shared.h"
78 #include "xfs_format.h"
89 #include "xfs_log_format.h"
910 #include "xfs_trans_resv.h"
1011 #include "xfs_mount.h"
1112 #include "xfs_inode.h"
12
-#include "xfs_acl.h"
1313 #include "xfs_attr.h"
1414 #include "xfs_trace.h"
15
-#include <linux/slab.h>
16
-#include <linux/xattr.h>
17
-#include <linux/posix_acl_xattr.h>
15
+#include "xfs_error.h"
16
+#include "xfs_acl.h"
17
+#include "xfs_da_format.h"
18
+#include "xfs_da_btree.h"
1819
20
+#include <linux/posix_acl_xattr.h>
1921
2022 /*
2123 * Locking scheme:
....@@ -25,6 +27,7 @@
2527
2628 STATIC struct posix_acl *
2729 xfs_acl_from_disk(
30
+ struct xfs_mount *mp,
2831 const struct xfs_acl *aclp,
2932 int len,
3033 int max_entries)
....@@ -34,11 +37,18 @@
3437 const struct xfs_acl_entry *ace;
3538 unsigned int count, i;
3639
37
- if (len < sizeof(*aclp))
40
+ if (len < sizeof(*aclp)) {
41
+ XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, aclp,
42
+ len);
3843 return ERR_PTR(-EFSCORRUPTED);
44
+ }
45
+
3946 count = be32_to_cpu(aclp->acl_cnt);
40
- if (count > max_entries || XFS_ACL_SIZE(count) != len)
47
+ if (count > max_entries || XFS_ACL_SIZE(count) != len) {
48
+ XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, aclp,
49
+ len);
4150 return ERR_PTR(-EFSCORRUPTED);
51
+ }
4252
4353 acl = posix_acl_alloc(count, GFP_KERNEL);
4454 if (!acl)
....@@ -59,10 +69,12 @@
5969
6070 switch (acl_e->e_tag) {
6171 case ACL_USER:
62
- acl_e->e_uid = xfs_uid_to_kuid(be32_to_cpu(ace->ae_id));
72
+ acl_e->e_uid = make_kuid(&init_user_ns,
73
+ be32_to_cpu(ace->ae_id));
6374 break;
6475 case ACL_GROUP:
65
- acl_e->e_gid = xfs_gid_to_kgid(be32_to_cpu(ace->ae_id));
76
+ acl_e->e_gid = make_kgid(&init_user_ns,
77
+ be32_to_cpu(ace->ae_id));
6678 break;
6779 case ACL_USER_OBJ:
6880 case ACL_GROUP_OBJ:
....@@ -95,10 +107,12 @@
95107 ace->ae_tag = cpu_to_be32(acl_e->e_tag);
96108 switch (acl_e->e_tag) {
97109 case ACL_USER:
98
- ace->ae_id = cpu_to_be32(xfs_kuid_to_uid(acl_e->e_uid));
110
+ ace->ae_id = cpu_to_be32(
111
+ from_kuid(&init_user_ns, acl_e->e_uid));
99112 break;
100113 case ACL_GROUP:
101
- ace->ae_id = cpu_to_be32(xfs_kgid_to_gid(acl_e->e_gid));
114
+ ace->ae_id = cpu_to_be32(
115
+ from_kgid(&init_user_ns, acl_e->e_gid));
102116 break;
103117 default:
104118 ace->ae_id = cpu_to_be32(ACL_UNDEFINED_ID);
....@@ -112,103 +126,86 @@
112126 struct posix_acl *
113127 xfs_get_acl(struct inode *inode, int type)
114128 {
115
- struct xfs_inode *ip = XFS_I(inode);
116
- struct posix_acl *acl = NULL;
117
- struct xfs_acl *xfs_acl;
118
- unsigned char *ea_name;
119
- int error;
120
- int len;
129
+ struct xfs_inode *ip = XFS_I(inode);
130
+ struct xfs_mount *mp = ip->i_mount;
131
+ struct posix_acl *acl = NULL;
132
+ struct xfs_da_args args = {
133
+ .dp = ip,
134
+ .attr_filter = XFS_ATTR_ROOT,
135
+ .valuelen = XFS_ACL_MAX_SIZE(mp),
136
+ };
137
+ int error;
121138
122139 trace_xfs_get_acl(ip);
123140
124141 switch (type) {
125142 case ACL_TYPE_ACCESS:
126
- ea_name = SGI_ACL_FILE;
143
+ args.name = SGI_ACL_FILE;
127144 break;
128145 case ACL_TYPE_DEFAULT:
129
- ea_name = SGI_ACL_DEFAULT;
146
+ args.name = SGI_ACL_DEFAULT;
130147 break;
131148 default:
132149 BUG();
133150 }
151
+ args.namelen = strlen(args.name);
134152
135153 /*
136
- * If we have a cached ACLs value just return it, not need to
137
- * go out to the disk.
154
+ * If the attribute doesn't exist make sure we have a negative cache
155
+ * entry, for any other error assume it is transient.
138156 */
139
- len = XFS_ACL_MAX_SIZE(ip->i_mount);
140
- xfs_acl = kmem_zalloc_large(len, KM_SLEEP);
141
- if (!xfs_acl)
142
- return ERR_PTR(-ENOMEM);
143
-
144
- error = xfs_attr_get(ip, ea_name, (unsigned char *)xfs_acl,
145
- &len, ATTR_ROOT);
146
- if (error) {
147
- /*
148
- * If the attribute doesn't exist make sure we have a negative
149
- * cache entry, for any other error assume it is transient.
150
- */
151
- if (error != -ENOATTR)
152
- acl = ERR_PTR(error);
153
- } else {
154
- acl = xfs_acl_from_disk(xfs_acl, len,
155
- XFS_ACL_MAX_ENTRIES(ip->i_mount));
157
+ error = xfs_attr_get(&args);
158
+ if (!error) {
159
+ acl = xfs_acl_from_disk(mp, args.value, args.valuelen,
160
+ XFS_ACL_MAX_ENTRIES(mp));
161
+ } else if (error != -ENOATTR) {
162
+ acl = ERR_PTR(error);
156163 }
157
- kmem_free(xfs_acl);
164
+
165
+ kmem_free(args.value);
158166 return acl;
159167 }
160168
161169 int
162170 __xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
163171 {
164
- struct xfs_inode *ip = XFS_I(inode);
165
- unsigned char *ea_name;
166
- int error;
172
+ struct xfs_inode *ip = XFS_I(inode);
173
+ struct xfs_da_args args = {
174
+ .dp = ip,
175
+ .attr_filter = XFS_ATTR_ROOT,
176
+ };
177
+ int error;
167178
168179 switch (type) {
169180 case ACL_TYPE_ACCESS:
170
- ea_name = SGI_ACL_FILE;
181
+ args.name = SGI_ACL_FILE;
171182 break;
172183 case ACL_TYPE_DEFAULT:
173184 if (!S_ISDIR(inode->i_mode))
174185 return acl ? -EACCES : 0;
175
- ea_name = SGI_ACL_DEFAULT;
186
+ args.name = SGI_ACL_DEFAULT;
176187 break;
177188 default:
178189 return -EINVAL;
179190 }
191
+ args.namelen = strlen(args.name);
180192
181193 if (acl) {
182
- struct xfs_acl *xfs_acl;
183
- int len = XFS_ACL_MAX_SIZE(ip->i_mount);
184
-
185
- xfs_acl = kmem_zalloc_large(len, KM_SLEEP);
186
- if (!xfs_acl)
194
+ args.valuelen = XFS_ACL_SIZE(acl->a_count);
195
+ args.value = kvzalloc(args.valuelen, GFP_KERNEL);
196
+ if (!args.value)
187197 return -ENOMEM;
188
-
189
- xfs_acl_to_disk(xfs_acl, acl);
190
-
191
- /* subtract away the unused acl entries */
192
- len -= sizeof(struct xfs_acl_entry) *
193
- (XFS_ACL_MAX_ENTRIES(ip->i_mount) - acl->a_count);
194
-
195
- error = xfs_attr_set(ip, ea_name, (unsigned char *)xfs_acl,
196
- len, ATTR_ROOT);
197
-
198
- kmem_free(xfs_acl);
199
- } else {
200
- /*
201
- * A NULL ACL argument means we want to remove the ACL.
202
- */
203
- error = xfs_attr_remove(ip, ea_name, ATTR_ROOT);
204
-
205
- /*
206
- * If the attribute didn't exist to start with that's fine.
207
- */
208
- if (error == -ENOATTR)
209
- error = 0;
198
+ xfs_acl_to_disk(args.value, acl);
210199 }
211200
201
+ error = xfs_attr_set(&args);
202
+ kmem_free(args.value);
203
+
204
+ /*
205
+ * If the attribute didn't exist to start with that's fine.
206
+ */
207
+ if (!acl && error == -ENOATTR)
208
+ error = 0;
212209 if (!error)
213210 set_cached_acl(inode, type, acl);
214211 return error;
....@@ -268,3 +265,19 @@
268265
269266 return error;
270267 }
268
+
269
+/*
270
+ * Invalidate any cached ACLs if the user has bypassed the ACL interface.
271
+ * We don't validate the content whatsoever so it is caller responsibility to
272
+ * provide data in valid format and ensure i_mode is consistent.
273
+ */
274
+void
275
+xfs_forget_acl(
276
+ struct inode *inode,
277
+ const char *name)
278
+{
279
+ if (!strcmp(name, SGI_ACL_FILE))
280
+ forget_cached_acl(inode, ACL_TYPE_ACCESS);
281
+ else if (!strcmp(name, SGI_ACL_DEFAULT))
282
+ forget_cached_acl(inode, ACL_TYPE_DEFAULT);
283
+}