new helper: import_xattr_name()

common logics for marshalling xattr names.

Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Al Viro 2024-09-26 14:11:52 -04:00
parent 537c76629d
commit a10c4c5e01
3 changed files with 28 additions and 27 deletions

View File

@ -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 setxattr_copy(const char __user *name, struct kernel_xattr_ctx *ctx);
int do_setxattr(struct mnt_idmap *idmap, struct dentry *dentry, int do_setxattr(struct mnt_idmap *idmap, struct dentry *dentry,
struct kernel_xattr_ctx *ctx); 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); int may_write_xattr(struct mnt_idmap *idmap, struct inode *inode);
#ifdef CONFIG_FS_POSIX_ACL #ifdef CONFIG_FS_POSIX_ACL

View File

@ -586,6 +586,17 @@ retry_deleg:
} }
EXPORT_SYMBOL_GPL(vfs_removexattr); 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 * 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)) if (ctx->flags & ~(XATTR_CREATE|XATTR_REPLACE))
return -EINVAL; return -EINVAL;
error = strncpy_from_user(ctx->kname->name, name, error = import_xattr_name(ctx->kname, name);
sizeof(ctx->kname->name)); if (error)
if (error == 0 || error == sizeof(ctx->kname->name))
return -ERANGE;
if (error < 0)
return error; return error;
error = 0;
if (ctx->size) { if (ctx->size) {
if (ctx->size > XATTR_SIZE_MAX) if (ctx->size > XATTR_SIZE_MAX)
return -E2BIG; return -E2BIG;
@ -763,10 +770,8 @@ getxattr(struct mnt_idmap *idmap, struct dentry *d,
.flags = 0, .flags = 0,
}; };
error = strncpy_from_user(kname.name, name, sizeof(kname.name)); error = import_xattr_name(&kname, name);
if (error == 0 || error == sizeof(kname.name)) if (error)
error = -ERANGE;
if (error < 0)
return error; return error;
error = do_getxattr(idmap, d, &ctx); error = do_getxattr(idmap, d, &ctx);
@ -906,12 +911,10 @@ static int path_removexattr(const char __user *pathname,
{ {
struct path path; struct path path;
int error; int error;
char kname[XATTR_NAME_MAX + 1]; struct xattr_name kname;
error = strncpy_from_user(kname, name, sizeof(kname)); error = import_xattr_name(&kname, name);
if (error == 0 || error == sizeof(kname)) if (error)
error = -ERANGE;
if (error < 0)
return error; return error;
retry: retry:
error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path); error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
@ -919,7 +922,7 @@ retry:
return error; return error;
error = mnt_want_write(path.mnt); error = mnt_want_write(path.mnt);
if (!error) { 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); mnt_drop_write(path.mnt);
} }
path_put(&path); path_put(&path);
@ -945,23 +948,21 @@ SYSCALL_DEFINE2(lremovexattr, const char __user *, pathname,
SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name) SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name)
{ {
CLASS(fd, f)(fd); CLASS(fd, f)(fd);
char kname[XATTR_NAME_MAX + 1]; struct xattr_name kname;
int error; int error;
if (fd_empty(f)) if (fd_empty(f))
return -EBADF; return -EBADF;
audit_file(fd_file(f)); audit_file(fd_file(f));
error = strncpy_from_user(kname, name, sizeof(kname)); error = import_xattr_name(&kname, name);
if (error == 0 || error == sizeof(kname)) if (error)
error = -ERANGE;
if (error < 0)
return error; return error;
error = mnt_want_write_file(fd_file(f)); error = mnt_want_write_file(fd_file(f));
if (!error) { if (!error) {
error = removexattr(file_mnt_idmap(fd_file(f)), 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)); mnt_drop_write_file(fd_file(f));
} }
return error; return error;

View File

@ -62,11 +62,8 @@ static int __io_getxattr_prep(struct io_kiocb *req,
if (!ix->ctx.kname) if (!ix->ctx.kname)
return -ENOMEM; return -ENOMEM;
ret = strncpy_from_user(ix->ctx.kname->name, name, ret = import_xattr_name(ix->ctx.kname, name);
sizeof(ix->ctx.kname->name)); if (ret) {
if (!ret || ret == sizeof(ix->ctx.kname->name))
ret = -ERANGE;
if (ret < 0) {
kfree(ix->ctx.kname); kfree(ix->ctx.kname);
return ret; return ret;
} }