aboutsummaryrefslogtreecommitdiffstats
path: root/fs/afs
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2019-04-30 13:30:21 -0400
committerDavid Howells <dhowells@redhat.com>2019-05-07 11:48:44 -0400
commitae46578b963f6daa9853791ab4c6ac1d6375937c (patch)
tree2ec257ba3ec3b10321c03ea6205879edabd28d9d /fs/afs
parentb10494af4989d2d20679d0e3b7d1a45c2f8f8f1a (diff)
afs: Get YFS ACLs and information through xattrs
The YFS/AuriStor variant of AFS provides more capable ACLs and provides per-volume ACLs and per-file ACLs as well as per-directory ACLs. It also provides some extra information that can be retrieved through four ACLs: (1) afs.yfs.acl The YFS file ACL (not the same format as afs.acl). (2) afs.yfs.vol_acl The YFS volume ACL. (3) afs.yfs.acl_inherited "1" if a file's ACL is inherited from its parent directory, "0" otherwise. (4) afs.yfs.acl_num_cleaned The number of of ACEs removed from the ACL by the server because the PT entries were removed from the PTS database (ie. the subject is no longer known). Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'fs/afs')
-rw-r--r--fs/afs/internal.h13
-rw-r--r--fs/afs/protocol_yfs.h6
-rw-r--r--fs/afs/xattr.c101
-rw-r--r--fs/afs/yfsclient.c188
4 files changed, 304 insertions, 4 deletions
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index 5269824244c6..b800b4e286d3 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -1371,6 +1371,19 @@ extern int yfs_fs_inline_bulk_status(struct afs_fs_cursor *, struct afs_net *,
1371 struct afs_callback *, unsigned int, 1371 struct afs_callback *, unsigned int,
1372 struct afs_volsync *); 1372 struct afs_volsync *);
1373 1373
1374struct yfs_acl {
1375 struct afs_acl *acl; /* Dir/file/symlink ACL */
1376 struct afs_acl *vol_acl; /* Whole volume ACL */
1377 u32 inherit_flag; /* True if ACL is inherited from parent dir */
1378 u32 num_cleaned; /* Number of ACEs removed due to subject removal */
1379 unsigned int flags;
1380#define YFS_ACL_WANT_ACL 0x01 /* Set if caller wants ->acl */
1381#define YFS_ACL_WANT_VOL_ACL 0x02 /* Set if caller wants ->vol_acl */
1382};
1383
1384extern void yfs_free_opaque_acl(struct yfs_acl *);
1385extern struct yfs_acl *yfs_fs_fetch_opaque_acl(struct afs_fs_cursor *, unsigned int);
1386
1374/* 1387/*
1375 * Miscellaneous inline functions. 1388 * Miscellaneous inline functions.
1376 */ 1389 */
diff --git a/fs/afs/protocol_yfs.h b/fs/afs/protocol_yfs.h
index d443e2bfa094..915b9d10cdf3 100644
--- a/fs/afs/protocol_yfs.h
+++ b/fs/afs/protocol_yfs.h
@@ -31,9 +31,9 @@ enum YFS_CM_Operations {
31}; 31};
32 32
33enum YFS_FS_Operations { 33enum YFS_FS_Operations {
34 YFSFETCHACL = 64131, /* YFS Fetch file ACL */ 34 YFSFETCHACL = 64131, /* YFS Fetch file AFS3 ACL */
35 YFSFETCHSTATUS = 64132, /* YFS Fetch file status */ 35 YFSFETCHSTATUS = 64132, /* YFS Fetch file status */
36 YFSSTOREACL = 64134, /* YFS Store file ACL */ 36 YFSSTOREACL = 64134, /* YFS Store file AFS3 ACL */
37 YFSSTORESTATUS = 64135, /* YFS Store file status */ 37 YFSSTORESTATUS = 64135, /* YFS Store file status */
38 YFSREMOVEFILE = 64136, /* YFS Remove a file */ 38 YFSREMOVEFILE = 64136, /* YFS Remove a file */
39 YFSCREATEFILE = 64137, /* YFS Create a file */ 39 YFSCREATEFILE = 64137, /* YFS Create a file */
@@ -49,7 +49,7 @@ enum YFS_FS_Operations {
49 YFSRELEASELOCK = 64158, /* YFS Release a file lock */ 49 YFSRELEASELOCK = 64158, /* YFS Release a file lock */
50 YFSLOOKUP = 64161, /* YFS lookup file in directory */ 50 YFSLOOKUP = 64161, /* YFS lookup file in directory */
51 YFSFLUSHCPS = 64165, 51 YFSFLUSHCPS = 64165,
52 YFSFETCHOPAQUEACL = 64168, 52 YFSFETCHOPAQUEACL = 64168, /* YFS Fetch file YFS ACL */
53 YFSWHOAMI = 64170, 53 YFSWHOAMI = 64170,
54 YFSREMOVEACL = 64171, 54 YFSREMOVEACL = 64171,
55 YFSREMOVEFILE2 = 64173, 55 YFSREMOVEFILE2 = 64173,
diff --git a/fs/afs/xattr.c b/fs/afs/xattr.c
index 31db360947a6..a5c82b0ad539 100644
--- a/fs/afs/xattr.c
+++ b/fs/afs/xattr.c
@@ -19,7 +19,11 @@ static const char afs_xattr_list[] =
19 "afs.acl\0" 19 "afs.acl\0"
20 "afs.cell\0" 20 "afs.cell\0"
21 "afs.fid\0" 21 "afs.fid\0"
22 "afs.volume"; 22 "afs.volume\0"
23 "afs.yfs.acl\0"
24 "afs.yfs.acl_inherited\0"
25 "afs.yfs.acl_num_cleaned\0"
26 "afs.yfs.vol_acl";
23 27
24/* 28/*
25 * Retrieve a list of the supported xattrs. 29 * Retrieve a list of the supported xattrs.
@@ -134,6 +138,100 @@ static const struct xattr_handler afs_xattr_afs_acl_handler = {
134}; 138};
135 139
136/* 140/*
141 * Get a file's YFS ACL.
142 */
143static int afs_xattr_get_yfs(const struct xattr_handler *handler,
144 struct dentry *dentry,
145 struct inode *inode, const char *name,
146 void *buffer, size_t size)
147{
148 struct afs_fs_cursor fc;
149 struct afs_vnode *vnode = AFS_FS_I(inode);
150 struct yfs_acl *yacl = NULL;
151 struct key *key;
152 unsigned int flags = 0;
153 char buf[16], *data;
154 int which = 0, dsize, ret;
155
156 if (strcmp(name, "acl") == 0)
157 which = 0;
158 else if (strcmp(name, "acl_inherited") == 0)
159 which = 1;
160 else if (strcmp(name, "acl_num_cleaned") == 0)
161 which = 2;
162 else if (strcmp(name, "vol_acl") == 0)
163 which = 3;
164 else
165 return -EOPNOTSUPP;
166
167 if (which == 0)
168 flags |= YFS_ACL_WANT_ACL;
169 else if (which == 3)
170 flags |= YFS_ACL_WANT_VOL_ACL;
171
172 key = afs_request_key(vnode->volume->cell);
173 if (IS_ERR(key))
174 return PTR_ERR(key);
175
176 ret = -ERESTARTSYS;
177 if (afs_begin_vnode_operation(&fc, vnode, key)) {
178 while (afs_select_fileserver(&fc)) {
179 fc.cb_break = afs_calc_vnode_cb_break(vnode);
180 yacl = yfs_fs_fetch_opaque_acl(&fc, flags);
181 }
182
183 afs_check_for_remote_deletion(&fc, fc.vnode);
184 afs_vnode_commit_status(&fc, vnode, fc.cb_break);
185 ret = afs_end_vnode_operation(&fc);
186 }
187
188 if (ret == 0) {
189 switch (which) {
190 case 0:
191 data = yacl->acl->data;
192 dsize = yacl->acl->size;
193 break;
194 case 1:
195 data = buf;
196 dsize = snprintf(buf, sizeof(buf), "%u",
197 yacl->inherit_flag);
198 break;
199 case 2:
200 data = buf;
201 dsize = snprintf(buf, sizeof(buf), "%u",
202 yacl->num_cleaned);
203 break;
204 case 3:
205 data = yacl->vol_acl->data;
206 dsize = yacl->vol_acl->size;
207 break;
208 default:
209 ret = -EOPNOTSUPP;
210 goto out;
211 }
212
213 ret = dsize;
214 if (size > 0) {
215 if (dsize > size) {
216 ret = -ERANGE;
217 goto out;
218 }
219 memcpy(buffer, data, dsize);
220 }
221 }
222
223out:
224 yfs_free_opaque_acl(yacl);
225 key_put(key);
226 return ret;
227}
228
229static const struct xattr_handler afs_xattr_yfs_handler = {
230 .prefix = "afs.yfs.",
231 .get = afs_xattr_get_yfs,
232};
233
234/*
137 * Get the name of the cell on which a file resides. 235 * Get the name of the cell on which a file resides.
138 */ 236 */
139static int afs_xattr_get_cell(const struct xattr_handler *handler, 237static int afs_xattr_get_cell(const struct xattr_handler *handler,
@@ -227,5 +325,6 @@ const struct xattr_handler *afs_xattr_handlers[] = {
227 &afs_xattr_afs_cell_handler, 325 &afs_xattr_afs_cell_handler,
228 &afs_xattr_afs_fid_handler, 326 &afs_xattr_afs_fid_handler,
229 &afs_xattr_afs_volume_handler, 327 &afs_xattr_afs_volume_handler,
328 &afs_xattr_yfs_handler, /* afs.yfs. prefix */
230 NULL 329 NULL
231}; 330};
diff --git a/fs/afs/yfsclient.c b/fs/afs/yfsclient.c
index 055840aa07f6..13eafa764d71 100644
--- a/fs/afs/yfsclient.c
+++ b/fs/afs/yfsclient.c
@@ -2204,3 +2204,191 @@ int yfs_fs_inline_bulk_status(struct afs_fs_cursor *fc,
2204 afs_make_call(&fc->ac, call, GFP_NOFS); 2204 afs_make_call(&fc->ac, call, GFP_NOFS);
2205 return afs_wait_for_call_to_complete(call, &fc->ac); 2205 return afs_wait_for_call_to_complete(call, &fc->ac);
2206} 2206}
2207
2208/*
2209 * Deliver reply data to an YFS.FetchOpaqueACL.
2210 */
2211static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call)
2212{
2213 struct afs_volsync *volsync = call->reply[2];
2214 struct afs_vnode *vnode = call->reply[1];
2215 struct yfs_acl *yacl = call->reply[0];
2216 struct afs_acl *acl;
2217 const __be32 *bp;
2218 unsigned int size;
2219 int ret;
2220
2221 _enter("{%u}", call->unmarshall);
2222
2223 switch (call->unmarshall) {
2224 case 0:
2225 afs_extract_to_tmp(call);
2226 call->unmarshall++;
2227
2228 /* Extract the file ACL length */
2229 case 1:
2230 ret = afs_extract_data(call, true);
2231 if (ret < 0)
2232 return ret;
2233
2234 size = call->count2 = ntohl(call->tmp);
2235 size = round_up(size, 4);
2236
2237 if (yacl->flags & YFS_ACL_WANT_ACL) {
2238 acl = kmalloc(struct_size(acl, data, size), GFP_KERNEL);
2239 if (!acl)
2240 return -ENOMEM;
2241 yacl->acl = acl;
2242 acl->size = call->count2;
2243 afs_extract_begin(call, acl->data, size);
2244 } else {
2245 iov_iter_discard(&call->iter, READ, size);
2246 }
2247 call->unmarshall++;
2248
2249 /* Extract the file ACL */
2250 case 2:
2251 ret = afs_extract_data(call, true);
2252 if (ret < 0)
2253 return ret;
2254
2255 afs_extract_to_tmp(call);
2256 call->unmarshall++;
2257
2258 /* Extract the volume ACL length */
2259 case 3:
2260 ret = afs_extract_data(call, true);
2261 if (ret < 0)
2262 return ret;
2263
2264 size = call->count2 = ntohl(call->tmp);
2265 size = round_up(size, 4);
2266
2267 if (yacl->flags & YFS_ACL_WANT_VOL_ACL) {
2268 acl = kmalloc(struct_size(acl, data, size), GFP_KERNEL);
2269 if (!acl)
2270 return -ENOMEM;
2271 yacl->vol_acl = acl;
2272 acl->size = call->count2;
2273 afs_extract_begin(call, acl->data, size);
2274 } else {
2275 iov_iter_discard(&call->iter, READ, size);
2276 }
2277 call->unmarshall++;
2278
2279 /* Extract the volume ACL */
2280 case 4:
2281 ret = afs_extract_data(call, true);
2282 if (ret < 0)
2283 return ret;
2284
2285 afs_extract_to_buf(call,
2286 sizeof(__be32) * 2 +
2287 sizeof(struct yfs_xdr_YFSFetchStatus) +
2288 sizeof(struct yfs_xdr_YFSVolSync));
2289 call->unmarshall++;
2290
2291 /* extract the metadata */
2292 case 5:
2293 ret = afs_extract_data(call, false);
2294 if (ret < 0)
2295 return ret;
2296
2297 bp = call->buffer;
2298 yacl->inherit_flag = ntohl(*bp++);
2299 yacl->num_cleaned = ntohl(*bp++);
2300 ret = yfs_decode_status(call, &bp, &vnode->status, vnode,
2301 &call->expected_version, NULL);
2302 if (ret < 0)
2303 return ret;
2304 xdr_decode_YFSVolSync(&bp, volsync);
2305
2306 call->unmarshall++;
2307
2308 case 6:
2309 break;
2310 }
2311
2312 _leave(" = 0 [done]");
2313 return 0;
2314}
2315
2316void yfs_free_opaque_acl(struct yfs_acl *yacl)
2317{
2318 if (yacl) {
2319 kfree(yacl->acl);
2320 kfree(yacl->vol_acl);
2321 kfree(yacl);
2322 }
2323}
2324
2325static void yfs_destroy_fs_fetch_opaque_acl(struct afs_call *call)
2326{
2327 yfs_free_opaque_acl(call->reply[0]);
2328 afs_flat_call_destructor(call);
2329}
2330
2331/*
2332 * YFS.FetchOpaqueACL operation type
2333 */
2334static const struct afs_call_type yfs_RXYFSFetchOpaqueACL = {
2335 .name = "YFS.FetchOpaqueACL",
2336 .op = yfs_FS_FetchOpaqueACL,
2337 .deliver = yfs_deliver_fs_fetch_opaque_acl,
2338 .destructor = yfs_destroy_fs_fetch_opaque_acl,
2339};
2340
2341/*
2342 * Fetch the YFS advanced ACLs for a file.
2343 */
2344struct yfs_acl *yfs_fs_fetch_opaque_acl(struct afs_fs_cursor *fc,
2345 unsigned int flags)
2346{
2347 struct afs_vnode *vnode = fc->vnode;
2348 struct afs_call *call;
2349 struct yfs_acl *yacl;
2350 struct afs_net *net = afs_v2net(vnode);
2351 __be32 *bp;
2352
2353 _enter(",%x,{%llx:%llu},,",
2354 key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
2355
2356 call = afs_alloc_flat_call(net, &yfs_RXYFSFetchOpaqueACL,
2357 sizeof(__be32) * 2 +
2358 sizeof(struct yfs_xdr_YFSFid),
2359 sizeof(__be32) * 2 +
2360 sizeof(struct yfs_xdr_YFSFetchStatus) +
2361 sizeof(struct yfs_xdr_YFSVolSync));
2362 if (!call)
2363 goto nomem;
2364
2365 yacl = kzalloc(sizeof(struct yfs_acl), GFP_KERNEL);
2366 if (!yacl)
2367 goto nomem_call;
2368
2369 yacl->flags = flags;
2370 call->key = fc->key;
2371 call->reply[0] = yacl;
2372 call->reply[1] = vnode;
2373 call->reply[2] = NULL; /* volsync */
2374 call->ret_reply0 = true;
2375
2376 /* marshall the parameters */
2377 bp = call->request;
2378 bp = xdr_encode_u32(bp, YFSFETCHOPAQUEACL);
2379 bp = xdr_encode_u32(bp, 0); /* RPC flags */
2380 bp = xdr_encode_YFSFid(bp, &vnode->fid);
2381 yfs_check_req(call, bp);
2382
2383 call->cb_break = fc->cb_break;
2384 afs_use_fs_server(call, fc->cbi);
2385 trace_afs_make_fs_call(call, &vnode->fid);
2386 afs_make_call(&fc->ac, call, GFP_KERNEL);
2387 return (struct yfs_acl *)afs_wait_for_call_to_complete(call, &fc->ac);
2388
2389nomem_call:
2390 afs_put_call(call);
2391nomem:
2392 fc->ac.error = -ENOMEM;
2393 return ERR_PTR(-ENOMEM);
2394}