From aa1c7b592aab5e3a18b3c8a1a0c13df6bb1812c7 Mon Sep 17 00:00:00 2001 From: Alexander Miller Date: Thu, 28 Nov 2019 22:17:24 +0100 Subject: [PATCH] Use .symver asm directive to set symbol versions for legacy syscalls The linker script hack to set a symbol version such that the symbols aren't used when linking for the *xattr system calls available in glibc, introduced in commit efa0b1ea982261861d64f6d6d620af83d82b02d3, doesn't work as intended with modern linkerss. Linking with --gc-sections, LTO, ld.gold, or lld results in the code being discarded and a library with unusable symbols, e.g. 23: 00000000 0 NOTYPE GLOBAL DEFAULT ABS getxattr@ATTR_1.0 instead of 23: 000033c0 0 FUNC GLOBAL DEFAULT 11 getxattr@ATTR_1.0 Remove the linker script and set symbol versions with the .symver directive in global asm statements, which is the documented and well supported way to do it. Also remove the libattr_ prefix from the wrapper names, as it is no longer needed. Add __attribute__((no_reorder)) to the wrapper functions to avoid problems during LTO partitioning, since function definitions and their corresponding .symver directives must be emitted to the same partition to work correctly. --- libattr/Makemodule.am | 5 +--- libattr/libattr.lds | 12 --------- libattr/syscalls.c | 60 ++++++++++++++++++++++++++++++------------- 3 files changed, 43 insertions(+), 34 deletions(-) delete mode 100644 libattr/libattr.lds diff --git a/libattr/Makemodule.am b/libattr/Makemodule.am index 4b3720c..e9f5661 100644 --- a/libattr/Makemodule.am +++ b/libattr/Makemodule.am @@ -8,7 +8,7 @@ LT_CURRENT = 2 LT_AGE = 1 LTVERSION = $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) -libattr_la_DEPENDENCIES = exports libattr/libattr.lds +libattr_la_DEPENDENCIES = exports libattr_la_SOURCES = \ libattr/attr_copy_action.c \ libattr/attr_copy_check.c \ @@ -20,7 +20,4 @@ libattr_la_SOURCES = \ libattr_la_CFLAGS = -include libattr/libattr.h libattr_la_LDFLAGS = \ -Wl,--version-script,$(top_srcdir)/exports \ - -Wl,$(top_srcdir)/libattr/libattr.lds \ -version-info $(LTVERSION) - -EXTRA_DIST += libattr/libattr.lds diff --git a/libattr/libattr.lds b/libattr/libattr.lds deleted file mode 100644 index 947f15d..0000000 --- a/libattr/libattr.lds +++ /dev/null @@ -1,12 +0,0 @@ -"fgetxattr@ATTR_1.0" = libattr_fgetxattr; -"flistxattr@ATTR_1.0" = libattr_flistxattr; -"fremovexattr@ATTR_1.0" = libattr_fremovexattr; -"fsetxattr@ATTR_1.0" = libattr_fsetxattr; -"getxattr@ATTR_1.0" = libattr_getxattr; -"lgetxattr@ATTR_1.0" = libattr_lgetxattr; -"listxattr@ATTR_1.0" = libattr_listxattr; -"llistxattr@ATTR_1.0" = libattr_llistxattr; -"lremovexattr@ATTR_1.0" = libattr_lremovexattr; -"lsetxattr@ATTR_1.0" = libattr_lsetxattr; -"removexattr@ATTR_1.0" = libattr_removexattr; -"setxattr@ATTR_1.0" = libattr_setxattr; diff --git a/libattr/syscalls.c b/libattr/syscalls.c index 721ad7f..e236677 100644 --- a/libattr/syscalls.c +++ b/libattr/syscalls.c @@ -30,71 +30,95 @@ # pragma GCC visibility push(default) #endif -int libattr_setxattr(const char *path, const char *name, - void *value, size_t size, int flags) +__attribute__((no_reorder)) +int setxattr(const char *path, const char *name, + const void *value, size_t size, int flags) { return syscall(__NR_setxattr, path, name, value, size, flags); } +__asm__(".symver setxattr, setxattr@ATTR_1.0"); -int libattr_lsetxattr(const char *path, const char *name, - void *value, size_t size, int flags) +__attribute__((no_reorder)) +int lsetxattr(const char *path, const char *name, + const void *value, size_t size, int flags) { return syscall(__NR_lsetxattr, path, name, value, size, flags); } +__asm__(".symver lsetxattr, lsetxattr@ATTR_1.0"); -int libattr_fsetxattr(int filedes, const char *name, - void *value, size_t size, int flags) +__attribute__((no_reorder)) +int fsetxattr(int filedes, const char *name, + const void *value, size_t size, int flags) { return syscall(__NR_fsetxattr, filedes, name, value, size, flags); } +__asm__(".symver fsetxattr, fsetxattr@ATTR_1.0"); -ssize_t libattr_getxattr(const char *path, const char *name, - void *value, size_t size) +__attribute__((no_reorder)) +ssize_t getxattr(const char *path, const char *name, + void *value, size_t size) { return syscall(__NR_getxattr, path, name, value, size); } +__asm__(".symver getxattr, getxattr@ATTR_1.0"); -ssize_t libattr_lgetxattr(const char *path, const char *name, - void *value, size_t size) +__attribute__((no_reorder)) +ssize_t lgetxattr(const char *path, const char *name, + void *value, size_t size) { return syscall(__NR_lgetxattr, path, name, value, size); } +__asm__(".symver lgetxattr, lgetxattr@ATTR_1.0"); -ssize_t libattr_fgetxattr(int filedes, const char *name, - void *value, size_t size) +__attribute__((no_reorder)) +ssize_t fgetxattr(int filedes, const char *name, + void *value, size_t size) { return syscall(__NR_fgetxattr, filedes, name, value, size); } +__asm__(".symver fgetxattr, fgetxattr@ATTR_1.0"); -ssize_t libattr_listxattr(const char *path, char *list, size_t size) +__attribute__((no_reorder)) +ssize_t listxattr(const char *path, char *list, size_t size) { return syscall(__NR_listxattr, path, list, size); } +__asm__(".symver listxattr, listxattr@ATTR_1.0"); -ssize_t libattr_llistxattr(const char *path, char *list, size_t size) +__attribute__((no_reorder)) +ssize_t llistxattr(const char *path, char *list, size_t size) { return syscall(__NR_llistxattr, path, list, size); } +__asm__(".symver llistxattr, llistxattr@ATTR_1.0"); -ssize_t libattr_flistxattr(int filedes, char *list, size_t size) +__attribute__((no_reorder)) +ssize_t flistxattr(int filedes, char *list, size_t size) { return syscall(__NR_flistxattr, filedes, list, size); } +__asm__(".symver flistxattr, flistxattr@ATTR_1.0"); -int libattr_removexattr(const char *path, const char *name) +__attribute__((no_reorder)) +int removexattr(const char *path, const char *name) { return syscall(__NR_removexattr, path, name); } +__asm__(".symver removexattr, removexattr@ATTR_1.0"); -int libattr_lremovexattr(const char *path, const char *name) +__attribute__((no_reorder)) +int lremovexattr(const char *path, const char *name) { return syscall(__NR_lremovexattr, path, name); } +__asm__(".symver lremovexattr, lremovexattr@ATTR_1.0"); -int libattr_fremovexattr(int filedes, const char *name) +__attribute__((no_reorder)) +int fremovexattr(int filedes, const char *name) { return syscall(__NR_fremovexattr, filedes, name); } +__asm__(".symver fremovexattr, fremovexattr@ATTR_1.0"); #ifdef HAVE_VISIBILITY_ATTRIBUTE # pragma GCC visibility pop -- 2.23.0 Bug: https://bugs.gentoo.org/644048 Bug: https://bugs.gentoo.org/700116