Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Christian Göttsche and committed by
Al Viro
6140be90 22a4d195

+268 -86
+4
arch/alpha/kernel/syscalls/syscall.tbl
··· 502 502 570 common lsm_set_self_attr sys_lsm_set_self_attr 503 503 571 common lsm_list_modules sys_lsm_list_modules 504 504 572 common mseal sys_mseal 505 + 573 common setxattrat sys_setxattrat 506 + 574 common getxattrat sys_getxattrat 507 + 575 common listxattrat sys_listxattrat 508 + 576 common removexattrat sys_removexattrat
+4
arch/arm/tools/syscall.tbl
··· 477 477 460 common lsm_set_self_attr sys_lsm_set_self_attr 478 478 461 common lsm_list_modules sys_lsm_list_modules 479 479 462 common mseal sys_mseal 480 + 463 common setxattrat sys_setxattrat 481 + 464 common getxattrat sys_getxattrat 482 + 465 common listxattrat sys_listxattrat 483 + 466 common removexattrat sys_removexattrat
+4
arch/arm64/tools/syscall_32.tbl
··· 474 474 460 common lsm_set_self_attr sys_lsm_set_self_attr 475 475 461 common lsm_list_modules sys_lsm_list_modules 476 476 462 common mseal sys_mseal 477 + 463 common setxattrat sys_setxattrat 478 + 464 common getxattrat sys_getxattrat 479 + 465 common listxattrat sys_listxattrat 480 + 466 common removexattrat sys_removexattrat
+4
arch/m68k/kernel/syscalls/syscall.tbl
··· 462 462 460 common lsm_set_self_attr sys_lsm_set_self_attr 463 463 461 common lsm_list_modules sys_lsm_list_modules 464 464 462 common mseal sys_mseal 465 + 463 common setxattrat sys_setxattrat 466 + 464 common getxattrat sys_getxattrat 467 + 465 common listxattrat sys_listxattrat 468 + 466 common removexattrat sys_removexattrat
+4
arch/microblaze/kernel/syscalls/syscall.tbl
··· 468 468 460 common lsm_set_self_attr sys_lsm_set_self_attr 469 469 461 common lsm_list_modules sys_lsm_list_modules 470 470 462 common mseal sys_mseal 471 + 463 common setxattrat sys_setxattrat 472 + 464 common getxattrat sys_getxattrat 473 + 465 common listxattrat sys_listxattrat 474 + 466 common removexattrat sys_removexattrat
+4
arch/mips/kernel/syscalls/syscall_n32.tbl
··· 401 401 460 n32 lsm_set_self_attr sys_lsm_set_self_attr 402 402 461 n32 lsm_list_modules sys_lsm_list_modules 403 403 462 n32 mseal sys_mseal 404 + 463 n32 setxattrat sys_setxattrat 405 + 464 n32 getxattrat sys_getxattrat 406 + 465 n32 listxattrat sys_listxattrat 407 + 466 n32 removexattrat sys_removexattrat
+4
arch/mips/kernel/syscalls/syscall_n64.tbl
··· 377 377 460 n64 lsm_set_self_attr sys_lsm_set_self_attr 378 378 461 n64 lsm_list_modules sys_lsm_list_modules 379 379 462 n64 mseal sys_mseal 380 + 463 n64 setxattrat sys_setxattrat 381 + 464 n64 getxattrat sys_getxattrat 382 + 465 n64 listxattrat sys_listxattrat 383 + 466 n64 removexattrat sys_removexattrat
+4
arch/mips/kernel/syscalls/syscall_o32.tbl
··· 450 450 460 o32 lsm_set_self_attr sys_lsm_set_self_attr 451 451 461 o32 lsm_list_modules sys_lsm_list_modules 452 452 462 o32 mseal sys_mseal 453 + 463 o32 setxattrat sys_setxattrat 454 + 464 o32 getxattrat sys_getxattrat 455 + 465 o32 listxattrat sys_listxattrat 456 + 466 o32 removexattrat sys_removexattrat
+4
arch/parisc/kernel/syscalls/syscall.tbl
··· 461 461 460 common lsm_set_self_attr sys_lsm_set_self_attr 462 462 461 common lsm_list_modules sys_lsm_list_modules 463 463 462 common mseal sys_mseal 464 + 463 common setxattrat sys_setxattrat 465 + 464 common getxattrat sys_getxattrat 466 + 465 common listxattrat sys_listxattrat 467 + 466 common removexattrat sys_removexattrat
+4
arch/powerpc/kernel/syscalls/syscall.tbl
··· 553 553 460 common lsm_set_self_attr sys_lsm_set_self_attr 554 554 461 common lsm_list_modules sys_lsm_list_modules 555 555 462 common mseal sys_mseal 556 + 463 common setxattrat sys_setxattrat 557 + 464 common getxattrat sys_getxattrat 558 + 465 common listxattrat sys_listxattrat 559 + 466 common removexattrat sys_removexattrat
+4
arch/s390/kernel/syscalls/syscall.tbl
··· 465 465 460 common lsm_set_self_attr sys_lsm_set_self_attr sys_lsm_set_self_attr 466 466 461 common lsm_list_modules sys_lsm_list_modules sys_lsm_list_modules 467 467 462 common mseal sys_mseal sys_mseal 468 + 463 common setxattrat sys_setxattrat sys_setxattrat 469 + 464 common getxattrat sys_getxattrat sys_getxattrat 470 + 465 common listxattrat sys_listxattrat sys_listxattrat 471 + 466 common removexattrat sys_removexattrat sys_removexattrat
+4
arch/sh/kernel/syscalls/syscall.tbl
··· 466 466 460 common lsm_set_self_attr sys_lsm_set_self_attr 467 467 461 common lsm_list_modules sys_lsm_list_modules 468 468 462 common mseal sys_mseal 469 + 463 common setxattrat sys_setxattrat 470 + 464 common getxattrat sys_getxattrat 471 + 465 common listxattrat sys_listxattrat 472 + 466 common removexattrat sys_removexattrat
+4
arch/sparc/kernel/syscalls/syscall.tbl
··· 508 508 460 common lsm_set_self_attr sys_lsm_set_self_attr 509 509 461 common lsm_list_modules sys_lsm_list_modules 510 510 462 common mseal sys_mseal 511 + 463 common setxattrat sys_setxattrat 512 + 464 common getxattrat sys_getxattrat 513 + 465 common listxattrat sys_listxattrat 514 + 466 common removexattrat sys_removexattrat
+4
arch/x86/entry/syscalls/syscall_32.tbl
··· 468 468 460 i386 lsm_set_self_attr sys_lsm_set_self_attr 469 469 461 i386 lsm_list_modules sys_lsm_list_modules 470 470 462 i386 mseal sys_mseal 471 + 463 i386 setxattrat sys_setxattrat 472 + 464 i386 getxattrat sys_getxattrat 473 + 465 i386 listxattrat sys_listxattrat 474 + 466 i386 removexattrat sys_removexattrat
+4
arch/x86/entry/syscalls/syscall_64.tbl
··· 386 386 460 common lsm_set_self_attr sys_lsm_set_self_attr 387 387 461 common lsm_list_modules sys_lsm_list_modules 388 388 462 common mseal sys_mseal 389 + 463 common setxattrat sys_setxattrat 390 + 464 common getxattrat sys_getxattrat 391 + 465 common listxattrat sys_listxattrat 392 + 466 common removexattrat sys_removexattrat 389 393 390 394 # 391 395 # Due to a historical design error, certain syscalls are numbered differently
+4
arch/xtensa/kernel/syscalls/syscall.tbl
··· 433 433 460 common lsm_set_self_attr sys_lsm_set_self_attr 434 434 461 common lsm_list_modules sys_lsm_list_modules 435 435 462 common mseal sys_mseal 436 + 463 common setxattrat sys_setxattrat 437 + 464 common getxattrat sys_getxattrat 438 + 465 common listxattrat sys_listxattrat 439 + 466 common removexattrat sys_removexattrat
+160 -85
fs/xattr.c
··· 676 676 return error; 677 677 } 678 678 679 - static int path_setxattr(const char __user *pathname, 680 - const char __user *name, const void __user *value, 681 - size_t size, int flags, unsigned int lookup_flags) 679 + static int path_setxattrat(int dfd, const char __user *pathname, 680 + unsigned int at_flags, const char __user *name, 681 + const void __user *value, size_t size, int flags) 682 682 { 683 683 struct xattr_name kname; 684 684 struct kernel_xattr_ctx ctx = { 685 - .cvalue = value, 686 - .kvalue = NULL, 687 - .size = size, 688 - .kname = &kname, 689 - .flags = flags, 685 + .cvalue = value, 686 + .kvalue = NULL, 687 + .size = size, 688 + .kname = &kname, 689 + .flags = flags, 690 690 }; 691 + struct filename *filename; 692 + unsigned int lookup_flags = 0; 691 693 int error; 694 + 695 + if ((at_flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0) 696 + return -EINVAL; 697 + 698 + if (!(at_flags & AT_SYMLINK_NOFOLLOW)) 699 + lookup_flags = LOOKUP_FOLLOW; 692 700 693 701 error = setxattr_copy(name, &ctx); 694 702 if (error) 695 703 return error; 696 704 697 - error = filename_setxattr(AT_FDCWD, getname(pathname), lookup_flags, 698 - &ctx); 705 + filename = getname_maybe_null(pathname, at_flags); 706 + if (!filename) { 707 + CLASS(fd, f)(dfd); 708 + if (fd_empty(f)) 709 + error = -EBADF; 710 + else 711 + error = file_setxattr(fd_file(f), &ctx); 712 + } else { 713 + error = filename_setxattr(dfd, filename, lookup_flags, &ctx); 714 + } 699 715 kvfree(ctx.kvalue); 700 716 return error; 717 + } 718 + 719 + SYSCALL_DEFINE6(setxattrat, int, dfd, const char __user *, pathname, unsigned int, at_flags, 720 + const char __user *, name, const struct xattr_args __user *, uargs, 721 + size_t, usize) 722 + { 723 + struct xattr_args args = {}; 724 + int error; 725 + 726 + BUILD_BUG_ON(sizeof(struct xattr_args) < XATTR_ARGS_SIZE_VER0); 727 + BUILD_BUG_ON(sizeof(struct xattr_args) != XATTR_ARGS_SIZE_LATEST); 728 + 729 + if (unlikely(usize < XATTR_ARGS_SIZE_VER0)) 730 + return -EINVAL; 731 + if (usize > PAGE_SIZE) 732 + return -E2BIG; 733 + 734 + error = copy_struct_from_user(&args, sizeof(args), uargs, usize); 735 + if (error) 736 + return error; 737 + 738 + return path_setxattrat(dfd, pathname, at_flags, name, 739 + u64_to_user_ptr(args.value), args.size, 740 + args.flags); 701 741 } 702 742 703 743 SYSCALL_DEFINE5(setxattr, const char __user *, pathname, 704 744 const char __user *, name, const void __user *, value, 705 745 size_t, size, int, flags) 706 746 { 707 - return path_setxattr(pathname, name, value, size, flags, LOOKUP_FOLLOW); 747 + return path_setxattrat(AT_FDCWD, pathname, 0, name, value, size, flags); 708 748 } 709 749 710 750 SYSCALL_DEFINE5(lsetxattr, const char __user *, pathname, 711 751 const char __user *, name, const void __user *, value, 712 752 size_t, size, int, flags) 713 753 { 714 - return path_setxattr(pathname, name, value, size, flags, 0); 754 + return path_setxattrat(AT_FDCWD, pathname, AT_SYMLINK_NOFOLLOW, name, 755 + value, size, flags); 715 756 } 716 757 717 758 SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name, 718 759 const void __user *,value, size_t, size, int, flags) 719 760 { 720 - struct xattr_name kname; 721 - struct kernel_xattr_ctx ctx = { 722 - .cvalue = value, 723 - .kvalue = NULL, 724 - .size = size, 725 - .kname = &kname, 726 - .flags = flags, 727 - }; 728 - int error; 729 - 730 - CLASS(fd, f)(fd); 731 - 732 - if (fd_empty(f)) 733 - return -EBADF; 734 - 735 - error = setxattr_copy(name, &ctx); 736 - if (error) 737 - return error; 738 - 739 - error = file_setxattr(fd_file(f), &ctx); 740 - kvfree(ctx.kvalue); 741 - return error; 761 + return path_setxattrat(fd, NULL, AT_EMPTY_PATH, name, 762 + value, size, flags); 742 763 } 743 764 744 765 /* ··· 825 804 return error; 826 805 } 827 806 828 - static ssize_t path_getxattr(const char __user *pathname, 829 - const char __user *name, void __user *value, 830 - size_t size, unsigned int lookup_flags) 807 + static ssize_t path_getxattrat(int dfd, const char __user *pathname, 808 + unsigned int at_flags, const char __user *name, 809 + void __user *value, size_t size) 831 810 { 832 - ssize_t error; 833 811 struct xattr_name kname; 834 812 struct kernel_xattr_ctx ctx = { 835 813 .value = value, ··· 836 816 .kname = &kname, 837 817 .flags = 0, 838 818 }; 819 + struct filename *filename; 820 + ssize_t error; 821 + 822 + if ((at_flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0) 823 + return -EINVAL; 839 824 840 825 error = import_xattr_name(&kname, name); 841 826 if (error) 842 827 return error; 843 - return filename_getxattr(AT_FDCWD, getname(pathname), lookup_flags, &ctx); 828 + 829 + filename = getname_maybe_null(pathname, at_flags); 830 + if (!filename) { 831 + CLASS(fd, f)(dfd); 832 + if (fd_empty(f)) 833 + return -EBADF; 834 + return file_getxattr(fd_file(f), &ctx); 835 + } else { 836 + int lookup_flags = 0; 837 + if (!(at_flags & AT_SYMLINK_NOFOLLOW)) 838 + lookup_flags = LOOKUP_FOLLOW; 839 + return filename_getxattr(dfd, filename, lookup_flags, &ctx); 840 + } 841 + } 842 + 843 + SYSCALL_DEFINE6(getxattrat, int, dfd, const char __user *, pathname, unsigned int, at_flags, 844 + const char __user *, name, struct xattr_args __user *, uargs, size_t, usize) 845 + { 846 + struct xattr_args args = {}; 847 + int error; 848 + 849 + BUILD_BUG_ON(sizeof(struct xattr_args) < XATTR_ARGS_SIZE_VER0); 850 + BUILD_BUG_ON(sizeof(struct xattr_args) != XATTR_ARGS_SIZE_LATEST); 851 + 852 + if (unlikely(usize < XATTR_ARGS_SIZE_VER0)) 853 + return -EINVAL; 854 + if (usize > PAGE_SIZE) 855 + return -E2BIG; 856 + 857 + error = copy_struct_from_user(&args, sizeof(args), uargs, usize); 858 + if (error) 859 + return error; 860 + 861 + if (args.flags != 0) 862 + return -EINVAL; 863 + 864 + return path_getxattrat(dfd, pathname, at_flags, name, 865 + u64_to_user_ptr(args.value), args.size); 844 866 } 845 867 846 868 SYSCALL_DEFINE4(getxattr, const char __user *, pathname, 847 869 const char __user *, name, void __user *, value, size_t, size) 848 870 { 849 - return path_getxattr(pathname, name, value, size, LOOKUP_FOLLOW); 871 + return path_getxattrat(AT_FDCWD, pathname, 0, name, value, size); 850 872 } 851 873 852 874 SYSCALL_DEFINE4(lgetxattr, const char __user *, pathname, 853 875 const char __user *, name, void __user *, value, size_t, size) 854 876 { 855 - return path_getxattr(pathname, name, value, size, 0); 877 + return path_getxattrat(AT_FDCWD, pathname, AT_SYMLINK_NOFOLLOW, name, 878 + value, size); 856 879 } 857 880 858 881 SYSCALL_DEFINE4(fgetxattr, int, fd, const char __user *, name, 859 882 void __user *, value, size_t, size) 860 883 { 861 - ssize_t error; 862 - struct xattr_name kname; 863 - struct kernel_xattr_ctx ctx = { 864 - .value = value, 865 - .size = size, 866 - .kname = &kname, 867 - .flags = 0, 868 - }; 869 - CLASS(fd, f)(fd); 870 - 871 - if (fd_empty(f)) 872 - return -EBADF; 873 - error = import_xattr_name(&kname, name); 874 - if (error) 875 - return error; 876 - return file_getxattr(fd_file(f), &ctx); 884 + return path_getxattrat(fd, NULL, AT_EMPTY_PATH, name, value, size); 877 885 } 878 886 879 887 /* ··· 966 918 return error; 967 919 } 968 920 969 - static ssize_t path_listxattr(const char __user *pathname, char __user *list, 970 - size_t size, unsigned int lookup_flags) 921 + static ssize_t path_listxattrat(int dfd, const char __user *pathname, 922 + unsigned int at_flags, char __user *list, 923 + size_t size) 971 924 { 972 - return filename_listxattr(AT_FDCWD, getname(pathname), lookup_flags, 973 - list, size); 925 + struct filename *filename; 926 + int lookup_flags; 927 + 928 + if ((at_flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0) 929 + return -EINVAL; 930 + 931 + filename = getname_maybe_null(pathname, at_flags); 932 + if (!filename) { 933 + CLASS(fd, f)(dfd); 934 + if (fd_empty(f)) 935 + return -EBADF; 936 + return file_listxattr(fd_file(f), list, size); 937 + } 938 + 939 + lookup_flags = (at_flags & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW; 940 + return filename_listxattr(dfd, filename, lookup_flags, list, size); 941 + } 942 + 943 + SYSCALL_DEFINE5(listxattrat, int, dfd, const char __user *, pathname, 944 + unsigned int, at_flags, 945 + char __user *, list, size_t, size) 946 + { 947 + return path_listxattrat(dfd, pathname, at_flags, list, size); 974 948 } 975 949 976 950 SYSCALL_DEFINE3(listxattr, const char __user *, pathname, char __user *, list, 977 951 size_t, size) 978 952 { 979 - return path_listxattr(pathname, list, size, LOOKUP_FOLLOW); 953 + return path_listxattrat(AT_FDCWD, pathname, 0, list, size); 980 954 } 981 955 982 956 SYSCALL_DEFINE3(llistxattr, const char __user *, pathname, char __user *, list, 983 957 size_t, size) 984 958 { 985 - return path_listxattr(pathname, list, size, 0); 959 + return path_listxattrat(AT_FDCWD, pathname, AT_SYMLINK_NOFOLLOW, list, size); 986 960 } 987 961 988 962 SYSCALL_DEFINE3(flistxattr, int, fd, char __user *, list, size_t, size) 989 963 { 990 - CLASS(fd, f)(fd); 991 - 992 - if (fd_empty(f)) 993 - return -EBADF; 994 - return file_listxattr(fd_file(f), list, size); 964 + return path_listxattrat(fd, NULL, AT_EMPTY_PATH, list, size); 995 965 } 996 966 997 967 /* ··· 1062 996 return error; 1063 997 } 1064 998 1065 - static int path_removexattr(const char __user *pathname, 1066 - const char __user *name, unsigned int lookup_flags) 999 + static int path_removexattrat(int dfd, const char __user *pathname, 1000 + unsigned int at_flags, const char __user *name) 1067 1001 { 1068 1002 struct xattr_name kname; 1003 + struct filename *filename; 1004 + unsigned int lookup_flags; 1069 1005 int error; 1006 + 1007 + if ((at_flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0) 1008 + return -EINVAL; 1070 1009 1071 1010 error = import_xattr_name(&kname, name); 1072 1011 if (error) 1073 1012 return error; 1074 - return filename_removexattr(AT_FDCWD, getname(pathname), lookup_flags, 1075 - &kname); 1013 + 1014 + filename = getname_maybe_null(pathname, at_flags); 1015 + if (!filename) { 1016 + CLASS(fd, f)(dfd); 1017 + if (fd_empty(f)) 1018 + return -EBADF; 1019 + return file_removexattr(fd_file(f), &kname); 1020 + } 1021 + lookup_flags = (at_flags & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW; 1022 + return filename_removexattr(dfd, filename, lookup_flags, &kname); 1023 + } 1024 + 1025 + SYSCALL_DEFINE4(removexattrat, int, dfd, const char __user *, pathname, 1026 + unsigned int, at_flags, const char __user *, name) 1027 + { 1028 + return path_removexattrat(dfd, pathname, at_flags, name); 1076 1029 } 1077 1030 1078 1031 SYSCALL_DEFINE2(removexattr, const char __user *, pathname, 1079 1032 const char __user *, name) 1080 1033 { 1081 - return path_removexattr(pathname, name, LOOKUP_FOLLOW); 1034 + return path_removexattrat(AT_FDCWD, pathname, 0, name); 1082 1035 } 1083 1036 1084 1037 SYSCALL_DEFINE2(lremovexattr, const char __user *, pathname, 1085 1038 const char __user *, name) 1086 1039 { 1087 - return path_removexattr(pathname, name, 0); 1040 + return path_removexattrat(AT_FDCWD, pathname, AT_SYMLINK_NOFOLLOW, name); 1088 1041 } 1089 1042 1090 1043 SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name) 1091 1044 { 1092 - CLASS(fd, f)(fd); 1093 - struct xattr_name kname; 1094 - int error; 1095 - 1096 - if (fd_empty(f)) 1097 - return -EBADF; 1098 - 1099 - error = import_xattr_name(&kname, name); 1100 - if (error) 1101 - return error; 1102 - return file_removexattr(fd_file(f), &kname); 1045 + return path_removexattrat(fd, NULL, AT_EMPTY_PATH, name); 1103 1046 } 1104 1047 1105 1048 int xattr_list_one(char **buffer, ssize_t *remaining_size, const char *name)
+6
include/asm-generic/audit_change_attr.h
··· 11 11 __NR_fchown, 12 12 #endif 13 13 __NR_setxattr, 14 + #ifdef __NR_setxattrat 15 + __NR_setxattrat, 16 + #endif 14 17 __NR_lsetxattr, 15 18 __NR_fsetxattr, 16 19 __NR_removexattr, 20 + #ifdef __NR_removexattrat 21 + __NR_removexattrat, 22 + #endif 17 23 __NR_lremovexattr, 18 24 __NR_fremovexattr, 19 25 #ifdef __NR_fchownat
+13
include/linux/syscalls.h
··· 77 77 struct cachestat; 78 78 struct statmount; 79 79 struct mnt_id_req; 80 + struct xattr_args; 80 81 81 82 #include <linux/types.h> 82 83 #include <linux/aio_abi.h> ··· 339 338 void __user *arg, unsigned int nr_args); 340 339 asmlinkage long sys_setxattr(const char __user *path, const char __user *name, 341 340 const void __user *value, size_t size, int flags); 341 + asmlinkage long sys_setxattrat(int dfd, const char __user *path, unsigned int at_flags, 342 + const char __user *name, 343 + const struct xattr_args __user *args, size_t size); 342 344 asmlinkage long sys_lsetxattr(const char __user *path, const char __user *name, 343 345 const void __user *value, size_t size, int flags); 344 346 asmlinkage long sys_fsetxattr(int fd, const char __user *name, 345 347 const void __user *value, size_t size, int flags); 346 348 asmlinkage long sys_getxattr(const char __user *path, const char __user *name, 347 349 void __user *value, size_t size); 350 + asmlinkage long sys_getxattrat(int dfd, const char __user *path, unsigned int at_flags, 351 + const char __user *name, 352 + struct xattr_args __user *args, size_t size); 348 353 asmlinkage long sys_lgetxattr(const char __user *path, const char __user *name, 349 354 void __user *value, size_t size); 350 355 asmlinkage long sys_fgetxattr(int fd, const char __user *name, 351 356 void __user *value, size_t size); 352 357 asmlinkage long sys_listxattr(const char __user *path, char __user *list, 353 358 size_t size); 359 + asmlinkage long sys_listxattrat(int dfd, const char __user *path, 360 + unsigned int at_flags, 361 + char __user *list, size_t size); 354 362 asmlinkage long sys_llistxattr(const char __user *path, char __user *list, 355 363 size_t size); 356 364 asmlinkage long sys_flistxattr(int fd, char __user *list, size_t size); 357 365 asmlinkage long sys_removexattr(const char __user *path, 358 366 const char __user *name); 367 + asmlinkage long sys_removexattrat(int dfd, const char __user *path, 368 + unsigned int at_flags, 369 + const char __user *name); 359 370 asmlinkage long sys_lremovexattr(const char __user *path, 360 371 const char __user *name); 361 372 asmlinkage long sys_fremovexattr(int fd, const char __user *name);
+4
include/linux/xattr.h
··· 19 19 #include <linux/user_namespace.h> 20 20 #include <uapi/linux/xattr.h> 21 21 22 + /* List of all open_how "versions". */ 23 + #define XATTR_ARGS_SIZE_VER0 16 /* sizeof first published struct */ 24 + #define XATTR_ARGS_SIZE_LATEST XATTR_ARGS_SIZE_VER0 25 + 22 26 struct inode; 23 27 struct dentry; 24 28
+10 -1
include/uapi/asm-generic/unistd.h
··· 841 841 #define __NR_mseal 462 842 842 __SYSCALL(__NR_mseal, sys_mseal) 843 843 844 + #define __NR_setxattrat 463 845 + __SYSCALL(__NR_setxattrat, sys_setxattrat) 846 + #define __NR_getxattrat 464 847 + __SYSCALL(__NR_getxattrat, sys_getxattrat) 848 + #define __NR_listxattrat 465 849 + __SYSCALL(__NR_listxattrat, sys_listxattrat) 850 + #define __NR_removexattrat 466 851 + __SYSCALL(__NR_removexattrat, sys_removexattrat) 852 + 844 853 #undef __NR_syscalls 845 - #define __NR_syscalls 463 854 + #define __NR_syscalls 467 846 855 847 856 /* 848 857 * 32 bit systems traditionally used different
+7
include/uapi/linux/xattr.h
··· 11 11 */ 12 12 13 13 #include <linux/libc-compat.h> 14 + #include <linux/types.h> 14 15 15 16 #ifndef _UAPI_LINUX_XATTR_H 16 17 #define _UAPI_LINUX_XATTR_H ··· 21 20 22 21 #define XATTR_CREATE 0x1 /* set value, fail if attr already exists */ 23 22 #define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */ 23 + 24 + struct xattr_args { 25 + __aligned_u64 __user value; 26 + __u32 size; 27 + __u32 flags; 28 + }; 24 29 #endif 25 30 26 31 /* Namespaces */
+4
scripts/syscall.tbl
··· 403 403 460 common lsm_set_self_attr sys_lsm_set_self_attr 404 404 461 common lsm_list_modules sys_lsm_list_modules 405 405 462 common mseal sys_mseal 406 + 463 common setxattrat sys_setxattrat 407 + 464 common getxattrat sys_getxattrat 408 + 465 common listxattrat sys_listxattrat 409 + 466 common removexattrat sys_removexattrat