Commit c975cad9 authored by Stefan Roesch's avatar Stefan Roesch Committed by Jens Axboe

fs: split off do_getxattr from getxattr

This splits off do_getxattr function from the getxattr function. This will
allow io_uring to call it from its io worker.
Signed-off-by: default avatarStefan Roesch <shr@fb.com>
Acked-by: default avatarChristian Brauner <christian.brauner@ubuntu.com>
Link: https://lore.kernel.org/r/20220323154420.3301504-3-shr@fb.comSigned-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 1a91794c
...@@ -212,6 +212,11 @@ struct xattr_ctx { ...@@ -212,6 +212,11 @@ struct xattr_ctx {
unsigned int flags; unsigned int flags;
}; };
ssize_t do_getxattr(struct user_namespace *mnt_userns,
struct dentry *d,
struct xattr_ctx *ctx);
int setxattr_copy(const char __user *name, struct xattr_ctx *ctx); int setxattr_copy(const char __user *name, struct xattr_ctx *ctx);
int do_setxattr(struct user_namespace *mnt_userns, struct dentry *dentry, int do_setxattr(struct user_namespace *mnt_userns, struct dentry *dentry,
struct xattr_ctx *ctx); struct xattr_ctx *ctx);
...@@ -676,44 +676,61 @@ SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name, ...@@ -676,44 +676,61 @@ SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name,
/* /*
* Extended attribute GET operations * Extended attribute GET operations
*/ */
static ssize_t ssize_t
getxattr(struct user_namespace *mnt_userns, struct dentry *d, do_getxattr(struct user_namespace *mnt_userns, struct dentry *d,
const char __user *name, void __user *value, size_t size) struct xattr_ctx *ctx)
{ {
ssize_t error; ssize_t error;
void *kvalue = NULL; char *kname = ctx->kname->name;
char kname[XATTR_NAME_MAX + 1];
error = strncpy_from_user(kname, name, sizeof(kname)); if (ctx->size) {
if (error == 0 || error == sizeof(kname)) if (ctx->size > XATTR_SIZE_MAX)
error = -ERANGE; ctx->size = XATTR_SIZE_MAX;
if (error < 0) ctx->kvalue = kvzalloc(ctx->size, GFP_KERNEL);
return error; if (!ctx->kvalue)
if (size) {
if (size > XATTR_SIZE_MAX)
size = XATTR_SIZE_MAX;
kvalue = kvzalloc(size, GFP_KERNEL);
if (!kvalue)
return -ENOMEM; return -ENOMEM;
} }
error = vfs_getxattr(mnt_userns, d, kname, kvalue, size); error = vfs_getxattr(mnt_userns, d, kname, ctx->kvalue, ctx->size);
if (error > 0) { if (error > 0) {
if ((strcmp(kname, XATTR_NAME_POSIX_ACL_ACCESS) == 0) || if ((strcmp(kname, XATTR_NAME_POSIX_ACL_ACCESS) == 0) ||
(strcmp(kname, XATTR_NAME_POSIX_ACL_DEFAULT) == 0)) (strcmp(kname, XATTR_NAME_POSIX_ACL_DEFAULT) == 0))
posix_acl_fix_xattr_to_user(mnt_userns, d_inode(d), posix_acl_fix_xattr_to_user(mnt_userns, d_inode(d),
kvalue, error); ctx->kvalue, error);
if (size && copy_to_user(value, kvalue, error)) if (ctx->size && copy_to_user(ctx->value, ctx->kvalue, error))
error = -EFAULT; error = -EFAULT;
} else if (error == -ERANGE && size >= XATTR_SIZE_MAX) { } else if (error == -ERANGE && ctx->size >= XATTR_SIZE_MAX) {
/* The file system tried to returned a value bigger /* The file system tried to returned a value bigger
than XATTR_SIZE_MAX bytes. Not possible. */ than XATTR_SIZE_MAX bytes. Not possible. */
error = -E2BIG; error = -E2BIG;
} }
kvfree(kvalue); return error;
}
static ssize_t
getxattr(struct user_namespace *mnt_userns, struct dentry *d,
const char __user *name, void __user *value, size_t size)
{
ssize_t error;
struct xattr_name kname;
struct xattr_ctx ctx = {
.value = value,
.kvalue = NULL,
.size = size,
.kname = &kname,
.flags = 0,
};
error = strncpy_from_user(kname.name, name, sizeof(kname.name));
if (error == 0 || error == sizeof(kname.name))
error = -ERANGE;
if (error < 0)
return error;
error = do_getxattr(mnt_userns, d, &ctx);
kvfree(ctx.kvalue);
return error; return error;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment