mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:41:42 +00:00
fs/xattr: add *at family syscalls
Add the four syscalls setxattrat(), getxattrat(), listxattrat() and removexattrat(). Those can be used to operate on extended attributes, especially security related ones, either relative to a pinned directory or on a file descriptor without read access, avoiding a /proc/<pid>/fd/<fd> detour, requiring a mounted procfs. One use case will be setfiles(8) setting SELinux file contexts ("security.selinux") without race conditions and without a file descriptor opened with read access requiring SELinux read permission. Use the do_{name}at() pattern from fs/open.c. Pass the value of the extended attribute, its length, and for setxattrat(2) the command (XATTR_CREATE or XATTR_REPLACE) via an added struct xattr_args to not exceed six syscall arguments and not merging the AT_* and XATTR_* flags. [AV: fixes by Christian Brauner folded in, the entire thing rebased on top of {filename,file}_...xattr() primitives, treatment of empty pathnames regularized. As the result, AT_EMPTY_PATH+NULL handling is cheap, so f...(2) can use it] Signed-off-by: Christian Göttsche <cgzones@googlemail.com> Link: https://lore.kernel.org/r/20240426162042.191916-1-cgoettsche@seltendoof.de Reviewed-by: Arnd Bergmann <arnd@arndb.de> Reviewed-by: Christian Brauner <brauner@kernel.org> CC: x86@kernel.org CC: linux-alpha@vger.kernel.org CC: linux-kernel@vger.kernel.org CC: linux-arm-kernel@lists.infradead.org CC: linux-ia64@vger.kernel.org CC: linux-m68k@lists.linux-m68k.org CC: linux-mips@vger.kernel.org CC: linux-parisc@vger.kernel.org CC: linuxppc-dev@lists.ozlabs.org CC: linux-s390@vger.kernel.org CC: linux-sh@vger.kernel.org CC: sparclinux@vger.kernel.org CC: linux-fsdevel@vger.kernel.org CC: audit@vger.kernel.org CC: linux-arch@vger.kernel.org CC: linux-api@vger.kernel.org CC: linux-security-module@vger.kernel.org CC: selinux@vger.kernel.org [brauner: slight tweaks] Signed-off-by: Christian Brauner <brauner@kernel.org> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
22a4d1954c
commit
6140be90ec
@ -502,3 +502,7 @@
|
|||||||
570 common lsm_set_self_attr sys_lsm_set_self_attr
|
570 common lsm_set_self_attr sys_lsm_set_self_attr
|
||||||
571 common lsm_list_modules sys_lsm_list_modules
|
571 common lsm_list_modules sys_lsm_list_modules
|
||||||
572 common mseal sys_mseal
|
572 common mseal sys_mseal
|
||||||
|
573 common setxattrat sys_setxattrat
|
||||||
|
574 common getxattrat sys_getxattrat
|
||||||
|
575 common listxattrat sys_listxattrat
|
||||||
|
576 common removexattrat sys_removexattrat
|
||||||
|
@ -477,3 +477,7 @@
|
|||||||
460 common lsm_set_self_attr sys_lsm_set_self_attr
|
460 common lsm_set_self_attr sys_lsm_set_self_attr
|
||||||
461 common lsm_list_modules sys_lsm_list_modules
|
461 common lsm_list_modules sys_lsm_list_modules
|
||||||
462 common mseal sys_mseal
|
462 common mseal sys_mseal
|
||||||
|
463 common setxattrat sys_setxattrat
|
||||||
|
464 common getxattrat sys_getxattrat
|
||||||
|
465 common listxattrat sys_listxattrat
|
||||||
|
466 common removexattrat sys_removexattrat
|
||||||
|
@ -474,3 +474,7 @@
|
|||||||
460 common lsm_set_self_attr sys_lsm_set_self_attr
|
460 common lsm_set_self_attr sys_lsm_set_self_attr
|
||||||
461 common lsm_list_modules sys_lsm_list_modules
|
461 common lsm_list_modules sys_lsm_list_modules
|
||||||
462 common mseal sys_mseal
|
462 common mseal sys_mseal
|
||||||
|
463 common setxattrat sys_setxattrat
|
||||||
|
464 common getxattrat sys_getxattrat
|
||||||
|
465 common listxattrat sys_listxattrat
|
||||||
|
466 common removexattrat sys_removexattrat
|
||||||
|
@ -462,3 +462,7 @@
|
|||||||
460 common lsm_set_self_attr sys_lsm_set_self_attr
|
460 common lsm_set_self_attr sys_lsm_set_self_attr
|
||||||
461 common lsm_list_modules sys_lsm_list_modules
|
461 common lsm_list_modules sys_lsm_list_modules
|
||||||
462 common mseal sys_mseal
|
462 common mseal sys_mseal
|
||||||
|
463 common setxattrat sys_setxattrat
|
||||||
|
464 common getxattrat sys_getxattrat
|
||||||
|
465 common listxattrat sys_listxattrat
|
||||||
|
466 common removexattrat sys_removexattrat
|
||||||
|
@ -468,3 +468,7 @@
|
|||||||
460 common lsm_set_self_attr sys_lsm_set_self_attr
|
460 common lsm_set_self_attr sys_lsm_set_self_attr
|
||||||
461 common lsm_list_modules sys_lsm_list_modules
|
461 common lsm_list_modules sys_lsm_list_modules
|
||||||
462 common mseal sys_mseal
|
462 common mseal sys_mseal
|
||||||
|
463 common setxattrat sys_setxattrat
|
||||||
|
464 common getxattrat sys_getxattrat
|
||||||
|
465 common listxattrat sys_listxattrat
|
||||||
|
466 common removexattrat sys_removexattrat
|
||||||
|
@ -401,3 +401,7 @@
|
|||||||
460 n32 lsm_set_self_attr sys_lsm_set_self_attr
|
460 n32 lsm_set_self_attr sys_lsm_set_self_attr
|
||||||
461 n32 lsm_list_modules sys_lsm_list_modules
|
461 n32 lsm_list_modules sys_lsm_list_modules
|
||||||
462 n32 mseal sys_mseal
|
462 n32 mseal sys_mseal
|
||||||
|
463 n32 setxattrat sys_setxattrat
|
||||||
|
464 n32 getxattrat sys_getxattrat
|
||||||
|
465 n32 listxattrat sys_listxattrat
|
||||||
|
466 n32 removexattrat sys_removexattrat
|
||||||
|
@ -377,3 +377,7 @@
|
|||||||
460 n64 lsm_set_self_attr sys_lsm_set_self_attr
|
460 n64 lsm_set_self_attr sys_lsm_set_self_attr
|
||||||
461 n64 lsm_list_modules sys_lsm_list_modules
|
461 n64 lsm_list_modules sys_lsm_list_modules
|
||||||
462 n64 mseal sys_mseal
|
462 n64 mseal sys_mseal
|
||||||
|
463 n64 setxattrat sys_setxattrat
|
||||||
|
464 n64 getxattrat sys_getxattrat
|
||||||
|
465 n64 listxattrat sys_listxattrat
|
||||||
|
466 n64 removexattrat sys_removexattrat
|
||||||
|
@ -450,3 +450,7 @@
|
|||||||
460 o32 lsm_set_self_attr sys_lsm_set_self_attr
|
460 o32 lsm_set_self_attr sys_lsm_set_self_attr
|
||||||
461 o32 lsm_list_modules sys_lsm_list_modules
|
461 o32 lsm_list_modules sys_lsm_list_modules
|
||||||
462 o32 mseal sys_mseal
|
462 o32 mseal sys_mseal
|
||||||
|
463 o32 setxattrat sys_setxattrat
|
||||||
|
464 o32 getxattrat sys_getxattrat
|
||||||
|
465 o32 listxattrat sys_listxattrat
|
||||||
|
466 o32 removexattrat sys_removexattrat
|
||||||
|
@ -461,3 +461,7 @@
|
|||||||
460 common lsm_set_self_attr sys_lsm_set_self_attr
|
460 common lsm_set_self_attr sys_lsm_set_self_attr
|
||||||
461 common lsm_list_modules sys_lsm_list_modules
|
461 common lsm_list_modules sys_lsm_list_modules
|
||||||
462 common mseal sys_mseal
|
462 common mseal sys_mseal
|
||||||
|
463 common setxattrat sys_setxattrat
|
||||||
|
464 common getxattrat sys_getxattrat
|
||||||
|
465 common listxattrat sys_listxattrat
|
||||||
|
466 common removexattrat sys_removexattrat
|
||||||
|
@ -553,3 +553,7 @@
|
|||||||
460 common lsm_set_self_attr sys_lsm_set_self_attr
|
460 common lsm_set_self_attr sys_lsm_set_self_attr
|
||||||
461 common lsm_list_modules sys_lsm_list_modules
|
461 common lsm_list_modules sys_lsm_list_modules
|
||||||
462 common mseal sys_mseal
|
462 common mseal sys_mseal
|
||||||
|
463 common setxattrat sys_setxattrat
|
||||||
|
464 common getxattrat sys_getxattrat
|
||||||
|
465 common listxattrat sys_listxattrat
|
||||||
|
466 common removexattrat sys_removexattrat
|
||||||
|
@ -465,3 +465,7 @@
|
|||||||
460 common lsm_set_self_attr sys_lsm_set_self_attr sys_lsm_set_self_attr
|
460 common lsm_set_self_attr sys_lsm_set_self_attr sys_lsm_set_self_attr
|
||||||
461 common lsm_list_modules sys_lsm_list_modules sys_lsm_list_modules
|
461 common lsm_list_modules sys_lsm_list_modules sys_lsm_list_modules
|
||||||
462 common mseal sys_mseal sys_mseal
|
462 common mseal sys_mseal sys_mseal
|
||||||
|
463 common setxattrat sys_setxattrat sys_setxattrat
|
||||||
|
464 common getxattrat sys_getxattrat sys_getxattrat
|
||||||
|
465 common listxattrat sys_listxattrat sys_listxattrat
|
||||||
|
466 common removexattrat sys_removexattrat sys_removexattrat
|
||||||
|
@ -466,3 +466,7 @@
|
|||||||
460 common lsm_set_self_attr sys_lsm_set_self_attr
|
460 common lsm_set_self_attr sys_lsm_set_self_attr
|
||||||
461 common lsm_list_modules sys_lsm_list_modules
|
461 common lsm_list_modules sys_lsm_list_modules
|
||||||
462 common mseal sys_mseal
|
462 common mseal sys_mseal
|
||||||
|
463 common setxattrat sys_setxattrat
|
||||||
|
464 common getxattrat sys_getxattrat
|
||||||
|
465 common listxattrat sys_listxattrat
|
||||||
|
466 common removexattrat sys_removexattrat
|
||||||
|
@ -508,3 +508,7 @@
|
|||||||
460 common lsm_set_self_attr sys_lsm_set_self_attr
|
460 common lsm_set_self_attr sys_lsm_set_self_attr
|
||||||
461 common lsm_list_modules sys_lsm_list_modules
|
461 common lsm_list_modules sys_lsm_list_modules
|
||||||
462 common mseal sys_mseal
|
462 common mseal sys_mseal
|
||||||
|
463 common setxattrat sys_setxattrat
|
||||||
|
464 common getxattrat sys_getxattrat
|
||||||
|
465 common listxattrat sys_listxattrat
|
||||||
|
466 common removexattrat sys_removexattrat
|
||||||
|
@ -468,3 +468,7 @@
|
|||||||
460 i386 lsm_set_self_attr sys_lsm_set_self_attr
|
460 i386 lsm_set_self_attr sys_lsm_set_self_attr
|
||||||
461 i386 lsm_list_modules sys_lsm_list_modules
|
461 i386 lsm_list_modules sys_lsm_list_modules
|
||||||
462 i386 mseal sys_mseal
|
462 i386 mseal sys_mseal
|
||||||
|
463 i386 setxattrat sys_setxattrat
|
||||||
|
464 i386 getxattrat sys_getxattrat
|
||||||
|
465 i386 listxattrat sys_listxattrat
|
||||||
|
466 i386 removexattrat sys_removexattrat
|
||||||
|
@ -386,6 +386,10 @@
|
|||||||
460 common lsm_set_self_attr sys_lsm_set_self_attr
|
460 common lsm_set_self_attr sys_lsm_set_self_attr
|
||||||
461 common lsm_list_modules sys_lsm_list_modules
|
461 common lsm_list_modules sys_lsm_list_modules
|
||||||
462 common mseal sys_mseal
|
462 common mseal sys_mseal
|
||||||
|
463 common setxattrat sys_setxattrat
|
||||||
|
464 common getxattrat sys_getxattrat
|
||||||
|
465 common listxattrat sys_listxattrat
|
||||||
|
466 common removexattrat sys_removexattrat
|
||||||
|
|
||||||
#
|
#
|
||||||
# Due to a historical design error, certain syscalls are numbered differently
|
# Due to a historical design error, certain syscalls are numbered differently
|
||||||
|
@ -433,3 +433,7 @@
|
|||||||
460 common lsm_set_self_attr sys_lsm_set_self_attr
|
460 common lsm_set_self_attr sys_lsm_set_self_attr
|
||||||
461 common lsm_list_modules sys_lsm_list_modules
|
461 common lsm_list_modules sys_lsm_list_modules
|
||||||
462 common mseal sys_mseal
|
462 common mseal sys_mseal
|
||||||
|
463 common setxattrat sys_setxattrat
|
||||||
|
464 common getxattrat sys_getxattrat
|
||||||
|
465 common listxattrat sys_listxattrat
|
||||||
|
466 common removexattrat sys_removexattrat
|
||||||
|
245
fs/xattr.c
245
fs/xattr.c
@ -676,69 +676,90 @@ out:
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int path_setxattr(const char __user *pathname,
|
static int path_setxattrat(int dfd, const char __user *pathname,
|
||||||
const char __user *name, const void __user *value,
|
unsigned int at_flags, const char __user *name,
|
||||||
size_t size, int flags, unsigned int lookup_flags)
|
const void __user *value, size_t size, int flags)
|
||||||
{
|
{
|
||||||
struct xattr_name kname;
|
struct xattr_name kname;
|
||||||
struct kernel_xattr_ctx ctx = {
|
struct kernel_xattr_ctx ctx = {
|
||||||
.cvalue = value,
|
.cvalue = value,
|
||||||
.kvalue = NULL,
|
.kvalue = NULL,
|
||||||
.size = size,
|
.size = size,
|
||||||
.kname = &kname,
|
.kname = &kname,
|
||||||
.flags = flags,
|
.flags = flags,
|
||||||
};
|
};
|
||||||
|
struct filename *filename;
|
||||||
|
unsigned int lookup_flags = 0;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
if ((at_flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (!(at_flags & AT_SYMLINK_NOFOLLOW))
|
||||||
|
lookup_flags = LOOKUP_FOLLOW;
|
||||||
|
|
||||||
error = setxattr_copy(name, &ctx);
|
error = setxattr_copy(name, &ctx);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
error = filename_setxattr(AT_FDCWD, getname(pathname), lookup_flags,
|
filename = getname_maybe_null(pathname, at_flags);
|
||||||
&ctx);
|
if (!filename) {
|
||||||
|
CLASS(fd, f)(dfd);
|
||||||
|
if (fd_empty(f))
|
||||||
|
error = -EBADF;
|
||||||
|
else
|
||||||
|
error = file_setxattr(fd_file(f), &ctx);
|
||||||
|
} else {
|
||||||
|
error = filename_setxattr(dfd, filename, lookup_flags, &ctx);
|
||||||
|
}
|
||||||
kvfree(ctx.kvalue);
|
kvfree(ctx.kvalue);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SYSCALL_DEFINE6(setxattrat, int, dfd, const char __user *, pathname, unsigned int, at_flags,
|
||||||
|
const char __user *, name, const struct xattr_args __user *, uargs,
|
||||||
|
size_t, usize)
|
||||||
|
{
|
||||||
|
struct xattr_args args = {};
|
||||||
|
int error;
|
||||||
|
|
||||||
|
BUILD_BUG_ON(sizeof(struct xattr_args) < XATTR_ARGS_SIZE_VER0);
|
||||||
|
BUILD_BUG_ON(sizeof(struct xattr_args) != XATTR_ARGS_SIZE_LATEST);
|
||||||
|
|
||||||
|
if (unlikely(usize < XATTR_ARGS_SIZE_VER0))
|
||||||
|
return -EINVAL;
|
||||||
|
if (usize > PAGE_SIZE)
|
||||||
|
return -E2BIG;
|
||||||
|
|
||||||
|
error = copy_struct_from_user(&args, sizeof(args), uargs, usize);
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
return path_setxattrat(dfd, pathname, at_flags, name,
|
||||||
|
u64_to_user_ptr(args.value), args.size,
|
||||||
|
args.flags);
|
||||||
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE5(setxattr, const char __user *, pathname,
|
SYSCALL_DEFINE5(setxattr, const char __user *, pathname,
|
||||||
const char __user *, name, const void __user *, value,
|
const char __user *, name, const void __user *, value,
|
||||||
size_t, size, int, flags)
|
size_t, size, int, flags)
|
||||||
{
|
{
|
||||||
return path_setxattr(pathname, name, value, size, flags, LOOKUP_FOLLOW);
|
return path_setxattrat(AT_FDCWD, pathname, 0, name, value, size, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE5(lsetxattr, const char __user *, pathname,
|
SYSCALL_DEFINE5(lsetxattr, const char __user *, pathname,
|
||||||
const char __user *, name, const void __user *, value,
|
const char __user *, name, const void __user *, value,
|
||||||
size_t, size, int, flags)
|
size_t, size, int, flags)
|
||||||
{
|
{
|
||||||
return path_setxattr(pathname, name, value, size, flags, 0);
|
return path_setxattrat(AT_FDCWD, pathname, AT_SYMLINK_NOFOLLOW, name,
|
||||||
|
value, size, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name,
|
SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name,
|
||||||
const void __user *,value, size_t, size, int, flags)
|
const void __user *,value, size_t, size, int, flags)
|
||||||
{
|
{
|
||||||
struct xattr_name kname;
|
return path_setxattrat(fd, NULL, AT_EMPTY_PATH, name,
|
||||||
struct kernel_xattr_ctx ctx = {
|
value, size, flags);
|
||||||
.cvalue = value,
|
|
||||||
.kvalue = NULL,
|
|
||||||
.size = size,
|
|
||||||
.kname = &kname,
|
|
||||||
.flags = flags,
|
|
||||||
};
|
|
||||||
int error;
|
|
||||||
|
|
||||||
CLASS(fd, f)(fd);
|
|
||||||
|
|
||||||
if (fd_empty(f))
|
|
||||||
return -EBADF;
|
|
||||||
|
|
||||||
error = setxattr_copy(name, &ctx);
|
|
||||||
if (error)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
error = file_setxattr(fd_file(f), &ctx);
|
|
||||||
kvfree(ctx.kvalue);
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -804,11 +825,10 @@ out:
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t path_getxattr(const char __user *pathname,
|
static ssize_t path_getxattrat(int dfd, const char __user *pathname,
|
||||||
const char __user *name, void __user *value,
|
unsigned int at_flags, const char __user *name,
|
||||||
size_t size, unsigned int lookup_flags)
|
void __user *value, size_t size)
|
||||||
{
|
{
|
||||||
ssize_t error;
|
|
||||||
struct xattr_name kname;
|
struct xattr_name kname;
|
||||||
struct kernel_xattr_ctx ctx = {
|
struct kernel_xattr_ctx ctx = {
|
||||||
.value = value,
|
.value = value,
|
||||||
@ -816,44 +836,72 @@ static ssize_t path_getxattr(const char __user *pathname,
|
|||||||
.kname = &kname,
|
.kname = &kname,
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
};
|
};
|
||||||
|
struct filename *filename;
|
||||||
|
ssize_t error;
|
||||||
|
|
||||||
|
if ((at_flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
error = import_xattr_name(&kname, name);
|
error = import_xattr_name(&kname, name);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
return filename_getxattr(AT_FDCWD, getname(pathname), lookup_flags, &ctx);
|
|
||||||
|
filename = getname_maybe_null(pathname, at_flags);
|
||||||
|
if (!filename) {
|
||||||
|
CLASS(fd, f)(dfd);
|
||||||
|
if (fd_empty(f))
|
||||||
|
return -EBADF;
|
||||||
|
return file_getxattr(fd_file(f), &ctx);
|
||||||
|
} else {
|
||||||
|
int lookup_flags = 0;
|
||||||
|
if (!(at_flags & AT_SYMLINK_NOFOLLOW))
|
||||||
|
lookup_flags = LOOKUP_FOLLOW;
|
||||||
|
return filename_getxattr(dfd, filename, lookup_flags, &ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SYSCALL_DEFINE6(getxattrat, int, dfd, const char __user *, pathname, unsigned int, at_flags,
|
||||||
|
const char __user *, name, struct xattr_args __user *, uargs, size_t, usize)
|
||||||
|
{
|
||||||
|
struct xattr_args args = {};
|
||||||
|
int error;
|
||||||
|
|
||||||
|
BUILD_BUG_ON(sizeof(struct xattr_args) < XATTR_ARGS_SIZE_VER0);
|
||||||
|
BUILD_BUG_ON(sizeof(struct xattr_args) != XATTR_ARGS_SIZE_LATEST);
|
||||||
|
|
||||||
|
if (unlikely(usize < XATTR_ARGS_SIZE_VER0))
|
||||||
|
return -EINVAL;
|
||||||
|
if (usize > PAGE_SIZE)
|
||||||
|
return -E2BIG;
|
||||||
|
|
||||||
|
error = copy_struct_from_user(&args, sizeof(args), uargs, usize);
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
if (args.flags != 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return path_getxattrat(dfd, pathname, at_flags, name,
|
||||||
|
u64_to_user_ptr(args.value), args.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE4(getxattr, const char __user *, pathname,
|
SYSCALL_DEFINE4(getxattr, const char __user *, pathname,
|
||||||
const char __user *, name, void __user *, value, size_t, size)
|
const char __user *, name, void __user *, value, size_t, size)
|
||||||
{
|
{
|
||||||
return path_getxattr(pathname, name, value, size, LOOKUP_FOLLOW);
|
return path_getxattrat(AT_FDCWD, pathname, 0, name, value, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE4(lgetxattr, const char __user *, pathname,
|
SYSCALL_DEFINE4(lgetxattr, const char __user *, pathname,
|
||||||
const char __user *, name, void __user *, value, size_t, size)
|
const char __user *, name, void __user *, value, size_t, size)
|
||||||
{
|
{
|
||||||
return path_getxattr(pathname, name, value, size, 0);
|
return path_getxattrat(AT_FDCWD, pathname, AT_SYMLINK_NOFOLLOW, name,
|
||||||
|
value, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE4(fgetxattr, int, fd, const char __user *, name,
|
SYSCALL_DEFINE4(fgetxattr, int, fd, const char __user *, name,
|
||||||
void __user *, value, size_t, size)
|
void __user *, value, size_t, size)
|
||||||
{
|
{
|
||||||
ssize_t error;
|
return path_getxattrat(fd, NULL, AT_EMPTY_PATH, name, value, size);
|
||||||
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;
|
|
||||||
error = import_xattr_name(&kname, name);
|
|
||||||
if (error)
|
|
||||||
return error;
|
|
||||||
return file_getxattr(fd_file(f), &ctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -918,32 +966,50 @@ out:
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t path_listxattr(const char __user *pathname, char __user *list,
|
static ssize_t path_listxattrat(int dfd, const char __user *pathname,
|
||||||
size_t size, unsigned int lookup_flags)
|
unsigned int at_flags, char __user *list,
|
||||||
|
size_t size)
|
||||||
{
|
{
|
||||||
return filename_listxattr(AT_FDCWD, getname(pathname), lookup_flags,
|
struct filename *filename;
|
||||||
list, size);
|
int lookup_flags;
|
||||||
|
|
||||||
|
if ((at_flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
filename = getname_maybe_null(pathname, at_flags);
|
||||||
|
if (!filename) {
|
||||||
|
CLASS(fd, f)(dfd);
|
||||||
|
if (fd_empty(f))
|
||||||
|
return -EBADF;
|
||||||
|
return file_listxattr(fd_file(f), list, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
lookup_flags = (at_flags & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
|
||||||
|
return filename_listxattr(dfd, filename, lookup_flags, list, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
SYSCALL_DEFINE5(listxattrat, int, dfd, const char __user *, pathname,
|
||||||
|
unsigned int, at_flags,
|
||||||
|
char __user *, list, size_t, size)
|
||||||
|
{
|
||||||
|
return path_listxattrat(dfd, pathname, at_flags, list, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE3(listxattr, const char __user *, pathname, char __user *, list,
|
SYSCALL_DEFINE3(listxattr, const char __user *, pathname, char __user *, list,
|
||||||
size_t, size)
|
size_t, size)
|
||||||
{
|
{
|
||||||
return path_listxattr(pathname, list, size, LOOKUP_FOLLOW);
|
return path_listxattrat(AT_FDCWD, pathname, 0, list, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE3(llistxattr, const char __user *, pathname, char __user *, list,
|
SYSCALL_DEFINE3(llistxattr, const char __user *, pathname, char __user *, list,
|
||||||
size_t, size)
|
size_t, size)
|
||||||
{
|
{
|
||||||
return path_listxattr(pathname, list, size, 0);
|
return path_listxattrat(AT_FDCWD, pathname, AT_SYMLINK_NOFOLLOW, list, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE3(flistxattr, int, fd, char __user *, list, size_t, size)
|
SYSCALL_DEFINE3(flistxattr, int, fd, char __user *, list, size_t, size)
|
||||||
{
|
{
|
||||||
CLASS(fd, f)(fd);
|
return path_listxattrat(fd, NULL, AT_EMPTY_PATH, list, size);
|
||||||
|
|
||||||
if (fd_empty(f))
|
|
||||||
return -EBADF;
|
|
||||||
return file_listxattr(fd_file(f), list, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -996,44 +1062,53 @@ out:
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int path_removexattr(const char __user *pathname,
|
static int path_removexattrat(int dfd, const char __user *pathname,
|
||||||
const char __user *name, unsigned int lookup_flags)
|
unsigned int at_flags, const char __user *name)
|
||||||
{
|
{
|
||||||
struct xattr_name kname;
|
struct xattr_name kname;
|
||||||
|
struct filename *filename;
|
||||||
|
unsigned int lookup_flags;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
if ((at_flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
error = import_xattr_name(&kname, name);
|
error = import_xattr_name(&kname, name);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
return filename_removexattr(AT_FDCWD, getname(pathname), lookup_flags,
|
|
||||||
&kname);
|
filename = getname_maybe_null(pathname, at_flags);
|
||||||
|
if (!filename) {
|
||||||
|
CLASS(fd, f)(dfd);
|
||||||
|
if (fd_empty(f))
|
||||||
|
return -EBADF;
|
||||||
|
return file_removexattr(fd_file(f), &kname);
|
||||||
|
}
|
||||||
|
lookup_flags = (at_flags & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
|
||||||
|
return filename_removexattr(dfd, filename, lookup_flags, &kname);
|
||||||
|
}
|
||||||
|
|
||||||
|
SYSCALL_DEFINE4(removexattrat, int, dfd, const char __user *, pathname,
|
||||||
|
unsigned int, at_flags, const char __user *, name)
|
||||||
|
{
|
||||||
|
return path_removexattrat(dfd, pathname, at_flags, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE2(removexattr, const char __user *, pathname,
|
SYSCALL_DEFINE2(removexattr, const char __user *, pathname,
|
||||||
const char __user *, name)
|
const char __user *, name)
|
||||||
{
|
{
|
||||||
return path_removexattr(pathname, name, LOOKUP_FOLLOW);
|
return path_removexattrat(AT_FDCWD, pathname, 0, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE2(lremovexattr, const char __user *, pathname,
|
SYSCALL_DEFINE2(lremovexattr, const char __user *, pathname,
|
||||||
const char __user *, name)
|
const char __user *, name)
|
||||||
{
|
{
|
||||||
return path_removexattr(pathname, name, 0);
|
return path_removexattrat(AT_FDCWD, pathname, AT_SYMLINK_NOFOLLOW, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name)
|
SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name)
|
||||||
{
|
{
|
||||||
CLASS(fd, f)(fd);
|
return path_removexattrat(fd, NULL, AT_EMPTY_PATH, name);
|
||||||
struct xattr_name kname;
|
|
||||||
int error;
|
|
||||||
|
|
||||||
if (fd_empty(f))
|
|
||||||
return -EBADF;
|
|
||||||
|
|
||||||
error = import_xattr_name(&kname, name);
|
|
||||||
if (error)
|
|
||||||
return error;
|
|
||||||
return file_removexattr(fd_file(f), &kname);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int xattr_list_one(char **buffer, ssize_t *remaining_size, const char *name)
|
int xattr_list_one(char **buffer, ssize_t *remaining_size, const char *name)
|
||||||
|
@ -11,9 +11,15 @@ __NR_lchown,
|
|||||||
__NR_fchown,
|
__NR_fchown,
|
||||||
#endif
|
#endif
|
||||||
__NR_setxattr,
|
__NR_setxattr,
|
||||||
|
#ifdef __NR_setxattrat
|
||||||
|
__NR_setxattrat,
|
||||||
|
#endif
|
||||||
__NR_lsetxattr,
|
__NR_lsetxattr,
|
||||||
__NR_fsetxattr,
|
__NR_fsetxattr,
|
||||||
__NR_removexattr,
|
__NR_removexattr,
|
||||||
|
#ifdef __NR_removexattrat
|
||||||
|
__NR_removexattrat,
|
||||||
|
#endif
|
||||||
__NR_lremovexattr,
|
__NR_lremovexattr,
|
||||||
__NR_fremovexattr,
|
__NR_fremovexattr,
|
||||||
#ifdef __NR_fchownat
|
#ifdef __NR_fchownat
|
||||||
|
@ -77,6 +77,7 @@ struct cachestat_range;
|
|||||||
struct cachestat;
|
struct cachestat;
|
||||||
struct statmount;
|
struct statmount;
|
||||||
struct mnt_id_req;
|
struct mnt_id_req;
|
||||||
|
struct xattr_args;
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/aio_abi.h>
|
#include <linux/aio_abi.h>
|
||||||
@ -338,23 +339,35 @@ asmlinkage long sys_io_uring_register(unsigned int fd, unsigned int op,
|
|||||||
void __user *arg, unsigned int nr_args);
|
void __user *arg, unsigned int nr_args);
|
||||||
asmlinkage long sys_setxattr(const char __user *path, const char __user *name,
|
asmlinkage long sys_setxattr(const char __user *path, const char __user *name,
|
||||||
const void __user *value, size_t size, int flags);
|
const void __user *value, size_t size, int flags);
|
||||||
|
asmlinkage long sys_setxattrat(int dfd, const char __user *path, unsigned int at_flags,
|
||||||
|
const char __user *name,
|
||||||
|
const struct xattr_args __user *args, size_t size);
|
||||||
asmlinkage long sys_lsetxattr(const char __user *path, const char __user *name,
|
asmlinkage long sys_lsetxattr(const char __user *path, const char __user *name,
|
||||||
const void __user *value, size_t size, int flags);
|
const void __user *value, size_t size, int flags);
|
||||||
asmlinkage long sys_fsetxattr(int fd, const char __user *name,
|
asmlinkage long sys_fsetxattr(int fd, const char __user *name,
|
||||||
const void __user *value, size_t size, int flags);
|
const void __user *value, size_t size, int flags);
|
||||||
asmlinkage long sys_getxattr(const char __user *path, const char __user *name,
|
asmlinkage long sys_getxattr(const char __user *path, const char __user *name,
|
||||||
void __user *value, size_t size);
|
void __user *value, size_t size);
|
||||||
|
asmlinkage long sys_getxattrat(int dfd, const char __user *path, unsigned int at_flags,
|
||||||
|
const char __user *name,
|
||||||
|
struct xattr_args __user *args, size_t size);
|
||||||
asmlinkage long sys_lgetxattr(const char __user *path, const char __user *name,
|
asmlinkage long sys_lgetxattr(const char __user *path, const char __user *name,
|
||||||
void __user *value, size_t size);
|
void __user *value, size_t size);
|
||||||
asmlinkage long sys_fgetxattr(int fd, const char __user *name,
|
asmlinkage long sys_fgetxattr(int fd, const char __user *name,
|
||||||
void __user *value, size_t size);
|
void __user *value, size_t size);
|
||||||
asmlinkage long sys_listxattr(const char __user *path, char __user *list,
|
asmlinkage long sys_listxattr(const char __user *path, char __user *list,
|
||||||
size_t size);
|
size_t size);
|
||||||
|
asmlinkage long sys_listxattrat(int dfd, const char __user *path,
|
||||||
|
unsigned int at_flags,
|
||||||
|
char __user *list, size_t size);
|
||||||
asmlinkage long sys_llistxattr(const char __user *path, char __user *list,
|
asmlinkage long sys_llistxattr(const char __user *path, char __user *list,
|
||||||
size_t size);
|
size_t size);
|
||||||
asmlinkage long sys_flistxattr(int fd, char __user *list, size_t size);
|
asmlinkage long sys_flistxattr(int fd, char __user *list, size_t size);
|
||||||
asmlinkage long sys_removexattr(const char __user *path,
|
asmlinkage long sys_removexattr(const char __user *path,
|
||||||
const char __user *name);
|
const char __user *name);
|
||||||
|
asmlinkage long sys_removexattrat(int dfd, const char __user *path,
|
||||||
|
unsigned int at_flags,
|
||||||
|
const char __user *name);
|
||||||
asmlinkage long sys_lremovexattr(const char __user *path,
|
asmlinkage long sys_lremovexattr(const char __user *path,
|
||||||
const char __user *name);
|
const char __user *name);
|
||||||
asmlinkage long sys_fremovexattr(int fd, const char __user *name);
|
asmlinkage long sys_fremovexattr(int fd, const char __user *name);
|
||||||
|
@ -19,6 +19,10 @@
|
|||||||
#include <linux/user_namespace.h>
|
#include <linux/user_namespace.h>
|
||||||
#include <uapi/linux/xattr.h>
|
#include <uapi/linux/xattr.h>
|
||||||
|
|
||||||
|
/* List of all open_how "versions". */
|
||||||
|
#define XATTR_ARGS_SIZE_VER0 16 /* sizeof first published struct */
|
||||||
|
#define XATTR_ARGS_SIZE_LATEST XATTR_ARGS_SIZE_VER0
|
||||||
|
|
||||||
struct inode;
|
struct inode;
|
||||||
struct dentry;
|
struct dentry;
|
||||||
|
|
||||||
|
@ -841,8 +841,17 @@ __SYSCALL(__NR_lsm_list_modules, sys_lsm_list_modules)
|
|||||||
#define __NR_mseal 462
|
#define __NR_mseal 462
|
||||||
__SYSCALL(__NR_mseal, sys_mseal)
|
__SYSCALL(__NR_mseal, sys_mseal)
|
||||||
|
|
||||||
|
#define __NR_setxattrat 463
|
||||||
|
__SYSCALL(__NR_setxattrat, sys_setxattrat)
|
||||||
|
#define __NR_getxattrat 464
|
||||||
|
__SYSCALL(__NR_getxattrat, sys_getxattrat)
|
||||||
|
#define __NR_listxattrat 465
|
||||||
|
__SYSCALL(__NR_listxattrat, sys_listxattrat)
|
||||||
|
#define __NR_removexattrat 466
|
||||||
|
__SYSCALL(__NR_removexattrat, sys_removexattrat)
|
||||||
|
|
||||||
#undef __NR_syscalls
|
#undef __NR_syscalls
|
||||||
#define __NR_syscalls 463
|
#define __NR_syscalls 467
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 32 bit systems traditionally used different
|
* 32 bit systems traditionally used different
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/libc-compat.h>
|
#include <linux/libc-compat.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
#ifndef _UAPI_LINUX_XATTR_H
|
#ifndef _UAPI_LINUX_XATTR_H
|
||||||
#define _UAPI_LINUX_XATTR_H
|
#define _UAPI_LINUX_XATTR_H
|
||||||
@ -20,6 +21,12 @@
|
|||||||
|
|
||||||
#define XATTR_CREATE 0x1 /* set value, fail if attr already exists */
|
#define XATTR_CREATE 0x1 /* set value, fail if attr already exists */
|
||||||
#define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */
|
#define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */
|
||||||
|
|
||||||
|
struct xattr_args {
|
||||||
|
__aligned_u64 __user value;
|
||||||
|
__u32 size;
|
||||||
|
__u32 flags;
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Namespaces */
|
/* Namespaces */
|
||||||
|
@ -403,3 +403,7 @@
|
|||||||
460 common lsm_set_self_attr sys_lsm_set_self_attr
|
460 common lsm_set_self_attr sys_lsm_set_self_attr
|
||||||
461 common lsm_list_modules sys_lsm_list_modules
|
461 common lsm_list_modules sys_lsm_list_modules
|
||||||
462 common mseal sys_mseal
|
462 common mseal sys_mseal
|
||||||
|
463 common setxattrat sys_setxattrat
|
||||||
|
464 common getxattrat sys_getxattrat
|
||||||
|
465 common listxattrat sys_listxattrat
|
||||||
|
466 common removexattrat sys_removexattrat
|
||||||
|
Loading…
Reference in New Issue
Block a user