]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Do not stack-protect ifunc resolvers [BZ #7065]
authorNick Alcock <nick.alcock@oracle.com>
Mon, 26 Dec 2016 09:08:41 +0000 (10:08 +0100)
committerFlorian Weimer <fweimer@redhat.com>
Mon, 26 Dec 2016 09:08:41 +0000 (10:08 +0100)
When dynamically linking, ifunc resolvers are called before TLS is
initialized, so they cannot be safely stack-protected.

We avoid disabling stack-protection on large numbers of files by
using __attribute__ ((__optimize__ ("-fno-stack-protector")))
to turn it off just for the resolvers themselves.  (We provide
the attribute even when statically linking, because we will later
use it elsewhere too.)

16 files changed:
ChangeLog
config.h.in
configure
configure.ac
elf/ifuncdep2.c
elf/ifuncmain6pie.c
elf/ifuncmain7.c
elf/ifuncmod1.c
elf/ifuncmod5.c
include/libc-symbols.h
sysdeps/generic/ifunc-sel.h
sysdeps/nacl/nacl_interface_query.c
sysdeps/powerpc/ifunc-sel.h
sysdeps/unix/make-syscalls.sh
sysdeps/unix/sysv/linux/x86_64/x32/getcpu.c
sysdeps/x86_64/ifuncmod8.c

index f17669931ba7ff0d4431f5976ddddabe19482968..395a14ba4d8be8894002b4987b4c02e76adcaa28 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2016-12-26  Nick Alcock  <nick.alcock@oracle.com>
+
+       [BZ #7065]
+       * configure.ac (HAVE_CC_NO_STACK_PROTECTOR): Define.
+       * config.h.in (HAVE_CC_NO_STACK_PROTECTOR): New macro.
+       * include/libc-symbols.h (inhibit_stack_protector): New macro.
+       (__ifunc_resolver): Use it.
+       * elf/ifuncdep2.c (foo1_ifunc, foo2_ifunc, foo3_ifunc): Apply
+       inhibit_stack_protector.
+       * elf/ifuncmain6pie.c (foo_ifunc): Likewise.
+       * elf/ifuncmain7.c (foo_ifunc): Likewise.
+       * elf/ifuncmod1.c (foo_ifunc, foo_hidden_ifunc)
+       (foo_protected_ifunc): Likewise.
+       * elf/ifuncmod5.c (foo_ifunc, foo_hidden_ifunc)
+       (foo_protected_ifunc): Likewise.
+       * sysdeps/generic/ifunc-sel.h (ifunc_sel, ifunc_one): Likewise.
+       * sysdeps/nacl/nacl_interface_query.c
+       (nacl_interface_query_ifunc): Likewise.
+       * sysdeps/powerpc/ifunc-sel.h (ifunc_sel, ifunc_one): Likewise.
+       * sysdeps/unix/sysv/linux/x86_64/x32/getcpu.c (getcpu_ifunc):
+       Likewise.
+       * sysdeps/x86_64/ifuncmod8.c (foo_ifunc): Likewise.
+       * sysdeps/unix/make-syscalls.sh: Apply inhibit_stack_protector to
+       the generated vDSO syscall resolver.
+
 2016-12-26  Nick Alcock  <nick.alcock@oracle.com>
            Florian Weimer  <fweimer@redhat.com>
 
index d96ce0f8cf366500d1f7db8b56794ea47f003570..82f95a6dbd0fe5ec3c9b0762a34cd56bc4385816 100644 (file)
 /* Define if compiler accepts -ftree-loop-distribute-patterns.  */
 #undef  HAVE_CC_INHIBIT_LOOP_TO_LIBCALL
 
+/* Define if compiler accepts -fno-stack-protector in an
+   __attribute__ ((__optimize__)).  */
+#undef HAVE_CC_NO_STACK_PROTECTOR
+
 /* The level of stack protection in use for glibc as a whole.
    May be overridden on a file-by-file basis.  */
 #ifndef STACK_PROTECTOR_LEVEL
index 8c69f09232ac062580a6609cb8a86182b203c480..b3007953ea199adc0cee77ade363c464df70cda7 100755 (executable)
--- a/configure
+++ b/configure
@@ -3994,6 +3994,8 @@ stack_protector=
 no_stack_protector=
 if test "$libc_cv_ssp" = yes; then
   no_stack_protector="-fno-stack-protector -DSTACK_PROTECTOR_LEVEL=0"
+  $as_echo "#define HAVE_CC_NO_STACK_PROTECTOR 1" >>confdefs.h
+
 fi
 
 if test "$enable_stack_protector" = yes && test "$libc_cv_ssp" = yes; then
index c1597689849c30f9654f08f85b58dd2e5721a4ae..f5fa1aaefa8e45e1cc077a0836a4c536d5b10790 100644 (file)
@@ -653,6 +653,7 @@ stack_protector=
 no_stack_protector=
 if test "$libc_cv_ssp" = yes; then
   no_stack_protector="-fno-stack-protector -DSTACK_PROTECTOR_LEVEL=0"
+  AC_DEFINE(HAVE_CC_NO_STACK_PROTECTOR)
 fi
 
 if test "$enable_stack_protector" = yes && test "$libc_cv_ssp" = yes; then
index 6e66d318a6a036bb772244819ce9c47c79d70da1..d87d61d5be6f4bc29863f1ae599727b6eb27dc3f 100644 (file)
@@ -32,6 +32,7 @@ void * foo1_ifunc (void) __asm__ ("foo1");
 __asm__(".type foo1, %gnu_indirect_function");
 
 void *
+inhibit_stack_protector
 foo1_ifunc (void)
 {
   return ifunc_sel (one, minus_one, zero);
@@ -41,6 +42,7 @@ void * foo2_ifunc (void) __asm__ ("foo2");
 __asm__(".type foo2, %gnu_indirect_function");
 
 void *
+inhibit_stack_protector
 foo2_ifunc (void)
 {
   return ifunc_sel (minus_one, one, zero);
@@ -50,6 +52,7 @@ void * foo3_ifunc (void) __asm__ ("foo3");
 __asm__(".type foo3, %gnu_indirect_function");
 
 void *
+inhibit_stack_protector
 foo3_ifunc (void)
 {
   return ifunc_sel (one, zero, minus_one);
index 8478d4c408d16c1dc107245e1040217d02d85ae2..04faeb86ef999019f42fa1843d52edaecd9ca00d 100644 (file)
@@ -21,6 +21,7 @@ void * foo_ifunc (void) __asm__ ("foo");
 __asm__(".type foo, %gnu_indirect_function");
 
 void *
+inhibit_stack_protector
 foo_ifunc (void)
 {
   return ifunc_one (one);
index 617a596d5e8c92c28a5e3fcc82a99eebf5bd4d58..1e8f7ea38ef94c0703d5177af30a56966371609d 100644 (file)
@@ -20,6 +20,7 @@ __asm__(".type foo, %gnu_indirect_function");
 
 static void *
 __attribute__ ((used))
+inhibit_stack_protector
 foo_ifunc (void)
 {
   return ifunc_one (one);
index 0b6138056daf7c7dfed2f455cc0845197100a995..f0bf5fb45ffdeaa7682354453a233aa099d8817e 100644 (file)
@@ -36,6 +36,7 @@ void * foo_ifunc (void) __asm__ ("foo");
 __asm__(".type foo, %gnu_indirect_function");
 
 void *
+inhibit_stack_protector
 foo_ifunc (void)
 {
   return ifunc_sel (one, minus_one, zero);
@@ -45,6 +46,7 @@ void * foo_hidden_ifunc (void) __asm__ ("foo_hidden");
 __asm__(".type foo_hidden, %gnu_indirect_function");
 
 void *
+inhibit_stack_protector
 foo_hidden_ifunc (void)
 {
   return ifunc_sel (minus_one, one, zero);
@@ -54,6 +56,7 @@ void * foo_protected_ifunc (void) __asm__ ("foo_protected");
 __asm__(".type foo_protected, %gnu_indirect_function");
 
 void *
+inhibit_stack_protector
 foo_protected_ifunc (void)
 {
   return ifunc_sel (one, zero, minus_one);
index 0e65a63691f2e65e7fd0b1897e14c72c1b89605d..5a957800e84b1acce6f62b752c621e877885c02f 100644 (file)
@@ -31,6 +31,7 @@ void * foo_ifunc (void) __asm__ ("foo");
 __asm__(".type foo, %gnu_indirect_function");
 
 void *
+inhibit_stack_protector
 foo_ifunc (void)
 {
   return ifunc_sel (one, minus_one, zero);
@@ -40,6 +41,7 @@ void * foo_hidden_ifunc (void) __asm__ ("foo_hidden");
 __asm__(".type foo_hidden, %gnu_indirect_function");
 
 void *
+inhibit_stack_protector
 foo_hidden_ifunc (void)
 {
   return ifunc_sel (minus_one, one, zero);
@@ -49,6 +51,7 @@ void * foo_protected_ifunc (void) __asm__ ("foo_protected");
 __asm__(".type foo_protected, %gnu_indirect_function");
 
 void *
+inhibit_stack_protector
 foo_protected_ifunc (void)
 {
   return ifunc_sel (one, zero, minus_one);
index 4238d7930b7e2c40629318d6380ea14c97205a30..d981e673434d12869d75efa237aaa6ef91d2a989 100644 (file)
@@ -336,6 +336,16 @@ for linking")
 
 #define attribute_relro __attribute__ ((section (".data.rel.ro")))
 
+
+/* Used to disable stack protection in sensitive places, like ifunc
+   resolvers and early static TLS init.  */
+#ifdef HAVE_CC_NO_STACK_PROTECTOR
+# define inhibit_stack_protector \
+    __attribute__ ((__optimize__ ("-fno-stack-protector")))
+#else
+# define inhibit_stack_protector
+#endif
+
 /* The following macros are used for PLT bypassing within libc.so
    (and if needed other libraries similarly).
    First of all, you need to have the function prototyped somewhere,
@@ -737,7 +747,7 @@ for linking")
 
 /* Helper / base  macros for indirect function symbols.  */
 #define __ifunc_resolver(type_name, name, expr, arg, init, classifier) \
-  classifier void *name##_ifunc (arg)                                  \
+  classifier inhibit_stack_protector void *name##_ifunc (arg)                                  \
   {                                                                    \
     init ();                                                           \
     __typeof (type_name) *res = expr;                                  \
index 6a27b69c5babaefab1c778f6d541ff8d14938d4a..1fff4059ccb05bf181672f7cbb3c9b32bb2f096d 100644 (file)
@@ -5,6 +5,7 @@
 extern int global;
 
 static inline void *
+inhibit_stack_protector
 ifunc_sel (int (*f1) (void), int (*f2) (void), int (*f3) (void))
 {
  switch (global)
@@ -19,6 +20,7 @@ ifunc_sel (int (*f1) (void), int (*f2) (void), int (*f3) (void))
 }
 
 static inline void *
+inhibit_stack_protector
 ifunc_one (int (*f1) (void))
 {
   return f1;
index adf1dd4c02a9f446b3b2b33228c696a46c7d96eb..dbaa88b037afec5d15caa171a31c21a3e0bacd0f 100644 (file)
@@ -29,6 +29,7 @@ extern TYPE_nacl_irt_query nacl_interface_query_ifunc (void)
   asm ("nacl_interface_query");
 
 TYPE_nacl_irt_query
+inhibit_stack_protector
 nacl_interface_query_ifunc (void)
 {
   return &__nacl_irt_query;
index ac589bd3c049b7ceed766c9c1697a0d0c2b8e81b..bdb00bf2c6ab4a0514bbede8bfb9deef27f02907 100644 (file)
@@ -5,6 +5,7 @@
 extern int global;
 
 static inline void *
+inhibit_stack_protector
 ifunc_sel (int (*f1) (void), int (*f2) (void), int (*f3) (void))
 {
   register void *ret __asm__ ("r3");
@@ -32,6 +33,7 @@ ifunc_sel (int (*f1) (void), int (*f2) (void), int (*f3) (void))
 }
 
 static inline void *
+inhibit_stack_protector
 ifunc_one (int (*f1) (void))
 {
   register void *ret __asm__ ("r3");
index 58d165e0156295374e5a2b3fa0f9fe96c4d4b6ba..123553c1d900a86374284e6d9fc0bc158ab1907e 100644 (file)
@@ -287,6 +287,7 @@ while read file srcfile caller syscall args strong weak; do
        (echo '#include <dl-vdso.h>'; \\
         echo 'extern void *${strong}_ifunc (void) __asm ("${strong}");'; \\
         echo 'void *'; \\
+        echo 'inhibit_stack_protector'; \\
         echo '${strong}_ifunc (void)'; \\
         echo '{'; \\
         echo '  PREPARE_VERSION_KNOWN (symver, ${vdso_symver});'; \\
index cbac4b3273720e4438578d369d0c7fb7cecd1b29..8436f9db932de0723ca4802e0fbd9facccbc3a70 100644 (file)
@@ -21,6 +21,7 @@
 void *getcpu_ifunc (void) __asm__ ("__getcpu");
 
 void *
+inhibit_stack_protector
 getcpu_ifunc (void)
 {
   PREPARE_VERSION (linux26, "LINUX_2.6", 61765110);
index c00436799c88464482205cbf28e3ad3b3241e714..7c065622be8c8190b880377fc281ee65f92beb10 100644 (file)
@@ -28,6 +28,7 @@ foo_impl (float x)
 }
 
 void *
+inhibit_stack_protector
 foo_ifunc (void)
 {
   __m128i xmm = _mm_set1_epi32 (-1);