Skip to content

Commit 260f082

Browse files
committed
afs: Get an AFS3 ACL as an xattr
Implement an xattr on AFS files called "afs.acl" that retrieves a file's ACL. It returns the raw AFS3 ACL from the result of calling FS.FetchACL, leaving any interpretation to userspace. Note that whilst YFS servers will respond to FS.FetchACL, this will render a more-advanced YFS ACL down. Use "afs.yfs.acl" instead for that. Signed-off-by: David Howells <[email protected]>
1 parent a2f611a commit 260f082

File tree

5 files changed

+184
-0
lines changed

5 files changed

+184
-0
lines changed

fs/afs/afs_fs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
enum AFS_FS_Operations {
1919
FSFETCHDATA = 130, /* AFS Fetch file data */
20+
FSFETCHACL = 131, /* AFS Fetch file ACL */
2021
FSFETCHSTATUS = 132, /* AFS Fetch file status */
2122
FSSTOREDATA = 133, /* AFS Store file data */
2223
FSSTORESTATUS = 135, /* AFS Store file status */

fs/afs/fsclient.c

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2391,3 +2391,125 @@ int afs_fs_inline_bulk_status(struct afs_fs_cursor *fc,
23912391
afs_make_call(&fc->ac, call, GFP_NOFS);
23922392
return afs_wait_for_call_to_complete(call, &fc->ac);
23932393
}
2394+
2395+
/*
2396+
* deliver reply data to an FS.FetchACL
2397+
*/
2398+
static int afs_deliver_fs_fetch_acl(struct afs_call *call)
2399+
{
2400+
struct afs_vnode *vnode = call->reply[1];
2401+
struct afs_acl *acl;
2402+
const __be32 *bp;
2403+
unsigned int size;
2404+
int ret;
2405+
2406+
_enter("{%u}", call->unmarshall);
2407+
2408+
switch (call->unmarshall) {
2409+
case 0:
2410+
afs_extract_to_tmp(call);
2411+
call->unmarshall++;
2412+
2413+
/* extract the returned data length */
2414+
case 1:
2415+
ret = afs_extract_data(call, true);
2416+
if (ret < 0)
2417+
return ret;
2418+
2419+
size = call->count2 = ntohl(call->tmp);
2420+
size = round_up(size, 4);
2421+
2422+
acl = kmalloc(struct_size(acl, data, size), GFP_KERNEL);
2423+
if (!acl)
2424+
return -ENOMEM;
2425+
call->reply[0] = acl;
2426+
acl->size = call->count2;
2427+
afs_extract_begin(call, acl->data, size);
2428+
call->unmarshall++;
2429+
2430+
/* extract the returned data */
2431+
case 2:
2432+
ret = afs_extract_data(call, true);
2433+
if (ret < 0)
2434+
return ret;
2435+
2436+
afs_extract_to_buf(call, (21 + 6) * 4);
2437+
call->unmarshall++;
2438+
2439+
/* extract the metadata */
2440+
case 3:
2441+
ret = afs_extract_data(call, false);
2442+
if (ret < 0)
2443+
return ret;
2444+
2445+
bp = call->buffer;
2446+
ret = afs_decode_status(call, &bp, &vnode->status, vnode,
2447+
&vnode->status.data_version, NULL);
2448+
if (ret < 0)
2449+
return ret;
2450+
xdr_decode_AFSVolSync(&bp, call->reply[2]);
2451+
2452+
call->unmarshall++;
2453+
2454+
case 4:
2455+
break;
2456+
}
2457+
2458+
_leave(" = 0 [done]");
2459+
return 0;
2460+
}
2461+
2462+
static void afs_destroy_fs_fetch_acl(struct afs_call *call)
2463+
{
2464+
kfree(call->reply[0]);
2465+
afs_flat_call_destructor(call);
2466+
}
2467+
2468+
/*
2469+
* FS.FetchACL operation type
2470+
*/
2471+
static const struct afs_call_type afs_RXFSFetchACL = {
2472+
.name = "FS.FetchACL",
2473+
.op = afs_FS_FetchACL,
2474+
.deliver = afs_deliver_fs_fetch_acl,
2475+
.destructor = afs_destroy_fs_fetch_acl,
2476+
};
2477+
2478+
/*
2479+
* Fetch the ACL for a file.
2480+
*/
2481+
struct afs_acl *afs_fs_fetch_acl(struct afs_fs_cursor *fc)
2482+
{
2483+
struct afs_vnode *vnode = fc->vnode;
2484+
struct afs_call *call;
2485+
struct afs_net *net = afs_v2net(vnode);
2486+
__be32 *bp;
2487+
2488+
_enter(",%x,{%llx:%llu},,",
2489+
key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
2490+
2491+
call = afs_alloc_flat_call(net, &afs_RXFSFetchACL, 16, (21 + 6) * 4);
2492+
if (!call) {
2493+
fc->ac.error = -ENOMEM;
2494+
return ERR_PTR(-ENOMEM);
2495+
}
2496+
2497+
call->key = fc->key;
2498+
call->reply[0] = NULL;
2499+
call->reply[1] = vnode;
2500+
call->reply[2] = NULL; /* volsync */
2501+
call->ret_reply0 = true;
2502+
2503+
/* marshall the parameters */
2504+
bp = call->request;
2505+
bp[0] = htonl(FSFETCHACL);
2506+
bp[1] = htonl(vnode->fid.vid);
2507+
bp[2] = htonl(vnode->fid.vnode);
2508+
bp[3] = htonl(vnode->fid.unique);
2509+
2510+
call->cb_break = fc->cb_break;
2511+
afs_use_fs_server(call, fc->cbi);
2512+
trace_afs_make_fs_call(call, &vnode->fid);
2513+
afs_make_call(&fc->ac, call, GFP_KERNEL);
2514+
return (struct afs_acl *)afs_wait_for_call_to_complete(call, &fc->ac);
2515+
}

fs/afs/internal.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -977,6 +977,13 @@ extern int afs_fs_fetch_status(struct afs_fs_cursor *, struct afs_net *,
977977
struct afs_fid *, struct afs_file_status *,
978978
struct afs_callback *, struct afs_volsync *);
979979

980+
struct afs_acl {
981+
u32 size;
982+
u8 data[];
983+
};
984+
985+
extern struct afs_acl *afs_fs_fetch_acl(struct afs_fs_cursor *);
986+
980987
/*
981988
* fs_probe.c
982989
*/

fs/afs/xattr.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "internal.h"
1717

1818
static const char afs_xattr_list[] =
19+
"afs.acl\0"
1920
"afs.cell\0"
2021
"afs.fid\0"
2122
"afs.volume";
@@ -33,6 +34,57 @@ ssize_t afs_listxattr(struct dentry *dentry, char *buffer, size_t size)
3334
return sizeof(afs_xattr_list);
3435
}
3536

37+
/*
38+
* Get a file's ACL.
39+
*/
40+
static int afs_xattr_get_acl(const struct xattr_handler *handler,
41+
struct dentry *dentry,
42+
struct inode *inode, const char *name,
43+
void *buffer, size_t size)
44+
{
45+
struct afs_fs_cursor fc;
46+
struct afs_vnode *vnode = AFS_FS_I(inode);
47+
struct afs_acl *acl = NULL;
48+
struct key *key;
49+
int ret;
50+
51+
key = afs_request_key(vnode->volume->cell);
52+
if (IS_ERR(key))
53+
return PTR_ERR(key);
54+
55+
ret = -ERESTARTSYS;
56+
if (afs_begin_vnode_operation(&fc, vnode, key)) {
57+
while (afs_select_fileserver(&fc)) {
58+
fc.cb_break = afs_calc_vnode_cb_break(vnode);
59+
acl = afs_fs_fetch_acl(&fc);
60+
}
61+
62+
afs_check_for_remote_deletion(&fc, fc.vnode);
63+
afs_vnode_commit_status(&fc, vnode, fc.cb_break);
64+
ret = afs_end_vnode_operation(&fc);
65+
}
66+
67+
if (ret == 0) {
68+
ret = acl->size;
69+
if (size > 0) {
70+
ret = -ERANGE;
71+
if (acl->size > size)
72+
return -ERANGE;
73+
memcpy(buffer, acl->data, acl->size);
74+
ret = acl->size;
75+
}
76+
kfree(acl);
77+
}
78+
79+
key_put(key);
80+
return ret;
81+
}
82+
83+
static const struct xattr_handler afs_xattr_afs_acl_handler = {
84+
.name = "afs.acl",
85+
.get = afs_xattr_get_acl,
86+
};
87+
3688
/*
3789
* Get the name of the cell on which a file resides.
3890
*/
@@ -123,6 +175,7 @@ static const struct xattr_handler afs_xattr_afs_volume_handler = {
123175
};
124176

125177
const struct xattr_handler *afs_xattr_handlers[] = {
178+
&afs_xattr_afs_acl_handler,
126179
&afs_xattr_afs_cell_handler,
127180
&afs_xattr_afs_fid_handler,
128181
&afs_xattr_afs_volume_handler,

include/trace/events/afs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ enum afs_call_trace {
3333

3434
enum afs_fs_operation {
3535
afs_FS_FetchData = 130, /* AFS Fetch file data */
36+
afs_FS_FetchACL = 131, /* AFS Fetch file ACL */
3637
afs_FS_FetchStatus = 132, /* AFS Fetch file status */
3738
afs_FS_StoreData = 133, /* AFS Store file data */
3839
afs_FS_StoreStatus = 135, /* AFS Store file status */

0 commit comments

Comments
 (0)