]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
fs/xattr: add *at family syscalls
authorChristian Göttsche <cgzones@googlemail.com>
Fri, 26 Apr 2024 16:20:14 +0000 (18:20 +0200)
committerAl Viro <viro@zeniv.linux.org.uk>
Wed, 6 Nov 2024 17:59:44 +0000 (12:59 -0500)
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>
23 files changed:
arch/alpha/kernel/syscalls/syscall.tbl
arch/arm/tools/syscall.tbl
arch/arm64/tools/syscall_32.tbl
arch/m68k/kernel/syscalls/syscall.tbl
arch/microblaze/kernel/syscalls/syscall.tbl
arch/mips/kernel/syscalls/syscall_n32.tbl
arch/mips/kernel/syscalls/syscall_n64.tbl
arch/mips/kernel/syscalls/syscall_o32.tbl
arch/parisc/kernel/syscalls/syscall.tbl
arch/powerpc/kernel/syscalls/syscall.tbl
arch/s390/kernel/syscalls/syscall.tbl
arch/sh/kernel/syscalls/syscall.tbl
arch/sparc/kernel/syscalls/syscall.tbl
arch/x86/entry/syscalls/syscall_32.tbl
arch/x86/entry/syscalls/syscall_64.tbl
arch/xtensa/kernel/syscalls/syscall.tbl
fs/xattr.c
include/asm-generic/audit_change_attr.h
include/linux/syscalls.h
include/linux/xattr.h
include/uapi/asm-generic/unistd.h
include/uapi/linux/xattr.h
scripts/syscall.tbl

index 74720667fe091768800a22fd4ce68b5324abff09..c59d53d6d3f3490f976ca179ddfe02e69265ae4d 100644 (file)
 570    common  lsm_set_self_attr               sys_lsm_set_self_attr
 571    common  lsm_list_modules                sys_lsm_list_modules
 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
index 23c98203c40fe6b7b80cc17df29be48d26423c09..49eeb2ad8dbd8e074c6240417693f23fb328afa8 100644 (file)
 460    common  lsm_set_self_attr               sys_lsm_set_self_attr
 461    common  lsm_list_modules                sys_lsm_list_modules
 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
index 9a37930d4e26f0c6cb8fe78f76bb1a4f32cbea16..69a829912a05eb8a3e21ed701d1030e31c0148bc 100644 (file)
 460    common  lsm_set_self_attr               sys_lsm_set_self_attr
 461    common  lsm_list_modules                sys_lsm_list_modules
 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
index 22a3cbd4c602983206263900e7f1e1211d31a068..f5ed71f1910d09769c845c2d062d99ee0449437c 100644 (file)
 460    common  lsm_set_self_attr               sys_lsm_set_self_attr
 461    common  lsm_list_modules                sys_lsm_list_modules
 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
index 2b81a6bd78b29207c948874c8b782e42677459e1..680f568b77f2cbefc3eacb2517f276041f229b1e 100644 (file)
 460    common  lsm_set_self_attr               sys_lsm_set_self_attr
 461    common  lsm_list_modules                sys_lsm_list_modules
 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
index 953f5b7dc723f60254ed7e5b256d3b611ae7dd13..0b9b7e25b69ad592642f8533bee9ccfe95ce9626 100644 (file)
 460    n32     lsm_set_self_attr               sys_lsm_set_self_attr
 461    n32     lsm_list_modules                sys_lsm_list_modules
 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
index 1464c6be6eb3c752eba0f7deccdd5b3ad7794aa6..c844cd5cda620b2809a397cdd6f4315ab6a1bfe2 100644 (file)
 460    n64     lsm_set_self_attr               sys_lsm_set_self_attr
 461    n64     lsm_list_modules                sys_lsm_list_modules
 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
index 2439a2491cffe30692cb721b98e0c059ec656297..349b8aad1159f404103bd2057a1e64e9bf309f18 100644 (file)
 460    o32     lsm_set_self_attr               sys_lsm_set_self_attr
 461    o32     lsm_list_modules                sys_lsm_list_modules
 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
index 66dc406b12e4482832b0e8836b8267b0fb37a5ed..d9fc94c869657fcfbd7aca1d5f5abc9fae2fb9d8 100644 (file)
 460    common  lsm_set_self_attr               sys_lsm_set_self_attr
 461    common  lsm_list_modules                sys_lsm_list_modules
 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
index ebae8415dfbbab6f6f0802913e7d0ef5de37ac70..d8b4ab78bef076bd50d49b87dea5060fd8c1686a 100644 (file)
 460    common  lsm_set_self_attr               sys_lsm_set_self_attr
 461    common  lsm_list_modules                sys_lsm_list_modules
 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
index 01071182763e96ff03b5d74e4b9c4387ab84c456..e9115b4d8b635b846e5c9ad6ce229605323723a5 100644 (file)
 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
 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
index c55fd7696d40fc4844a66b9061bffbb399b9ac8b..c8cad33bf250ea110de37bd1407f5a43ec5e38f2 100644 (file)
 460    common  lsm_set_self_attr               sys_lsm_set_self_attr
 461    common  lsm_list_modules                sys_lsm_list_modules
 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
index cfdfb3707c167cd26aefc6412accfefbddfef937..727f99d333b304b3db0711953a3d91ece18a28eb 100644 (file)
 460    common  lsm_set_self_attr               sys_lsm_set_self_attr
 461    common  lsm_list_modules                sys_lsm_list_modules
 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
index 534c74b14fab511709be06ae1491b9922a66841b..4d0fb2fba7e208ae9455459afe11e277321d9f74 100644 (file)
 460    i386    lsm_set_self_attr       sys_lsm_set_self_attr
 461    i386    lsm_list_modules        sys_lsm_list_modules
 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
index 7093ee21c0d1c0410dbf17a77cb70a6bc6736f04..5eb708bff1c791debd6cfc5322583b2ae53f6437 100644 (file)
 460    common  lsm_set_self_attr       sys_lsm_set_self_attr
 461    common  lsm_list_modules        sys_lsm_list_modules
 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
index 67083fc1b2f56383d369f8b5337d7ce0b43c157b..37effc1b134eea061f2c350c1d68b4436b65a4dd 100644 (file)
 460    common  lsm_set_self_attr               sys_lsm_set_self_attr
 461    common  lsm_list_modules                sys_lsm_list_modules
 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
index b76911b23293fabbe99a6c67abb05c9c4ae06ce0..deb336b821c92510c1103176f1f26bbdd94cb86f 100644 (file)
@@ -676,69 +676,90 @@ out:
        return error;
 }
 
-static int path_setxattr(const char __user *pathname,
-                        const char __user *name, const void __user *value,
-                        size_t size, int flags, unsigned int lookup_flags)
+static int path_setxattrat(int dfd, const char __user *pathname,
+                          unsigned int at_flags, const char __user *name,
+                          const void __user *value, size_t size, int flags)
 {
        struct xattr_name kname;
        struct kernel_xattr_ctx ctx = {
-               .cvalue   = value,
-               .kvalue   = NULL,
-               .size     = size,
-               .kname    = &kname,
-               .flags    = flags,
+               .cvalue = value,
+               .kvalue = NULL,
+               .size   = size,
+               .kname  = &kname,
+               .flags  = flags,
        };
+       struct filename *filename;
+       unsigned int lookup_flags = 0;
        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);
        if (error)
                return error;
 
-       error = filename_setxattr(AT_FDCWD, getname(pathname), lookup_flags,
-                                 &ctx);
+       filename = getname_maybe_null(pathname, at_flags);
+       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);
        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,
                const char __user *, name, const void __user *, value,
                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,
                const char __user *, name, const void __user *, value,
                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,
                const void __user *,value, size_t, size, int, flags)
 {
-       struct xattr_name kname;
-       struct kernel_xattr_ctx ctx = {
-               .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;
+       return path_setxattrat(fd, NULL, AT_EMPTY_PATH, name,
+                              value, size, flags);
 }
 
 /*
@@ -804,11 +825,10 @@ out:
        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)
+static ssize_t path_getxattrat(int dfd, const char __user *pathname,
+                              unsigned int at_flags, const char __user *name,
+                              void __user *value, size_t size)
 {
-       ssize_t error;
        struct xattr_name kname;
        struct kernel_xattr_ctx ctx = {
                .value    = value,
@@ -816,44 +836,72 @@ static ssize_t path_getxattr(const char __user *pathname,
                .kname    = &kname,
                .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);
        if (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,
                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,
                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,
                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;
-       error = import_xattr_name(&kname, name);
-       if (error)
-               return error;
-       return file_getxattr(fd_file(f), &ctx);
+       return path_getxattrat(fd, NULL, AT_EMPTY_PATH, name, value, size);
 }
 
 /*
@@ -918,32 +966,50 @@ out:
        return error;
 }
 
-static ssize_t path_listxattr(const char __user *pathname, char __user *list,
-                             size_t size, unsigned int lookup_flags)
+static ssize_t path_listxattrat(int dfd, const char __user *pathname,
+                               unsigned int at_flags, char __user *list,
+                               size_t size)
+{
+       struct filename *filename;
+       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 filename_listxattr(AT_FDCWD, getname(pathname), lookup_flags,
-                                 list, size);
+       return path_listxattrat(dfd, pathname, at_flags, list, size);
 }
 
 SYSCALL_DEFINE3(listxattr, const char __user *, pathname, char __user *, list,
                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,
                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)
 {
-       CLASS(fd, f)(fd);
-
-       if (fd_empty(f))
-               return -EBADF;
-       return file_listxattr(fd_file(f), list, size);
+       return path_listxattrat(fd, NULL, AT_EMPTY_PATH, list, size);
 }
 
 /*
@@ -996,44 +1062,53 @@ out:
        return error;
 }
 
-static int path_removexattr(const char __user *pathname,
-                           const char __user *name, unsigned int lookup_flags)
+static int path_removexattrat(int dfd, const char __user *pathname,
+                             unsigned int at_flags, const char __user *name)
 {
        struct xattr_name kname;
+       struct filename *filename;
+       unsigned int lookup_flags;
        int error;
 
+       if ((at_flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0)
+               return -EINVAL;
+
        error = import_xattr_name(&kname, name);
        if (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,
                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,
                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)
 {
-       CLASS(fd, f)(fd);
-       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);
+       return path_removexattrat(fd, NULL, AT_EMPTY_PATH, name);
 }
 
 int xattr_list_one(char **buffer, ssize_t *remaining_size, const char *name)
index 331670807cf011f6eea61b2066ee28e5663d51ca..cc840537885fbcd3bd470c2382cf9c49f5b05aa4 100644 (file)
@@ -11,9 +11,15 @@ __NR_lchown,
 __NR_fchown,
 #endif
 __NR_setxattr,
+#ifdef __NR_setxattrat
+__NR_setxattrat,
+#endif
 __NR_lsetxattr,
 __NR_fsetxattr,
 __NR_removexattr,
+#ifdef __NR_removexattrat
+__NR_removexattrat,
+#endif
 __NR_lremovexattr,
 __NR_fremovexattr,
 #ifdef __NR_fchownat
index 5758104921e66e2e3b815bacb1953ac892599a46..c6333204d45130eb022f6db460eea34a1f6e91db 100644 (file)
@@ -77,6 +77,7 @@ struct cachestat_range;
 struct cachestat;
 struct statmount;
 struct mnt_id_req;
+struct xattr_args;
 
 #include <linux/types.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);
 asmlinkage long sys_setxattr(const char __user *path, const char __user *name,
                             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,
                              const void __user *value, size_t size, int flags);
 asmlinkage long sys_fsetxattr(int fd, const char __user *name,
                              const void __user *value, size_t size, int flags);
 asmlinkage long sys_getxattr(const char __user *path, const char __user *name,
                             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,
                              void __user *value, size_t size);
 asmlinkage long sys_fgetxattr(int fd, const char __user *name,
                              void __user *value, size_t size);
 asmlinkage long sys_listxattr(const char __user *path, char __user *list,
                              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,
                               size_t size);
 asmlinkage long sys_flistxattr(int fd, char __user *list, size_t size);
 asmlinkage long sys_removexattr(const char __user *path,
                                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,
                                 const char __user *name);
 asmlinkage long sys_fremovexattr(int fd, const char __user *name);
index d20051865800800df5d24a0edd7a485b296ba9fa..86b0d47984a16d935dd1c45ca80a3b8bb5b7295b 100644 (file)
 #include <linux/user_namespace.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 dentry;
 
index 5bf6148cac2b93e36f362236545e2e6eb473d5ff..88dc393c2bca38c0fa1b3fae579f7cfe4931223c 100644 (file)
@@ -841,8 +841,17 @@ __SYSCALL(__NR_lsm_list_modules, sys_lsm_list_modules)
 #define __NR_mseal 462
 __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
-#define __NR_syscalls 463
+#define __NR_syscalls 467
 
 /*
  * 32 bit systems traditionally used different
index 9463db2dfa9d412dbf13051763416b7464876c0f..9854f9cff3c6615cd1024719dd11d5f8c43b7c09 100644 (file)
@@ -11,6 +11,7 @@
 */
 
 #include <linux/libc-compat.h>
+#include <linux/types.h>
 
 #ifndef _UAPI_LINUX_XATTR_H
 #define _UAPI_LINUX_XATTR_H
 
 #define XATTR_CREATE   0x1     /* set value, fail if attr already exists */
 #define XATTR_REPLACE  0x2     /* set value, fail if attr does not exist */
+
+struct xattr_args {
+       __aligned_u64 __user value;
+       __u32 size;
+       __u32 flags;
+};
 #endif
 
 /* Namespaces */
index 845e24eb372e7f2aca193a4f424b85234b4fc9c2..ebbdb3c42e9f74613b003014c0baf44c842bb756 100644 (file)
 460    common  lsm_set_self_attr               sys_lsm_set_self_attr
 461    common  lsm_list_modules                sys_lsm_list_modules
 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