aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Alcock <nick.alcock@oracle.com>2016-12-26 10:08:41 +0100
committerFlorian Weimer <fweimer@redhat.com>2016-12-26 10:08:41 +0100
commitde6591238b478bc86b8cf5af01a484114e399213 (patch)
tree2717c115fbc7518fcbe9348239ff536eb914d267
parent003a27e8195470f470f4d9384ca70d4e9fc8bd1b (diff)
downloadglibc-de6591238b478bc86b8cf5af01a484114e399213.tar
glibc-de6591238b478bc86b8cf5af01a484114e399213.tar.gz
glibc-de6591238b478bc86b8cf5af01a484114e399213.tar.bz2
glibc-de6591238b478bc86b8cf5af01a484114e399213.zip
Do not stack-protect ifunc resolvers [BZ #7065]
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.)
-rw-r--r--ChangeLog25
-rw-r--r--config.h.in4
-rwxr-xr-xconfigure2
-rw-r--r--configure.ac1
-rw-r--r--elf/ifuncdep2.c3
-rw-r--r--elf/ifuncmain6pie.c1
-rw-r--r--elf/ifuncmain7.c1
-rw-r--r--elf/ifuncmod1.c3
-rw-r--r--elf/ifuncmod5.c3
-rw-r--r--include/libc-symbols.h12
-rw-r--r--sysdeps/generic/ifunc-sel.h2
-rw-r--r--sysdeps/nacl/nacl_interface_query.c1
-rw-r--r--sysdeps/powerpc/ifunc-sel.h2
-rw-r--r--sysdeps/unix/make-syscalls.sh1
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/x32/getcpu.c1
-rw-r--r--sysdeps/x86_64/ifuncmod8.c1
16 files changed, 62 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index f17669931b..395a14ba4d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,29 @@
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>
[BZ #7065]
diff --git a/config.h.in b/config.h.in
index d96ce0f8cf..82f95a6dbd 100644
--- a/config.h.in
+++ b/config.h.in
@@ -48,6 +48,10 @@
/* 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
diff --git a/configure b/configure
index 8c69f09232..b3007953ea 100755
--- 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
diff --git a/configure.ac b/configure.ac
index c159768984..f5fa1aaefa 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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
diff --git a/elf/ifuncdep2.c b/elf/ifuncdep2.c
index 6e66d318a6..d87d61d5be 100644
--- a/elf/ifuncdep2.c
+++ b/elf/ifuncdep2.c
@@ -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);
diff --git a/elf/ifuncmain6pie.c b/elf/ifuncmain6pie.c
index 8478d4c408..04faeb86ef 100644
--- a/elf/ifuncmain6pie.c
+++ b/elf/ifuncmain6pie.c
@@ -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);
diff --git a/elf/ifuncmain7.c b/elf/ifuncmain7.c
index 617a596d5e..1e8f7ea38e 100644
--- a/elf/ifuncmain7.c
+++ b/elf/ifuncmain7.c
@@ -20,6 +20,7 @@ __asm__(".type foo, %gnu_indirect_function");
static void *
__attribute__ ((used))
+inhibit_stack_protector
foo_ifunc (void)
{
return ifunc_one (one);
diff --git a/elf/ifuncmod1.c b/elf/ifuncmod1.c
index 0b6138056d..f0bf5fb45f 100644
--- a/elf/ifuncmod1.c
+++ b/elf/ifuncmod1.c
@@ -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);
diff --git a/elf/ifuncmod5.c b/elf/ifuncmod5.c
index 0e65a63691..5a957800e8 100644
--- a/elf/ifuncmod5.c
+++ b/elf/ifuncmod5.c
@@ -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);
diff --git a/include/libc-symbols.h b/include/libc-symbols.h
index 4238d7930b..d981e67343 100644
--- a/include/libc-symbols.h
+++ b/include/libc-symbols.h
@@ -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; \
diff --git a/sysdeps/generic/ifunc-sel.h b/sysdeps/generic/ifunc-sel.h
index 6a27b69c5b..1fff4059cc 100644
--- a/sysdeps/generic/ifunc-sel.h
+++ b/sysdeps/generic/ifunc-sel.h
@@ -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;
diff --git a/sysdeps/nacl/nacl_interface_query.c b/sysdeps/nacl/nacl_interface_query.c
index adf1dd4c02..dbaa88b037 100644
--- a/sysdeps/nacl/nacl_interface_query.c
+++ b/sysdeps/nacl/nacl_interface_query.c
@@ -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;
diff --git a/sysdeps/powerpc/ifunc-sel.h b/sysdeps/powerpc/ifunc-sel.h
index ac589bd3c0..bdb00bf2c6 100644
--- a/sysdeps/powerpc/ifunc-sel.h
+++ b/sysdeps/powerpc/ifunc-sel.h
@@ -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");
diff --git a/sysdeps/unix/make-syscalls.sh b/sysdeps/unix/make-syscalls.sh
index 58d165e015..123553c1d9 100644
--- a/sysdeps/unix/make-syscalls.sh
+++ b/sysdeps/unix/make-syscalls.sh
@@ -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});'; \\
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/getcpu.c b/sysdeps/unix/sysv/linux/x86_64/x32/getcpu.c
index cbac4b3273..8436f9db93 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/getcpu.c
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/getcpu.c
@@ -21,6 +21,7 @@
void *getcpu_ifunc (void) __asm__ ("__getcpu");
void *
+inhibit_stack_protector
getcpu_ifunc (void)
{
PREPARE_VERSION (linux26, "LINUX_2.6", 61765110);
diff --git a/sysdeps/x86_64/ifuncmod8.c b/sysdeps/x86_64/ifuncmod8.c
index c00436799c..7c065622be 100644
--- a/sysdeps/x86_64/ifuncmod8.c
+++ b/sysdeps/x86_64/ifuncmod8.c
@@ -28,6 +28,7 @@ foo_impl (float x)
}
void *
+inhibit_stack_protector
foo_ifunc (void)
{
__m128i xmm = _mm_set1_epi32 (-1);