]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
replace do_getxattr() with saner helpers.
authorAl Viro <viro@zeniv.linux.org.uk>
Thu, 26 Sep 2024 21:07:15 +0000 (17:07 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Wed, 6 Nov 2024 17:59:39 +0000 (12:59 -0500)
similar to do_setxattr() in the previous commit...

Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/internal.h
fs/xattr.c
io_uring/xattr.c

index be7c0da3bcecc1a8ba2cc9fda5061967c57979ab..8001efd1f047b54510bba6471865e37840c8f404 100644 (file)
@@ -280,11 +280,9 @@ struct kernel_xattr_ctx {
        unsigned int flags;
 };
 
-
-ssize_t do_getxattr(struct mnt_idmap *idmap,
-                   struct dentry *d,
-                   struct kernel_xattr_ctx *ctx);
-
+ssize_t file_getxattr(struct file *file, struct kernel_xattr_ctx *ctx);
+ssize_t filename_getxattr(int dfd, struct filename *filename,
+                         unsigned int lookup_flags, struct kernel_xattr_ctx *ctx);
 int file_setxattr(struct file *file, struct kernel_xattr_ctx *ctx);
 int filename_setxattr(int dfd, struct filename *filename,
                      unsigned int lookup_flags, struct kernel_xattr_ctx *ctx);
index 38bf8cfbd46499d38976ac1fc75ab3ae104ca2bc..d55f3d1e758934a199eadd0bdf878392e865d9a2 100644 (file)
@@ -744,27 +744,28 @@ SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name,
 /*
  * Extended attribute GET operations
  */
-ssize_t
+static ssize_t
 do_getxattr(struct mnt_idmap *idmap, struct dentry *d,
        struct kernel_xattr_ctx *ctx)
 {
        ssize_t error;
        char *kname = ctx->kname->name;
+       void *kvalue = NULL;
 
        if (ctx->size) {
                if (ctx->size > XATTR_SIZE_MAX)
                        ctx->size = XATTR_SIZE_MAX;
-               ctx->kvalue = kvzalloc(ctx->size, GFP_KERNEL);
-               if (!ctx->kvalue)
+               kvalue = kvzalloc(ctx->size, GFP_KERNEL);
+               if (!kvalue)
                        return -ENOMEM;
        }
 
-       if (is_posix_acl_xattr(ctx->kname->name))
-               error = do_get_acl(idmap, d, kname, ctx->kvalue, ctx->size);
+       if (is_posix_acl_xattr(kname))
+               error = do_get_acl(idmap, d, kname, kvalue, ctx->size);
        else
-               error = vfs_getxattr(idmap, d, kname, ctx->kvalue, ctx->size);
+               error = vfs_getxattr(idmap, d, kname, kvalue, ctx->size);
        if (error > 0) {
-               if (ctx->size && copy_to_user(ctx->value, ctx->kvalue, error))
+               if (ctx->size && copy_to_user(ctx->value, kvalue, error))
                        error = -EFAULT;
        } else if (error == -ERANGE && ctx->size >= XATTR_SIZE_MAX) {
                /* The file system tried to returned a value bigger
@@ -772,52 +773,56 @@ do_getxattr(struct mnt_idmap *idmap, struct dentry *d,
                error = -E2BIG;
        }
 
+       kvfree(kvalue);
        return error;
 }
 
-static ssize_t
-getxattr(struct mnt_idmap *idmap, struct dentry *d,
-        const char __user *name, void __user *value, size_t size)
+ssize_t file_getxattr(struct file *f, struct kernel_xattr_ctx *ctx)
 {
-       ssize_t error;
-       struct xattr_name kname;
-       struct kernel_xattr_ctx ctx = {
-               .value    = value,
-               .kvalue   = NULL,
-               .size     = size,
-               .kname    = &kname,
-               .flags    = 0,
-       };
-
-       error = import_xattr_name(&kname, name);
-       if (error)
-               return error;
-
-       error =  do_getxattr(idmap, d, &ctx);
-
-       kvfree(ctx.kvalue);
-       return error;
+       audit_file(f);
+       return do_getxattr(file_mnt_idmap(f), f->f_path.dentry, ctx);
 }
 
-static ssize_t path_getxattr(const char __user *pathname,
-                            const char __user *name, void __user *value,
-                            size_t size, unsigned int lookup_flags)
+/* unconditionally consumes filename */
+ssize_t filename_getxattr(int dfd, struct filename *filename,
+                         unsigned int lookup_flags, struct kernel_xattr_ctx *ctx)
 {
        struct path path;
        ssize_t error;
 retry:
-       error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
+       error = filename_lookup(dfd, filename, lookup_flags, &path, NULL);
        if (error)
-               return error;
-       error = getxattr(mnt_idmap(path.mnt), path.dentry, name, value, size);
+               goto out;
+       error = do_getxattr(mnt_idmap(path.mnt), path.dentry, ctx);
        path_put(&path);
        if (retry_estale(error, lookup_flags)) {
                lookup_flags |= LOOKUP_REVAL;
                goto retry;
        }
+out:
+       putname(filename);
        return error;
 }
 
+static ssize_t path_getxattr(const char __user *pathname,
+                            const char __user *name, void __user *value,
+                            size_t size, unsigned int lookup_flags)
+{
+       ssize_t error;
+       struct xattr_name kname;
+       struct kernel_xattr_ctx ctx = {
+               .value    = value,
+               .size     = size,
+               .kname    = &kname,
+               .flags    = 0,
+       };
+
+       error = import_xattr_name(&kname, name);
+       if (error)
+               return error;
+       return filename_getxattr(AT_FDCWD, getname(pathname), lookup_flags, &ctx);
+}
+
 SYSCALL_DEFINE4(getxattr, const char __user *, pathname,
                const char __user *, name, void __user *, value, size_t, size)
 {
@@ -833,13 +838,22 @@ SYSCALL_DEFINE4(lgetxattr, const char __user *, pathname,
 SYSCALL_DEFINE4(fgetxattr, int, fd, const char __user *, name,
                void __user *, value, size_t, size)
 {
+       ssize_t error;
+       struct xattr_name kname;
+       struct kernel_xattr_ctx ctx = {
+               .value    = value,
+               .size     = size,
+               .kname    = &kname,
+               .flags    = 0,
+       };
        CLASS(fd, f)(fd);
 
        if (fd_empty(f))
                return -EBADF;
-       audit_file(fd_file(f));
-       return getxattr(file_mnt_idmap(fd_file(f)), fd_file(f)->f_path.dentry,
-                        name, value, size);
+       error = import_xattr_name(&kname, name);
+       if (error)
+               return error;
+       return file_getxattr(fd_file(f), &ctx);
 }
 
 /*
index 2671ad05d63b20023a2eb0609f0fb528568fc856..de5064fcae8a241941f7e4597df70ab079704015 100644 (file)
@@ -51,7 +51,7 @@ static int __io_getxattr_prep(struct io_kiocb *req,
        ix->filename = NULL;
        ix->ctx.kvalue = NULL;
        name = u64_to_user_ptr(READ_ONCE(sqe->addr));
-       ix->ctx.cvalue = u64_to_user_ptr(READ_ONCE(sqe->addr2));
+       ix->ctx.value = u64_to_user_ptr(READ_ONCE(sqe->addr2));
        ix->ctx.size = READ_ONCE(sqe->len);
        ix->ctx.flags = READ_ONCE(sqe->xattr_flags);
 
@@ -94,12 +94,10 @@ int io_getxattr_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
        path = u64_to_user_ptr(READ_ONCE(sqe->addr3));
 
        ix->filename = getname(path);
-       if (IS_ERR(ix->filename)) {
-               ret = PTR_ERR(ix->filename);
-               ix->filename = NULL;
-       }
+       if (IS_ERR(ix->filename))
+               return PTR_ERR(ix->filename);
 
-       return ret;
+       return 0;
 }
 
 int io_fgetxattr(struct io_kiocb *req, unsigned int issue_flags)
@@ -109,10 +107,7 @@ int io_fgetxattr(struct io_kiocb *req, unsigned int issue_flags)
 
        WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
 
-       ret = do_getxattr(file_mnt_idmap(req->file),
-                       req->file->f_path.dentry,
-                       &ix->ctx);
-
+       ret = file_getxattr(req->file, &ix->ctx);
        io_xattr_finish(req, ret);
        return IOU_OK;
 }
@@ -120,24 +115,12 @@ int io_fgetxattr(struct io_kiocb *req, unsigned int issue_flags)
 int io_getxattr(struct io_kiocb *req, unsigned int issue_flags)
 {
        struct io_xattr *ix = io_kiocb_to_cmd(req, struct io_xattr);
-       unsigned int lookup_flags = LOOKUP_FOLLOW;
-       struct path path;
        int ret;
 
        WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK);
 
-retry:
-       ret = filename_lookup(AT_FDCWD, ix->filename, lookup_flags, &path, NULL);
-       if (!ret) {
-               ret = do_getxattr(mnt_idmap(path.mnt), path.dentry, &ix->ctx);
-
-               path_put(&path);
-               if (retry_estale(ret, lookup_flags)) {
-                       lookup_flags |= LOOKUP_REVAL;
-                       goto retry;
-               }
-       }
-
+       ret = filename_getxattr(AT_FDCWD, ix->filename, LOOKUP_FOLLOW, &ix->ctx);
+       ix->filename = NULL;
        io_xattr_finish(req, ret);
        return IOU_OK;
 }