diff options
| author | Joe Gorse <jhgorse@gmail.com> | 2019-04-25 09:26:52 -0400 |
|---|---|---|
| committer | David Howells <dhowells@redhat.com> | 2019-05-07 11:48:44 -0400 |
| commit | b10494af4989d2d20679d0e3b7d1a45c2f8f8f1a (patch) | |
| tree | 27a9fcdea021ddcb324da97695aa2efb8326ff69 | |
| parent | 260f082bae6dcf70aeae2cc3e24aecb55bdb1c99 (diff) | |
afs: implement acl setting
Implements the setting of ACLs in AFS by means of setting the
afs.acl extended attribute on the file.
Signed-off-by: Joe Gorse <jhgorse@gmail.com>
Signed-off-by: David Howells <dhowells@redhat.com>
| -rw-r--r-- | fs/afs/afs_fs.h | 1 | ||||
| -rw-r--r-- | fs/afs/fsclient.c | 61 | ||||
| -rw-r--r-- | fs/afs/internal.h | 1 | ||||
| -rw-r--r-- | fs/afs/xattr.c | 52 | ||||
| -rw-r--r-- | include/trace/events/afs.h | 1 |
5 files changed, 110 insertions, 6 deletions
diff --git a/fs/afs/afs_fs.h b/fs/afs/afs_fs.h index 4df1f1eec0ab..18a54ca422f8 100644 --- a/fs/afs/afs_fs.h +++ b/fs/afs/afs_fs.h | |||
| @@ -20,6 +20,7 @@ enum AFS_FS_Operations { | |||
| 20 | FSFETCHACL = 131, /* AFS Fetch file ACL */ | 20 | FSFETCHACL = 131, /* AFS Fetch file ACL */ |
| 21 | FSFETCHSTATUS = 132, /* AFS Fetch file status */ | 21 | FSFETCHSTATUS = 132, /* AFS Fetch file status */ |
| 22 | FSSTOREDATA = 133, /* AFS Store file data */ | 22 | FSSTOREDATA = 133, /* AFS Store file data */ |
| 23 | FSSTOREACL = 134, /* AFS Store file ACL */ | ||
| 23 | FSSTORESTATUS = 135, /* AFS Store file status */ | 24 | FSSTORESTATUS = 135, /* AFS Store file status */ |
| 24 | FSREMOVEFILE = 136, /* AFS Remove a file */ | 25 | FSREMOVEFILE = 136, /* AFS Remove a file */ |
| 25 | FSCREATEFILE = 137, /* AFS Create a file */ | 26 | FSCREATEFILE = 137, /* AFS Create a file */ |
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c index 283f486c59f4..7f1722b9e432 100644 --- a/fs/afs/fsclient.c +++ b/fs/afs/fsclient.c | |||
| @@ -836,9 +836,10 @@ int afs_fs_create(struct afs_fs_cursor *fc, | |||
| 836 | } | 836 | } |
| 837 | 837 | ||
| 838 | /* | 838 | /* |
| 839 | * deliver reply data to an FS.RemoveFile or FS.RemoveDir | 839 | * Deliver reply data to any operation that returns file status and volume |
| 840 | * sync. | ||
| 840 | */ | 841 | */ |
| 841 | static int afs_deliver_fs_remove(struct afs_call *call) | 842 | static int afs_deliver_fs_status_and_vol(struct afs_call *call) |
| 842 | { | 843 | { |
| 843 | struct afs_vnode *vnode = call->reply[0]; | 844 | struct afs_vnode *vnode = call->reply[0]; |
| 844 | const __be32 *bp; | 845 | const __be32 *bp; |
| @@ -868,14 +869,14 @@ static int afs_deliver_fs_remove(struct afs_call *call) | |||
| 868 | static const struct afs_call_type afs_RXFSRemoveFile = { | 869 | static const struct afs_call_type afs_RXFSRemoveFile = { |
| 869 | .name = "FS.RemoveFile", | 870 | .name = "FS.RemoveFile", |
| 870 | .op = afs_FS_RemoveFile, | 871 | .op = afs_FS_RemoveFile, |
| 871 | .deliver = afs_deliver_fs_remove, | 872 | .deliver = afs_deliver_fs_status_and_vol, |
| 872 | .destructor = afs_flat_call_destructor, | 873 | .destructor = afs_flat_call_destructor, |
| 873 | }; | 874 | }; |
| 874 | 875 | ||
| 875 | static const struct afs_call_type afs_RXFSRemoveDir = { | 876 | static const struct afs_call_type afs_RXFSRemoveDir = { |
| 876 | .name = "FS.RemoveDir", | 877 | .name = "FS.RemoveDir", |
| 877 | .op = afs_FS_RemoveDir, | 878 | .op = afs_FS_RemoveDir, |
| 878 | .deliver = afs_deliver_fs_remove, | 879 | .deliver = afs_deliver_fs_status_and_vol, |
| 879 | .destructor = afs_flat_call_destructor, | 880 | .destructor = afs_flat_call_destructor, |
| 880 | }; | 881 | }; |
| 881 | 882 | ||
| @@ -2513,3 +2514,55 @@ struct afs_acl *afs_fs_fetch_acl(struct afs_fs_cursor *fc) | |||
| 2513 | afs_make_call(&fc->ac, call, GFP_KERNEL); | 2514 | afs_make_call(&fc->ac, call, GFP_KERNEL); |
| 2514 | return (struct afs_acl *)afs_wait_for_call_to_complete(call, &fc->ac); | 2515 | return (struct afs_acl *)afs_wait_for_call_to_complete(call, &fc->ac); |
| 2515 | } | 2516 | } |
| 2517 | |||
| 2518 | /* | ||
| 2519 | * FS.StoreACL operation type | ||
| 2520 | */ | ||
| 2521 | static const struct afs_call_type afs_RXFSStoreACL = { | ||
| 2522 | .name = "FS.StoreACL", | ||
| 2523 | .op = afs_FS_StoreACL, | ||
| 2524 | .deliver = afs_deliver_fs_status_and_vol, | ||
| 2525 | .destructor = afs_flat_call_destructor, | ||
| 2526 | }; | ||
| 2527 | |||
| 2528 | /* | ||
| 2529 | * Fetch the ACL for a file. | ||
| 2530 | */ | ||
| 2531 | int afs_fs_store_acl(struct afs_fs_cursor *fc, const struct afs_acl *acl) | ||
| 2532 | { | ||
| 2533 | struct afs_vnode *vnode = fc->vnode; | ||
| 2534 | struct afs_call *call; | ||
| 2535 | struct afs_net *net = afs_v2net(vnode); | ||
| 2536 | size_t size; | ||
| 2537 | __be32 *bp; | ||
| 2538 | |||
| 2539 | _enter(",%x,{%llx:%llu},,", | ||
| 2540 | key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); | ||
| 2541 | |||
| 2542 | size = round_up(acl->size, 4); | ||
| 2543 | call = afs_alloc_flat_call(net, &afs_RXFSStoreACL, | ||
| 2544 | 5 * 4 + size, (21 + 6) * 4); | ||
| 2545 | if (!call) { | ||
| 2546 | fc->ac.error = -ENOMEM; | ||
| 2547 | return -ENOMEM; | ||
| 2548 | } | ||
| 2549 | |||
| 2550 | call->key = fc->key; | ||
| 2551 | call->reply[0] = vnode; | ||
| 2552 | call->reply[2] = NULL; /* volsync */ | ||
| 2553 | |||
| 2554 | /* marshall the parameters */ | ||
| 2555 | bp = call->request; | ||
| 2556 | bp[0] = htonl(FSSTOREACL); | ||
| 2557 | bp[1] = htonl(vnode->fid.vid); | ||
| 2558 | bp[2] = htonl(vnode->fid.vnode); | ||
| 2559 | bp[3] = htonl(vnode->fid.unique); | ||
| 2560 | bp[4] = htonl(acl->size); | ||
| 2561 | memcpy(&bp[5], acl->data, acl->size); | ||
| 2562 | if (acl->size != size) | ||
| 2563 | memset((void *)&bp[5] + acl->size, 0, size - acl->size); | ||
| 2564 | |||
| 2565 | trace_afs_make_fs_call(call, &vnode->fid); | ||
| 2566 | afs_make_call(&fc->ac, call, GFP_KERNEL); | ||
| 2567 | return afs_wait_for_call_to_complete(call, &fc->ac); | ||
| 2568 | } | ||
diff --git a/fs/afs/internal.h b/fs/afs/internal.h index 683b802c20ea..5269824244c6 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h | |||
| @@ -983,6 +983,7 @@ struct afs_acl { | |||
| 983 | }; | 983 | }; |
| 984 | 984 | ||
| 985 | extern struct afs_acl *afs_fs_fetch_acl(struct afs_fs_cursor *); | 985 | extern struct afs_acl *afs_fs_fetch_acl(struct afs_fs_cursor *); |
| 986 | extern int afs_fs_store_acl(struct afs_fs_cursor *, const struct afs_acl *); | ||
| 986 | 987 | ||
| 987 | /* | 988 | /* |
| 988 | * fs_probe.c | 989 | * fs_probe.c |
diff --git a/fs/afs/xattr.c b/fs/afs/xattr.c index b7d3d714d8ff..31db360947a6 100644 --- a/fs/afs/xattr.c +++ b/fs/afs/xattr.c | |||
| @@ -80,9 +80,57 @@ static int afs_xattr_get_acl(const struct xattr_handler *handler, | |||
| 80 | return ret; | 80 | return ret; |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | /* | ||
| 84 | * Set a file's AFS3 ACL. | ||
| 85 | */ | ||
| 86 | static int afs_xattr_set_acl(const struct xattr_handler *handler, | ||
| 87 | struct dentry *dentry, | ||
| 88 | struct inode *inode, const char *name, | ||
| 89 | const void *buffer, size_t size, int flags) | ||
| 90 | { | ||
| 91 | struct afs_fs_cursor fc; | ||
| 92 | struct afs_vnode *vnode = AFS_FS_I(inode); | ||
| 93 | struct afs_acl *acl = NULL; | ||
| 94 | struct key *key; | ||
| 95 | int ret; | ||
| 96 | |||
| 97 | if (flags == XATTR_CREATE) | ||
| 98 | return -EINVAL; | ||
| 99 | |||
| 100 | key = afs_request_key(vnode->volume->cell); | ||
| 101 | if (IS_ERR(key)) | ||
| 102 | return PTR_ERR(key); | ||
| 103 | |||
| 104 | acl = kmalloc(sizeof(*acl) + size, GFP_KERNEL); | ||
| 105 | if (!acl) { | ||
| 106 | key_put(key); | ||
| 107 | return -ENOMEM; | ||
| 108 | } | ||
| 109 | |||
| 110 | acl->size = size; | ||
| 111 | memcpy(acl->data, buffer, size); | ||
| 112 | |||
| 113 | ret = -ERESTARTSYS; | ||
| 114 | if (afs_begin_vnode_operation(&fc, vnode, key)) { | ||
| 115 | while (afs_select_fileserver(&fc)) { | ||
| 116 | fc.cb_break = afs_calc_vnode_cb_break(vnode); | ||
| 117 | afs_fs_store_acl(&fc, acl); | ||
| 118 | } | ||
| 119 | |||
| 120 | afs_check_for_remote_deletion(&fc, fc.vnode); | ||
| 121 | afs_vnode_commit_status(&fc, vnode, fc.cb_break); | ||
| 122 | ret = afs_end_vnode_operation(&fc); | ||
| 123 | } | ||
| 124 | |||
| 125 | kfree(acl); | ||
| 126 | key_put(key); | ||
| 127 | return ret; | ||
| 128 | } | ||
| 129 | |||
| 83 | static const struct xattr_handler afs_xattr_afs_acl_handler = { | 130 | static const struct xattr_handler afs_xattr_afs_acl_handler = { |
| 84 | .name = "afs.acl", | 131 | .name = "afs.acl", |
| 85 | .get = afs_xattr_get_acl, | 132 | .get = afs_xattr_get_acl, |
| 133 | .set = afs_xattr_set_acl, | ||
| 86 | }; | 134 | }; |
| 87 | 135 | ||
| 88 | /* | 136 | /* |
diff --git a/include/trace/events/afs.h b/include/trace/events/afs.h index 25c2e089c6ea..562f854ac4bf 100644 --- a/include/trace/events/afs.h +++ b/include/trace/events/afs.h | |||
| @@ -36,6 +36,7 @@ enum afs_fs_operation { | |||
| 36 | afs_FS_FetchACL = 131, /* AFS Fetch file ACL */ | 36 | afs_FS_FetchACL = 131, /* AFS Fetch file ACL */ |
| 37 | afs_FS_FetchStatus = 132, /* AFS Fetch file status */ | 37 | afs_FS_FetchStatus = 132, /* AFS Fetch file status */ |
| 38 | afs_FS_StoreData = 133, /* AFS Store file data */ | 38 | afs_FS_StoreData = 133, /* AFS Store file data */ |
| 39 | afs_FS_StoreACL = 134, /* AFS Store file ACL */ | ||
| 39 | afs_FS_StoreStatus = 135, /* AFS Store file status */ | 40 | afs_FS_StoreStatus = 135, /* AFS Store file status */ |
| 40 | afs_FS_RemoveFile = 136, /* AFS Remove a file */ | 41 | afs_FS_RemoveFile = 136, /* AFS Remove a file */ |
| 41 | afs_FS_CreateFile = 137, /* AFS Create a file */ | 42 | afs_FS_CreateFile = 137, /* AFS Create a file */ |
