b4d0d230ccfb5 (Thomas Gleixner 2019-05-20 19:08:01 +0200 1) // SPDX-License-Identifier: GPL-2.0-or-later
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 2) /* Extended attribute handling for AFS. We use xattrs to get and set metadata
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 3) * instead of providing pioctl().
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 4) *
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 5) * Copyright (C) 2017 Red Hat, Inc. All Rights Reserved.
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 6) * Written by David Howells (dhowells@redhat.com)
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 7) */
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 8)
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 9) #include <linux/slab.h>
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 10) #include <linux/fs.h>
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 11) #include <linux/xattr.h>
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 12) #include "internal.h"
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 13)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 14) /*
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 15) * Deal with the result of a successful fetch ACL operation.
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 16) */
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 17) static void afs_acl_success(struct afs_operation *op)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 18) {
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 19) afs_vnode_commit_status(op, &op->file[0]);
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 20) }
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 21)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 22) static void afs_acl_put(struct afs_operation *op)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 23) {
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 24) kfree(op->acl);
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 25) }
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 26)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 27) static const struct afs_operation_ops afs_fetch_acl_operation = {
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 28) .issue_afs_rpc = afs_fs_fetch_acl,
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 29) .success = afs_acl_success,
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 30) .put = afs_acl_put,
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 31) };
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 32)
260f082bae6dc (David Howells 2019-04-25 14:26:52 +0100 33) /*
260f082bae6dc (David Howells 2019-04-25 14:26:52 +0100 34) * Get a file's ACL.
260f082bae6dc (David Howells 2019-04-25 14:26:52 +0100 35) */
260f082bae6dc (David Howells 2019-04-25 14:26:52 +0100 36) static int afs_xattr_get_acl(const struct xattr_handler *handler,
260f082bae6dc (David Howells 2019-04-25 14:26:52 +0100 37) struct dentry *dentry,
260f082bae6dc (David Howells 2019-04-25 14:26:52 +0100 38) struct inode *inode, const char *name,
260f082bae6dc (David Howells 2019-04-25 14:26:52 +0100 39) void *buffer, size_t size)
260f082bae6dc (David Howells 2019-04-25 14:26:52 +0100 40) {
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 41) struct afs_operation *op;
260f082bae6dc (David Howells 2019-04-25 14:26:52 +0100 42) struct afs_vnode *vnode = AFS_FS_I(inode);
260f082bae6dc (David Howells 2019-04-25 14:26:52 +0100 43) struct afs_acl *acl = NULL;
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 44) int ret;
a58823ac45896 (David Howells 2019-05-09 15:16:10 +0100 45)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 46) op = afs_alloc_operation(NULL, vnode->volume);
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 47) if (IS_ERR(op))
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 48) return -ENOMEM;
260f082bae6dc (David Howells 2019-04-25 14:26:52 +0100 49)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 50) afs_op_set_vnode(op, 0, vnode);
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 51) op->ops = &afs_fetch_acl_operation;
260f082bae6dc (David Howells 2019-04-25 14:26:52 +0100 52)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 53) afs_begin_vnode_operation(op);
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 54) afs_wait_for_operation(op);
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 55) acl = op->acl;
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 56) op->acl = NULL;
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 57) ret = afs_put_operation(op);
260f082bae6dc (David Howells 2019-04-25 14:26:52 +0100 58)
260f082bae6dc (David Howells 2019-04-25 14:26:52 +0100 59) if (ret == 0) {
260f082bae6dc (David Howells 2019-04-25 14:26:52 +0100 60) ret = acl->size;
260f082bae6dc (David Howells 2019-04-25 14:26:52 +0100 61) if (size > 0) {
cc1dd5c85cb70 (David Howells 2019-05-12 08:05:10 +0100 62) if (acl->size <= size)
cc1dd5c85cb70 (David Howells 2019-05-12 08:05:10 +0100 63) memcpy(buffer, acl->data, acl->size);
cc1dd5c85cb70 (David Howells 2019-05-12 08:05:10 +0100 64) else
248c944e2159d (Dan Carpenter 2020-08-24 11:58:12 +0300 65) ret = -ERANGE;
260f082bae6dc (David Howells 2019-04-25 14:26:52 +0100 66) }
260f082bae6dc (David Howells 2019-04-25 14:26:52 +0100 67) }
260f082bae6dc (David Howells 2019-04-25 14:26:52 +0100 68)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 69) kfree(acl);
260f082bae6dc (David Howells 2019-04-25 14:26:52 +0100 70) return ret;
260f082bae6dc (David Howells 2019-04-25 14:26:52 +0100 71) }
260f082bae6dc (David Howells 2019-04-25 14:26:52 +0100 72)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 73) static bool afs_make_acl(struct afs_operation *op,
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 74) const void *buffer, size_t size)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 75) {
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 76) struct afs_acl *acl;
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 77)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 78) acl = kmalloc(sizeof(*acl) + size, GFP_KERNEL);
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 79) if (!acl) {
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 80) afs_op_nomem(op);
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 81) return false;
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 82) }
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 83)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 84) acl->size = size;
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 85) memcpy(acl->data, buffer, size);
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 86) op->acl = acl;
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 87) return true;
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 88) }
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 89)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 90) static const struct afs_operation_ops afs_store_acl_operation = {
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 91) .issue_afs_rpc = afs_fs_store_acl,
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 92) .success = afs_acl_success,
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 93) .put = afs_acl_put,
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 94) };
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 95)
b10494af4989d (Joe Gorse 2019-04-25 14:26:52 +0100 96) /*
b10494af4989d (Joe Gorse 2019-04-25 14:26:52 +0100 97) * Set a file's AFS3 ACL.
b10494af4989d (Joe Gorse 2019-04-25 14:26:52 +0100 98) */
b10494af4989d (Joe Gorse 2019-04-25 14:26:52 +0100 99) static int afs_xattr_set_acl(const struct xattr_handler *handler,
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 100) struct user_namespace *mnt_userns,
b10494af4989d (Joe Gorse 2019-04-25 14:26:52 +0100 101) struct dentry *dentry,
b10494af4989d (Joe Gorse 2019-04-25 14:26:52 +0100 102) struct inode *inode, const char *name,
b10494af4989d (Joe Gorse 2019-04-25 14:26:52 +0100 103) const void *buffer, size_t size, int flags)
b10494af4989d (Joe Gorse 2019-04-25 14:26:52 +0100 104) {
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 105) struct afs_operation *op;
b10494af4989d (Joe Gorse 2019-04-25 14:26:52 +0100 106) struct afs_vnode *vnode = AFS_FS_I(inode);
b10494af4989d (Joe Gorse 2019-04-25 14:26:52 +0100 107)
b10494af4989d (Joe Gorse 2019-04-25 14:26:52 +0100 108) if (flags == XATTR_CREATE)
b10494af4989d (Joe Gorse 2019-04-25 14:26:52 +0100 109) return -EINVAL;
b10494af4989d (Joe Gorse 2019-04-25 14:26:52 +0100 110)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 111) op = afs_alloc_operation(NULL, vnode->volume);
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 112) if (IS_ERR(op))
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 113) return -ENOMEM;
a58823ac45896 (David Howells 2019-05-09 15:16:10 +0100 114)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 115) afs_op_set_vnode(op, 0, vnode);
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 116) if (!afs_make_acl(op, buffer, size))
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 117) return afs_put_operation(op);
b10494af4989d (Joe Gorse 2019-04-25 14:26:52 +0100 118)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 119) op->ops = &afs_store_acl_operation;
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 120) return afs_do_sync_operation(op);
b10494af4989d (Joe Gorse 2019-04-25 14:26:52 +0100 121) }
b10494af4989d (Joe Gorse 2019-04-25 14:26:52 +0100 122)
260f082bae6dc (David Howells 2019-04-25 14:26:52 +0100 123) static const struct xattr_handler afs_xattr_afs_acl_handler = {
b10494af4989d (Joe Gorse 2019-04-25 14:26:52 +0100 124) .name = "afs.acl",
b10494af4989d (Joe Gorse 2019-04-25 14:26:52 +0100 125) .get = afs_xattr_get_acl,
b10494af4989d (Joe Gorse 2019-04-25 14:26:52 +0100 126) .set = afs_xattr_set_acl,
260f082bae6dc (David Howells 2019-04-25 14:26:52 +0100 127) };
260f082bae6dc (David Howells 2019-04-25 14:26:52 +0100 128)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 129) static const struct afs_operation_ops yfs_fetch_opaque_acl_operation = {
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 130) .issue_yfs_rpc = yfs_fs_fetch_opaque_acl,
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 131) .success = afs_acl_success,
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 132) /* Don't free op->yacl in .put here */
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 133) };
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 134)
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 135) /*
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 136) * Get a file's YFS ACL.
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 137) */
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 138) static int afs_xattr_get_yfs(const struct xattr_handler *handler,
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 139) struct dentry *dentry,
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 140) struct inode *inode, const char *name,
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 141) void *buffer, size_t size)
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 142) {
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 143) struct afs_operation *op;
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 144) struct afs_vnode *vnode = AFS_FS_I(inode);
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 145) struct yfs_acl *yacl = NULL;
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 146) char buf[16], *data;
773e0c4025344 (David Howells 2019-05-12 08:31:23 +0100 147) int which = 0, dsize, ret = -ENOMEM;
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 148)
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 149) if (strcmp(name, "acl") == 0)
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 150) which = 0;
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 151) else if (strcmp(name, "acl_inherited") == 0)
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 152) which = 1;
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 153) else if (strcmp(name, "acl_num_cleaned") == 0)
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 154) which = 2;
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 155) else if (strcmp(name, "vol_acl") == 0)
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 156) which = 3;
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 157) else
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 158) return -EOPNOTSUPP;
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 159)
773e0c4025344 (David Howells 2019-05-12 08:31:23 +0100 160) yacl = kzalloc(sizeof(struct yfs_acl), GFP_KERNEL);
773e0c4025344 (David Howells 2019-05-12 08:31:23 +0100 161) if (!yacl)
773e0c4025344 (David Howells 2019-05-12 08:31:23 +0100 162) goto error;
773e0c4025344 (David Howells 2019-05-12 08:31:23 +0100 163)
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 164) if (which == 0)
773e0c4025344 (David Howells 2019-05-12 08:31:23 +0100 165) yacl->flags |= YFS_ACL_WANT_ACL;
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 166) else if (which == 3)
773e0c4025344 (David Howells 2019-05-12 08:31:23 +0100 167) yacl->flags |= YFS_ACL_WANT_VOL_ACL;
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 168)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 169) op = afs_alloc_operation(NULL, vnode->volume);
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 170) if (IS_ERR(op))
a58823ac45896 (David Howells 2019-05-09 15:16:10 +0100 171) goto error_yacl;
a58823ac45896 (David Howells 2019-05-09 15:16:10 +0100 172)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 173) afs_op_set_vnode(op, 0, vnode);
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 174) op->yacl = yacl;
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 175) op->ops = &yfs_fetch_opaque_acl_operation;
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 176)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 177) afs_begin_vnode_operation(op);
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 178) afs_wait_for_operation(op);
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 179) ret = afs_put_operation(op);
a58823ac45896 (David Howells 2019-05-09 15:16:10 +0100 180)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 181) if (ret == 0) {
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 182) switch (which) {
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 183) case 0:
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 184) data = yacl->acl->data;
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 185) dsize = yacl->acl->size;
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 186) break;
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 187) case 1:
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 188) data = buf;
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 189) dsize = scnprintf(buf, sizeof(buf), "%u", yacl->inherit_flag);
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 190) break;
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 191) case 2:
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 192) data = buf;
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 193) dsize = scnprintf(buf, sizeof(buf), "%u", yacl->num_cleaned);
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 194) break;
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 195) case 3:
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 196) data = yacl->vol_acl->data;
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 197) dsize = yacl->vol_acl->size;
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 198) break;
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 199) default:
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 200) ret = -EOPNOTSUPP;
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 201) goto error_yacl;
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 202) }
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 203)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 204) ret = dsize;
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 205) if (size > 0) {
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 206) if (dsize <= size)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 207) memcpy(buffer, data, dsize);
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 208) else
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 209) ret = -ERANGE;
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 210) }
64fcbb6158ecc (David Howells 2021-03-02 10:26:45 +0000 211) } else if (ret == -ENOTSUPP) {
64fcbb6158ecc (David Howells 2021-03-02 10:26:45 +0000 212) ret = -ENODATA;
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 213) }
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 214)
773e0c4025344 (David Howells 2019-05-12 08:31:23 +0100 215) error_yacl:
773e0c4025344 (David Howells 2019-05-12 08:31:23 +0100 216) yfs_free_opaque_acl(yacl);
773e0c4025344 (David Howells 2019-05-12 08:31:23 +0100 217) error:
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 218) return ret;
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 219) }
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 220)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 221) static const struct afs_operation_ops yfs_store_opaque_acl2_operation = {
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 222) .issue_yfs_rpc = yfs_fs_store_opaque_acl2,
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 223) .success = afs_acl_success,
f4c79144edd8a (David Howells 2020-11-03 16:33:07 +0000 224) .put = afs_acl_put,
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 225) };
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 226)
f5e4546347bc8 (David Howells 2019-05-01 14:05:27 +0100 227) /*
f5e4546347bc8 (David Howells 2019-05-01 14:05:27 +0100 228) * Set a file's YFS ACL.
f5e4546347bc8 (David Howells 2019-05-01 14:05:27 +0100 229) */
f5e4546347bc8 (David Howells 2019-05-01 14:05:27 +0100 230) static int afs_xattr_set_yfs(const struct xattr_handler *handler,
e65ce2a50cf6a (Christian Brauner 2021-01-21 14:19:27 +0100 231) struct user_namespace *mnt_userns,
f5e4546347bc8 (David Howells 2019-05-01 14:05:27 +0100 232) struct dentry *dentry,
f5e4546347bc8 (David Howells 2019-05-01 14:05:27 +0100 233) struct inode *inode, const char *name,
f5e4546347bc8 (David Howells 2019-05-01 14:05:27 +0100 234) const void *buffer, size_t size, int flags)
f5e4546347bc8 (David Howells 2019-05-01 14:05:27 +0100 235) {
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 236) struct afs_operation *op;
f5e4546347bc8 (David Howells 2019-05-01 14:05:27 +0100 237) struct afs_vnode *vnode = AFS_FS_I(inode);
64fcbb6158ecc (David Howells 2021-03-02 10:26:45 +0000 238) int ret;
f5e4546347bc8 (David Howells 2019-05-01 14:05:27 +0100 239)
f5e4546347bc8 (David Howells 2019-05-01 14:05:27 +0100 240) if (flags == XATTR_CREATE ||
f5e4546347bc8 (David Howells 2019-05-01 14:05:27 +0100 241) strcmp(name, "acl") != 0)
f5e4546347bc8 (David Howells 2019-05-01 14:05:27 +0100 242) return -EINVAL;
f5e4546347bc8 (David Howells 2019-05-01 14:05:27 +0100 243)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 244) op = afs_alloc_operation(NULL, vnode->volume);
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 245) if (IS_ERR(op))
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 246) return -ENOMEM;
f5e4546347bc8 (David Howells 2019-05-01 14:05:27 +0100 247)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 248) afs_op_set_vnode(op, 0, vnode);
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 249) if (!afs_make_acl(op, buffer, size))
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 250) return afs_put_operation(op);
f5e4546347bc8 (David Howells 2019-05-01 14:05:27 +0100 251)
e49c7b2f6de7f (David Howells 2020-04-10 20:51:51 +0100 252) op->ops = &yfs_store_opaque_acl2_operation;
64fcbb6158ecc (David Howells 2021-03-02 10:26:45 +0000 253) ret = afs_do_sync_operation(op);
64fcbb6158ecc (David Howells 2021-03-02 10:26:45 +0000 254) if (ret == -ENOTSUPP)
64fcbb6158ecc (David Howells 2021-03-02 10:26:45 +0000 255) ret = -ENODATA;
64fcbb6158ecc (David Howells 2021-03-02 10:26:45 +0000 256) return ret;
f5e4546347bc8 (David Howells 2019-05-01 14:05:27 +0100 257) }
f5e4546347bc8 (David Howells 2019-05-01 14:05:27 +0100 258)
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 259) static const struct xattr_handler afs_xattr_yfs_handler = {
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 260) .prefix = "afs.yfs.",
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 261) .get = afs_xattr_get_yfs,
f5e4546347bc8 (David Howells 2019-05-01 14:05:27 +0100 262) .set = afs_xattr_set_yfs,
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 263) };
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 264)
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 265) /*
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 266) * Get the name of the cell on which a file resides.
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 267) */
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 268) static int afs_xattr_get_cell(const struct xattr_handler *handler,
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 269) struct dentry *dentry,
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 270) struct inode *inode, const char *name,
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 271) void *buffer, size_t size)
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 272) {
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 273) struct afs_vnode *vnode = AFS_FS_I(inode);
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 274) struct afs_cell *cell = vnode->volume->cell;
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 275) size_t namelen;
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 276)
989782dcdc91a (David Howells 2017-11-02 15:27:50 +0000 277) namelen = cell->name_len;
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 278) if (size == 0)
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 279) return namelen;
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 280) if (namelen > size)
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 281) return -ERANGE;
c73aa4102f5b9 (David Howells 2019-05-01 13:27:09 +0100 282) memcpy(buffer, cell->name, namelen);
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 283) return namelen;
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 284) }
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 285)
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 286) static const struct xattr_handler afs_xattr_afs_cell_handler = {
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 287) .name = "afs.cell",
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 288) .get = afs_xattr_get_cell,
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 289) };
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 290)
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 291) /*
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 292) * Get the volume ID, vnode ID and vnode uniquifier of a file as a sequence of
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 293) * hex numbers separated by colons.
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 294) */
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 295) static int afs_xattr_get_fid(const struct xattr_handler *handler,
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 296) struct dentry *dentry,
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 297) struct inode *inode, const char *name,
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 298) void *buffer, size_t size)
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 299) {
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 300) struct afs_vnode *vnode = AFS_FS_I(inode);
a2f611a3dc317 (David Howells 2019-05-01 15:58:24 +0100 301) char text[16 + 1 + 24 + 1 + 8 + 1];
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 302) size_t len;
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 303)
a2f611a3dc317 (David Howells 2019-05-01 15:58:24 +0100 304) /* The volume ID is 64-bit, the vnode ID is 96-bit and the
a2f611a3dc317 (David Howells 2019-05-01 15:58:24 +0100 305) * uniquifier is 32-bit.
a2f611a3dc317 (David Howells 2019-05-01 15:58:24 +0100 306) */
2e2fae99d1f30 (Mark Salyzyn 2019-11-21 09:12:17 +0000 307) len = scnprintf(text, sizeof(text), "%llx:", vnode->fid.vid);
a2f611a3dc317 (David Howells 2019-05-01 15:58:24 +0100 308) if (vnode->fid.vnode_hi)
2e2fae99d1f30 (Mark Salyzyn 2019-11-21 09:12:17 +0000 309) len += scnprintf(text + len, sizeof(text) - len, "%x%016llx",
2e2fae99d1f30 (Mark Salyzyn 2019-11-21 09:12:17 +0000 310) vnode->fid.vnode_hi, vnode->fid.vnode);
a2f611a3dc317 (David Howells 2019-05-01 15:58:24 +0100 311) else
2e2fae99d1f30 (Mark Salyzyn 2019-11-21 09:12:17 +0000 312) len += scnprintf(text + len, sizeof(text) - len, "%llx",
2e2fae99d1f30 (Mark Salyzyn 2019-11-21 09:12:17 +0000 313) vnode->fid.vnode);
2e2fae99d1f30 (Mark Salyzyn 2019-11-21 09:12:17 +0000 314) len += scnprintf(text + len, sizeof(text) - len, ":%x",
2e2fae99d1f30 (Mark Salyzyn 2019-11-21 09:12:17 +0000 315) vnode->fid.unique);
a2f611a3dc317 (David Howells 2019-05-01 15:58:24 +0100 316)
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 317) if (size == 0)
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 318) return len;
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 319) if (len > size)
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 320) return -ERANGE;
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 321) memcpy(buffer, text, len);
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 322) return len;
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 323) }
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 324)
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 325) static const struct xattr_handler afs_xattr_afs_fid_handler = {
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 326) .name = "afs.fid",
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 327) .get = afs_xattr_get_fid,
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 328) };
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 329)
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 330) /*
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 331) * Get the name of the volume on which a file resides.
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 332) */
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 333) static int afs_xattr_get_volume(const struct xattr_handler *handler,
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 334) struct dentry *dentry,
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 335) struct inode *inode, const char *name,
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 336) void *buffer, size_t size)
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 337) {
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 338) struct afs_vnode *vnode = AFS_FS_I(inode);
d2ddc776a4581 (David Howells 2017-11-02 15:27:50 +0000 339) const char *volname = vnode->volume->name;
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 340) size_t namelen;
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 341)
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 342) namelen = strlen(volname);
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 343) if (size == 0)
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 344) return namelen;
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 345) if (namelen > size)
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 346) return -ERANGE;
c73aa4102f5b9 (David Howells 2019-05-01 13:27:09 +0100 347) memcpy(buffer, volname, namelen);
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 348) return namelen;
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 349) }
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 350)
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 351) static const struct xattr_handler afs_xattr_afs_volume_handler = {
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 352) .name = "afs.volume",
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 353) .get = afs_xattr_get_volume,
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 354) };
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 355)
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 356) const struct xattr_handler *afs_xattr_handlers[] = {
260f082bae6dc (David Howells 2019-04-25 14:26:52 +0100 357) &afs_xattr_afs_acl_handler,
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 358) &afs_xattr_afs_cell_handler,
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 359) &afs_xattr_afs_fid_handler,
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 360) &afs_xattr_afs_volume_handler,
ae46578b963f6 (David Howells 2019-04-30 18:30:21 +0100 361) &afs_xattr_yfs_handler, /* afs.yfs. prefix */
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 362) NULL
d3e3b7eac886f (David Howells 2017-07-06 15:50:27 +0100 363) };