hc
2024-05-10 10ebd8556b7990499c896a550e3d416b444211e6
kernel/fs/afs/xattr.c
....@@ -1,13 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /* Extended attribute handling for AFS. We use xattrs to get and set metadata
23 * instead of providing pioctl().
34 *
45 * Copyright (C) 2017 Red Hat, Inc. All Rights Reserved.
56 * Written by David Howells (dhowells@redhat.com)
6
- *
7
- * This program is free software; you can redistribute it and/or
8
- * modify it under the terms of the GNU General Public Licence
9
- * as published by the Free Software Foundation; either version
10
- * 2 of the Licence, or (at your option) any later version.
117 */
128
139 #include <linux/slab.h>
....@@ -15,23 +11,254 @@
1511 #include <linux/xattr.h>
1612 #include "internal.h"
1713
18
-static const char afs_xattr_list[] =
19
- "afs.cell\0"
20
- "afs.fid\0"
21
- "afs.volume";
14
+/*
15
+ * Deal with the result of a successful fetch ACL operation.
16
+ */
17
+static void afs_acl_success(struct afs_operation *op)
18
+{
19
+ afs_vnode_commit_status(op, &op->file[0]);
20
+}
21
+
22
+static void afs_acl_put(struct afs_operation *op)
23
+{
24
+ kfree(op->acl);
25
+}
26
+
27
+static const struct afs_operation_ops afs_fetch_acl_operation = {
28
+ .issue_afs_rpc = afs_fs_fetch_acl,
29
+ .success = afs_acl_success,
30
+ .put = afs_acl_put,
31
+};
2232
2333 /*
24
- * Retrieve a list of the supported xattrs.
34
+ * Get a file's ACL.
2535 */
26
-ssize_t afs_listxattr(struct dentry *dentry, char *buffer, size_t size)
36
+static int afs_xattr_get_acl(const struct xattr_handler *handler,
37
+ struct dentry *dentry,
38
+ struct inode *inode, const char *name,
39
+ void *buffer, size_t size, int flags)
2740 {
28
- if (size == 0)
29
- return sizeof(afs_xattr_list);
30
- if (size < sizeof(afs_xattr_list))
31
- return -ERANGE;
32
- memcpy(buffer, afs_xattr_list, sizeof(afs_xattr_list));
33
- return sizeof(afs_xattr_list);
41
+ struct afs_operation *op;
42
+ struct afs_vnode *vnode = AFS_FS_I(inode);
43
+ struct afs_acl *acl = NULL;
44
+ int ret;
45
+
46
+ op = afs_alloc_operation(NULL, vnode->volume);
47
+ if (IS_ERR(op))
48
+ return -ENOMEM;
49
+
50
+ afs_op_set_vnode(op, 0, vnode);
51
+ op->ops = &afs_fetch_acl_operation;
52
+
53
+ afs_begin_vnode_operation(op);
54
+ afs_wait_for_operation(op);
55
+ acl = op->acl;
56
+ op->acl = NULL;
57
+ ret = afs_put_operation(op);
58
+
59
+ if (ret == 0) {
60
+ ret = acl->size;
61
+ if (size > 0) {
62
+ if (acl->size <= size)
63
+ memcpy(buffer, acl->data, acl->size);
64
+ else
65
+ ret = -ERANGE;
66
+ }
67
+ }
68
+
69
+ kfree(acl);
70
+ return ret;
3471 }
72
+
73
+static bool afs_make_acl(struct afs_operation *op,
74
+ const void *buffer, size_t size)
75
+{
76
+ struct afs_acl *acl;
77
+
78
+ acl = kmalloc(sizeof(*acl) + size, GFP_KERNEL);
79
+ if (!acl) {
80
+ afs_op_nomem(op);
81
+ return false;
82
+ }
83
+
84
+ acl->size = size;
85
+ memcpy(acl->data, buffer, size);
86
+ op->acl = acl;
87
+ return true;
88
+}
89
+
90
+static const struct afs_operation_ops afs_store_acl_operation = {
91
+ .issue_afs_rpc = afs_fs_store_acl,
92
+ .success = afs_acl_success,
93
+ .put = afs_acl_put,
94
+};
95
+
96
+/*
97
+ * Set a file's AFS3 ACL.
98
+ */
99
+static int afs_xattr_set_acl(const struct xattr_handler *handler,
100
+ struct dentry *dentry,
101
+ struct inode *inode, const char *name,
102
+ const void *buffer, size_t size, int flags)
103
+{
104
+ struct afs_operation *op;
105
+ struct afs_vnode *vnode = AFS_FS_I(inode);
106
+
107
+ if (flags == XATTR_CREATE)
108
+ return -EINVAL;
109
+
110
+ op = afs_alloc_operation(NULL, vnode->volume);
111
+ if (IS_ERR(op))
112
+ return -ENOMEM;
113
+
114
+ afs_op_set_vnode(op, 0, vnode);
115
+ if (!afs_make_acl(op, buffer, size))
116
+ return afs_put_operation(op);
117
+
118
+ op->ops = &afs_store_acl_operation;
119
+ return afs_do_sync_operation(op);
120
+}
121
+
122
+static const struct xattr_handler afs_xattr_afs_acl_handler = {
123
+ .name = "afs.acl",
124
+ .get = afs_xattr_get_acl,
125
+ .set = afs_xattr_set_acl,
126
+};
127
+
128
+static const struct afs_operation_ops yfs_fetch_opaque_acl_operation = {
129
+ .issue_yfs_rpc = yfs_fs_fetch_opaque_acl,
130
+ .success = afs_acl_success,
131
+ /* Don't free op->yacl in .put here */
132
+};
133
+
134
+/*
135
+ * Get a file's YFS ACL.
136
+ */
137
+static int afs_xattr_get_yfs(const struct xattr_handler *handler,
138
+ struct dentry *dentry,
139
+ struct inode *inode, const char *name,
140
+ void *buffer, size_t size, int flags)
141
+{
142
+ struct afs_operation *op;
143
+ struct afs_vnode *vnode = AFS_FS_I(inode);
144
+ struct yfs_acl *yacl = NULL;
145
+ char buf[16], *data;
146
+ int which = 0, dsize, ret = -ENOMEM;
147
+
148
+ if (strcmp(name, "acl") == 0)
149
+ which = 0;
150
+ else if (strcmp(name, "acl_inherited") == 0)
151
+ which = 1;
152
+ else if (strcmp(name, "acl_num_cleaned") == 0)
153
+ which = 2;
154
+ else if (strcmp(name, "vol_acl") == 0)
155
+ which = 3;
156
+ else
157
+ return -EOPNOTSUPP;
158
+
159
+ yacl = kzalloc(sizeof(struct yfs_acl), GFP_KERNEL);
160
+ if (!yacl)
161
+ goto error;
162
+
163
+ if (which == 0)
164
+ yacl->flags |= YFS_ACL_WANT_ACL;
165
+ else if (which == 3)
166
+ yacl->flags |= YFS_ACL_WANT_VOL_ACL;
167
+
168
+ op = afs_alloc_operation(NULL, vnode->volume);
169
+ if (IS_ERR(op))
170
+ goto error_yacl;
171
+
172
+ afs_op_set_vnode(op, 0, vnode);
173
+ op->yacl = yacl;
174
+ op->ops = &yfs_fetch_opaque_acl_operation;
175
+
176
+ afs_begin_vnode_operation(op);
177
+ afs_wait_for_operation(op);
178
+ ret = afs_put_operation(op);
179
+
180
+ if (ret == 0) {
181
+ switch (which) {
182
+ case 0:
183
+ data = yacl->acl->data;
184
+ dsize = yacl->acl->size;
185
+ break;
186
+ case 1:
187
+ data = buf;
188
+ dsize = scnprintf(buf, sizeof(buf), "%u", yacl->inherit_flag);
189
+ break;
190
+ case 2:
191
+ data = buf;
192
+ dsize = scnprintf(buf, sizeof(buf), "%u", yacl->num_cleaned);
193
+ break;
194
+ case 3:
195
+ data = yacl->vol_acl->data;
196
+ dsize = yacl->vol_acl->size;
197
+ break;
198
+ default:
199
+ ret = -EOPNOTSUPP;
200
+ goto error_yacl;
201
+ }
202
+
203
+ ret = dsize;
204
+ if (size > 0) {
205
+ if (dsize <= size)
206
+ memcpy(buffer, data, dsize);
207
+ else
208
+ ret = -ERANGE;
209
+ }
210
+ } else if (ret == -ENOTSUPP) {
211
+ ret = -ENODATA;
212
+ }
213
+
214
+error_yacl:
215
+ yfs_free_opaque_acl(yacl);
216
+error:
217
+ return ret;
218
+}
219
+
220
+static const struct afs_operation_ops yfs_store_opaque_acl2_operation = {
221
+ .issue_yfs_rpc = yfs_fs_store_opaque_acl2,
222
+ .success = afs_acl_success,
223
+ .put = afs_acl_put,
224
+};
225
+
226
+/*
227
+ * Set a file's YFS ACL.
228
+ */
229
+static int afs_xattr_set_yfs(const struct xattr_handler *handler,
230
+ struct dentry *dentry,
231
+ struct inode *inode, const char *name,
232
+ const void *buffer, size_t size, int flags)
233
+{
234
+ struct afs_operation *op;
235
+ struct afs_vnode *vnode = AFS_FS_I(inode);
236
+ int ret;
237
+
238
+ if (flags == XATTR_CREATE ||
239
+ strcmp(name, "acl") != 0)
240
+ return -EINVAL;
241
+
242
+ op = afs_alloc_operation(NULL, vnode->volume);
243
+ if (IS_ERR(op))
244
+ return -ENOMEM;
245
+
246
+ afs_op_set_vnode(op, 0, vnode);
247
+ if (!afs_make_acl(op, buffer, size))
248
+ return afs_put_operation(op);
249
+
250
+ op->ops = &yfs_store_opaque_acl2_operation;
251
+ ret = afs_do_sync_operation(op);
252
+ if (ret == -ENOTSUPP)
253
+ ret = -ENODATA;
254
+ return ret;
255
+}
256
+
257
+static const struct xattr_handler afs_xattr_yfs_handler = {
258
+ .prefix = "afs.yfs.",
259
+ .get = afs_xattr_get_yfs,
260
+ .set = afs_xattr_set_yfs,
261
+};
35262
36263 /*
37264 * Get the name of the cell on which a file resides.
....@@ -39,7 +266,7 @@
39266 static int afs_xattr_get_cell(const struct xattr_handler *handler,
40267 struct dentry *dentry,
41268 struct inode *inode, const char *name,
42
- void *buffer, size_t size)
269
+ void *buffer, size_t size, int flags)
43270 {
44271 struct afs_vnode *vnode = AFS_FS_I(inode);
45272 struct afs_cell *cell = vnode->volume->cell;
....@@ -66,14 +293,25 @@
66293 static int afs_xattr_get_fid(const struct xattr_handler *handler,
67294 struct dentry *dentry,
68295 struct inode *inode, const char *name,
69
- void *buffer, size_t size)
296
+ void *buffer, size_t size, int flags)
70297 {
71298 struct afs_vnode *vnode = AFS_FS_I(inode);
72
- char text[8 + 1 + 8 + 1 + 8 + 1];
299
+ char text[16 + 1 + 24 + 1 + 8 + 1];
73300 size_t len;
74301
75
- len = sprintf(text, "%x:%x:%x",
76
- vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique);
302
+ /* The volume ID is 64-bit, the vnode ID is 96-bit and the
303
+ * uniquifier is 32-bit.
304
+ */
305
+ len = scnprintf(text, sizeof(text), "%llx:", vnode->fid.vid);
306
+ if (vnode->fid.vnode_hi)
307
+ len += scnprintf(text + len, sizeof(text) - len, "%x%016llx",
308
+ vnode->fid.vnode_hi, vnode->fid.vnode);
309
+ else
310
+ len += scnprintf(text + len, sizeof(text) - len, "%llx",
311
+ vnode->fid.vnode);
312
+ len += scnprintf(text + len, sizeof(text) - len, ":%x",
313
+ vnode->fid.unique);
314
+
77315 if (size == 0)
78316 return len;
79317 if (len > size)
....@@ -93,7 +331,7 @@
93331 static int afs_xattr_get_volume(const struct xattr_handler *handler,
94332 struct dentry *dentry,
95333 struct inode *inode, const char *name,
96
- void *buffer, size_t size)
334
+ void *buffer, size_t size, int flags)
97335 {
98336 struct afs_vnode *vnode = AFS_FS_I(inode);
99337 const char *volname = vnode->volume->name;
....@@ -114,8 +352,10 @@
114352 };
115353
116354 const struct xattr_handler *afs_xattr_handlers[] = {
355
+ &afs_xattr_afs_acl_handler,
117356 &afs_xattr_afs_cell_handler,
118357 &afs_xattr_afs_fid_handler,
119358 &afs_xattr_afs_volume_handler,
359
+ &afs_xattr_yfs_handler, /* afs.yfs. prefix */
120360 NULL
121361 };