common logics for marshalling xattr names. Signed-off-by: Al Viro <viro@xxxxxxxxxxxxxxxxxx> --- fs/internal.h | 3 +++ fs/xattr.c | 45 +++++++++++++++++++++++---------------------- io_uring/xattr.c | 7 ++----- 3 files changed, 28 insertions(+), 27 deletions(-) diff --git a/fs/internal.h b/fs/internal.h index 81c7a085355c..b9f5ac4d39fc 100644 --- a/fs/internal.h +++ b/fs/internal.h @@ -288,6 +288,9 @@ ssize_t do_getxattr(struct mnt_idmap *idmap, int setxattr_copy(const char __user *name, struct kernel_xattr_ctx *ctx); int do_setxattr(struct mnt_idmap *idmap, struct dentry *dentry, struct kernel_xattr_ctx *ctx); + +int import_xattr_name(struct xattr_name *kname, const char __user *name); + int may_write_xattr(struct mnt_idmap *idmap, struct inode *inode); #ifdef CONFIG_FS_POSIX_ACL diff --git a/fs/xattr.c b/fs/xattr.c index 1214ae7e71db..d8f7c766f28a 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -586,6 +586,17 @@ vfs_removexattr(struct mnt_idmap *idmap, struct dentry *dentry, } EXPORT_SYMBOL_GPL(vfs_removexattr); +int import_xattr_name(struct xattr_name *kname, const char __user *name) +{ + int error = strncpy_from_user(kname->name, name, + sizeof(kname->name)); + if (error == 0 || error == sizeof(kname->name)) + return -ERANGE; + if (error < 0) + return error; + return 0; +} + /* * Extended attribute SET operations */ @@ -597,14 +608,10 @@ int setxattr_copy(const char __user *name, struct kernel_xattr_ctx *ctx) if (ctx->flags & ~(XATTR_CREATE|XATTR_REPLACE)) return -EINVAL; - error = strncpy_from_user(ctx->kname->name, name, - sizeof(ctx->kname->name)); - if (error == 0 || error == sizeof(ctx->kname->name)) - return -ERANGE; - if (error < 0) + error = import_xattr_name(ctx->kname, name); + if (error) return error; - error = 0; if (ctx->size) { if (ctx->size > XATTR_SIZE_MAX) return -E2BIG; @@ -763,10 +770,8 @@ getxattr(struct mnt_idmap *idmap, struct dentry *d, .flags = 0, }; - error = strncpy_from_user(kname.name, name, sizeof(kname.name)); - if (error == 0 || error == sizeof(kname.name)) - error = -ERANGE; - if (error < 0) + error = import_xattr_name(&kname, name); + if (error) return error; error = do_getxattr(idmap, d, &ctx); @@ -906,12 +911,10 @@ static int path_removexattr(const char __user *pathname, { struct path path; int error; - char kname[XATTR_NAME_MAX + 1]; + struct xattr_name kname; - error = strncpy_from_user(kname, name, sizeof(kname)); - if (error == 0 || error == sizeof(kname)) - error = -ERANGE; - if (error < 0) + error = import_xattr_name(&kname, name); + if (error) return error; retry: error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path); @@ -919,7 +922,7 @@ static int path_removexattr(const char __user *pathname, return error; error = mnt_want_write(path.mnt); if (!error) { - error = removexattr(mnt_idmap(path.mnt), path.dentry, kname); + error = removexattr(mnt_idmap(path.mnt), path.dentry, kname.name); mnt_drop_write(path.mnt); } path_put(&path); @@ -945,23 +948,21 @@ SYSCALL_DEFINE2(lremovexattr, const char __user *, pathname, SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name) { CLASS(fd, f)(fd); - char kname[XATTR_NAME_MAX + 1]; + struct xattr_name kname; int error; if (fd_empty(f)) return -EBADF; audit_file(fd_file(f)); - error = strncpy_from_user(kname, name, sizeof(kname)); - if (error == 0 || error == sizeof(kname)) - error = -ERANGE; - if (error < 0) + error = import_xattr_name(&kname, name); + if (error) return error; error = mnt_want_write_file(fd_file(f)); if (!error) { error = removexattr(file_mnt_idmap(fd_file(f)), - fd_file(f)->f_path.dentry, kname); + fd_file(f)->f_path.dentry, kname.name); mnt_drop_write_file(fd_file(f)); } return error; diff --git a/io_uring/xattr.c b/io_uring/xattr.c index 04abf0739668..71d9e2569a2f 100644 --- a/io_uring/xattr.c +++ b/io_uring/xattr.c @@ -65,11 +65,8 @@ static int __io_getxattr_prep(struct io_kiocb *req, if (!ix->ctx.kname) return -ENOMEM; - ret = strncpy_from_user(ix->ctx.kname->name, name, - sizeof(ix->ctx.kname->name)); - if (!ret || ret == sizeof(ix->ctx.kname->name)) - ret = -ERANGE; - if (ret < 0) { + ret = import_xattr_name(ix->ctx.kname, name); + if (ret) { kfree(ix->ctx.kname); return ret; } -- 2.39.5