Message ID | 1457445064-7107-4-git-send-email-nix@esperi.org.uk |
---|---|
State | New |
Headers | show |
On 08 Mar 2016 13:50, Nix wrote: > +AC_CACHE_CHECK(if $CC accepts -fno-stack-protector with \ > +__attribute__ ((__optimize__)), m4 strings should be quoted. so this should be: AC_CACHE_CHECK([if $CC ........], ... -mike
On 08 Mar 2016 13:50, Nix wrote: > +AC_CACHE_CHECK(if $CC accepts -fno-stack-protector with \ > +__attribute__ ((__optimize__)), libc_cv_cc_no_stack_protector, [dnl > +cat > conftest.c <<EOF > +void > +__attribute__ ((__optimize__ ("-fno-stack-protector"))) > +foo (void) {} > +EOF actually, which versions of gcc *don't* support this ? if it's in gcc-4.7 and newer, then we don't need this test as we require that already. -mike
On 9 Mar 2016, Mike Frysinger outgrape: > On 08 Mar 2016 13:50, Nix wrote: >> +AC_CACHE_CHECK(if $CC accepts -fno-stack-protector with \ >> +__attribute__ ((__optimize__)), > > m4 strings should be quoted. so this should be: > AC_CACHE_CHECK([if $CC ........], ... I copied it from the similarly unquoted AC_CACHE_CHECK(if $CC accepts -fno-tree-loop-distribute-patterns with \ __attribute__ ((__optimize__)), libc_cv_cc_loop_to_function, [dnl cat > conftest.c <<EOF and didn't quote it out of unreasoning fear that \-escaping might get broken if I did that. I didn't actually *test* it, or I'd have seen that my fears were groundless. Fixed (at least, fixed my copy: I think the other one is for another time).
On 9 Mar 2016, Mike Frysinger told this: > On 08 Mar 2016 13:50, Nix wrote: >> +AC_CACHE_CHECK(if $CC accepts -fno-stack-protector with \ >> +__attribute__ ((__optimize__)), libc_cv_cc_no_stack_protector, [dnl >> +cat > conftest.c <<EOF >> +void >> +__attribute__ ((__optimize__ ("-fno-stack-protector"))) >> +foo (void) {} >> +EOF > > actually, which versions of gcc *don't* support this ? if it's in gcc-4.7 > and newer, then we don't need this test as we require that already. Good question. The worrying thing is that support for __attribute__((__optimize__)) may not be enough: IIRC, that attribute was not exactly perfectly functional in the first release or two after it landed, IIRC. Let's see... ... GCC 4.4?! OK, way older than I remembered. We can definitely drop this: there have been fixes to fix things like target-specific options with __attribute__((__optimize__)) right up until recently, but nothing that would perturb -fno-stack-protector (and nothing at *all* between 4.6.x and 4.8.x, and I know 4.8.x works). So I'll drop this bit. (Technically this makes libc_cv_ssp useless too, because -fstack-protector is *much* older than __attribute__((__optimize__)), but it's consistent with the checks for -fstack-protector-strong and -all to have it there, and those are much newer and still not consistently supported on all targets. I can tear libc_cv_ssp and have_ssp out as well if you think it worth doing.)
On Wed, 9 Mar 2016, Mike Frysinger wrote: > On 08 Mar 2016 13:50, Nix wrote: > > +AC_CACHE_CHECK(if $CC accepts -fno-stack-protector with \ > > +__attribute__ ((__optimize__)), > > m4 strings should be quoted. so this should be: > AC_CACHE_CHECK([if $CC ........], ... It would certainly be nice if someone cleaned up the existing *.ac scripts and fragments to consistently follow this rule (for each autoconf macro, there should generally be exactly one level of [] quoting around each of its arguments, except in special cases such as where the Autoconf manual explains that AC_LANG_SOURCE's argument should be double-quoted [[]]).
On 09 Mar 2016 23:48, Nix wrote: > On 9 Mar 2016, Mike Frysinger told this: > > On 08 Mar 2016 13:50, Nix wrote: > >> +AC_CACHE_CHECK(if $CC accepts -fno-stack-protector with \ > >> +__attribute__ ((__optimize__)), libc_cv_cc_no_stack_protector, [dnl > >> +cat > conftest.c <<EOF > >> +void > >> +__attribute__ ((__optimize__ ("-fno-stack-protector"))) > >> +foo (void) {} > >> +EOF > > > > actually, which versions of gcc *don't* support this ? if it's in gcc-4.7 > > and newer, then we don't need this test as we require that already. > > Good question. The worrying thing is that support for > __attribute__((__optimize__)) may not be enough: IIRC, that attribute > was not exactly perfectly functional in the first release or two after > it landed, IIRC. > > Let's see... > > ... GCC 4.4?! OK, way older than I remembered. We can definitely drop > this: there have been fixes to fix things like target-specific options > with __attribute__((__optimize__)) right up until recently, but nothing > that would perturb -fno-stack-protector (and nothing at *all* between > 4.6.x and 4.8.x, and I know 4.8.x works). > > So I'll drop this bit. > > (Technically this makes libc_cv_ssp useless too, because > -fstack-protector is *much* older than __attribute__((__optimize__)), > but it's consistent with the checks for -fstack-protector-strong and > -all to have it there, and those are much newer and still not > consistently supported on all targets. I can tear libc_cv_ssp and > have_ssp out as well if you think it worth doing.) checking for the flag itself we prob want to keep because not all targets support SSP -mike
diff --git a/config.h.in b/config.h.in index ec9c8bc..7bbc148 100644 --- a/config.h.in +++ b/config.h.in @@ -43,6 +43,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 + /* Define if the regparm attribute shall be used for local functions (gcc on ix86 only). */ #undef USE_REGPARMS diff --git a/configure.ac b/configure.ac index 7b81049..a920f89 100644 --- a/configure.ac +++ b/configure.ac @@ -632,10 +632,25 @@ LIBC_TRY_CC_OPTION([$CFLAGS $CPPFLAGS -Werror -fstack-protector-all], [libc_cv_ssp_all=no]) ]) +AC_CACHE_CHECK(if $CC accepts -fno-stack-protector with \ +__attribute__ ((__optimize__)), libc_cv_cc_no_stack_protector, [dnl +cat > conftest.c <<EOF +void +__attribute__ ((__optimize__ ("-fno-stack-protector"))) +foo (void) {} +EOF +libc_cv_cc_no_stack_protector=no +if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS -c conftest.c]) +then + libc_cv_cc_no_stack_protector=yes +fi +rm -f conftest*]) + stack_protector= no_stack_protector= if test x$libc_cv_ssp = xyes; then no_stack_protector=-fno-stack-protector + AC_DEFINE(HAVE_CC_NO_STACK_PROTECTOR) fi if test x$enable_stack_protector = xyes && test $libc_cv_ssp = yes; then diff --git a/elf/ifuncdep2.c b/elf/ifuncdep2.c index 6e66d31..d87d61d 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 8478d4c..04faeb8 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 617a596..1e8f7ea 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 0b61380..f0bf5fb 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 0e65a63..5a95780 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 4548e09..531092c 100644 --- a/include/libc-symbols.h +++ b/include/libc-symbols.h @@ -314,6 +314,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, @@ -716,7 +726,9 @@ for linking") /* Marker used for indirection function symbols. */ #define libc_ifunc(name, expr) \ extern void *name##_ifunc (void) __asm__ (#name); \ - void *name##_ifunc (void) \ + void * \ + inhibit_stack_protector \ + name##_ifunc (void) \ { \ INIT_ARCH (); \ __typeof (name) *res = expr; \ @@ -728,7 +740,9 @@ for linking") which will, if necessary, initialize the data first. */ #define libm_ifunc(name, expr) \ extern void *name##_ifunc (void) __asm__ (#name); \ - void *name##_ifunc (void) \ + void * \ + inhibit_stack_protector \ + name##_ifunc (void) \ { \ __typeof (name) *res = expr; \ return res; \ diff --git a/nptl/pt-fork.c b/nptl/pt-fork.c index b65d6b4..4178af8 100644 --- a/nptl/pt-fork.c +++ b/nptl/pt-fork.c @@ -34,6 +34,7 @@ static __typeof (fork) * __attribute__ ((used)) +inhibit_stack_protector fork_resolve (void) { return &__libc_fork; diff --git a/nptl/pt-longjmp.c b/nptl/pt-longjmp.c index a1cc286..8a33cb4 100644 --- a/nptl/pt-longjmp.c +++ b/nptl/pt-longjmp.c @@ -34,6 +34,7 @@ static __typeof (longjmp) * __attribute__ ((used)) +inhibit_stack_protector longjmp_resolve (void) { return &__libc_longjmp; diff --git a/nptl/pt-system.c b/nptl/pt-system.c index 56f2a89..a481ab3 100644 --- a/nptl/pt-system.c +++ b/nptl/pt-system.c @@ -34,6 +34,7 @@ static __typeof (system) * __attribute__ ((used)) +inhibit_stack_protector system_resolve (void) { return &__libc_system; diff --git a/nptl/pt-vfork.c b/nptl/pt-vfork.c index 8f4be0c..8f3c2c0 100644 --- a/nptl/pt-vfork.c +++ b/nptl/pt-vfork.c @@ -48,6 +48,7 @@ extern __typeof (vfork) __libc_vfork; /* Defined in libc. */ static __typeof (vfork) * __attribute__ ((used)) +inhibit_stack_protector vfork_resolve (void) { return &__libc_vfork; diff --git a/rt/clock-compat.c b/rt/clock-compat.c index dc69e4a..b0fdd8b 100644 --- a/rt/clock-compat.c +++ b/rt/clock-compat.c @@ -30,7 +30,9 @@ #if HAVE_IFUNC # define COMPAT_REDIRECT(name, proto, arglist) \ __typeof (name) *name##_ifunc (void) asm (#name); \ - __typeof (name) *name##_ifunc (void) \ + __typeof (name) * \ + inhibit_stack_protector \ + name##_ifunc (void) \ { \ return &__##name; \ } \ diff --git a/sysdeps/generic/ifunc-sel.h b/sysdeps/generic/ifunc-sel.h index 6a27b69..1fff405 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 adf1dd4..dbaa88b 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 526d8ed..598b125 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"); @@ -30,6 +31,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 58d165e..123553c 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/powerpc/gettimeofday.c b/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c index 25a4e7c..a8b6cfa 100644 --- a/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c +++ b/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c @@ -33,6 +33,7 @@ __gettimeofday_syscall (struct timeval *tv, struct timezone *tz) } void * +inhibit_stack_protector gettimeofday_ifunc (void) { PREPARE_VERSION (linux2615, "LINUX_2.6.15", 123718565); diff --git a/sysdeps/unix/sysv/linux/powerpc/time.c b/sysdeps/unix/sysv/linux/powerpc/time.c index 7973419..4b89b38 100644 --- a/sysdeps/unix/sysv/linux/powerpc/time.c +++ b/sysdeps/unix/sysv/linux/powerpc/time.c @@ -43,6 +43,7 @@ time_syscall (time_t *t) } void * +inhibit_stack_protector time_ifunc (void) { PREPARE_VERSION (linux2615, "LINUX_2.6.15", 123718565); diff --git a/sysdeps/unix/sysv/linux/x86/gettimeofday.c b/sysdeps/unix/sysv/linux/x86/gettimeofday.c index 36f7c26..e05ad53 100644 --- a/sysdeps/unix/sysv/linux/x86/gettimeofday.c +++ b/sysdeps/unix/sysv/linux/x86/gettimeofday.c @@ -32,6 +32,7 @@ __gettimeofday_syscall (struct timeval *tv, struct timezone *tz) void *gettimeofday_ifunc (void) __asm__ ("__gettimeofday"); void * +inhibit_stack_protector gettimeofday_ifunc (void) { PREPARE_VERSION_KNOWN (linux26, LINUX_2_6); diff --git a/sysdeps/unix/sysv/linux/x86/time.c b/sysdeps/unix/sysv/linux/x86/time.c index f5f7f91..c5bd8dc 100644 --- a/sysdeps/unix/sysv/linux/x86/time.c +++ b/sysdeps/unix/sysv/linux/x86/time.c @@ -33,6 +33,7 @@ __time_syscall (time_t *t) void *time_ifunc (void) __asm__ ("time"); void * +inhibit_stack_protector time_ifunc (void) { PREPARE_VERSION_KNOWN (linux26, LINUX_2_6); diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/getcpu.c b/sysdeps/unix/sysv/linux/x86_64/x32/getcpu.c index cbac4b3..8436f9d 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 c004367..7c06562 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);
From: Nick Alcock <nick.alcock@oracle.com> 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 depending on the availability of __attribute__ ((__optimize__ ("-fno-stack-protector"))), and turning it off just for the resolvers themselves. (We provide the attribute even when statically linking, because we will later use it elsewhere too.) v4: New. v5: Comment fix. * config.h.in (HAVE_CC_NO_STACK_PROTECTOR): New macro. * configure.ac (libc_cv_cc_no_stack_protector): Check if compiler accepts __attribute__ ((__optimize__ ("-fno-stack-protector"))). * include/libc-symbols.h (inhibit_stack_protector): New macro. (libc_ifunc): Use it. (libm_ifunc): Likewise. * elf/ifuncdep2.c (foo1_ifunc): Add inhibit_stack_protector. (foo2_ifunc): Likewise. (foo3_ifunc): Likewise. * elf/ifuncmain6pie.c (foo_ifunc): Likewise. * elf/ifuncmain7.c (foo_ifunc): Likewise. * elf/ifuncmod1.c (foo_ifunc): Likewise. (foo_hidden_ifunc): Likewise. (foo_protected_ifunc): Likewise. * elf/ifuncmod5.c (foo_ifunc): Likewise. (foo_hidden_ifunc): Likewise. (foo_protected_ifunc): Likewise. * sysdeps/x86_64/ifuncmod8.c (foo_ifunc): Likewise. * nptl/pt-fork.c (fork_resolve): Likewise. * nptl/pt-longjmp.c (longjmp_resolve): Likewise. * nptl/pt-system.c (system_resolve): Likewise. * nptl/pt-vfork.c (vfork_resolve): Likewise. * rt/clock-compat.c [HAVE_IFUNC] (COMPAT_REDIRECT): Likewise. * sysdeps/generic/ifunc-sel.h (ifunc_sel): Likewise. (ifunc_one): Likewise. * sysdeps/nacl/nacl_interface_query.c [SHARED] (nacl_interface_query_ifunc): Likewise. * sysdeps/powerpc/ifunc-sel.h (ifunc_sel): Likewise. (ifunc_one): Likewise. * sysdeps/unix/make-syscalls.sh: Likewise. * sysdeps/unix/sysv/linux/powerpc/gettimeofday.c (gettimeofday_ifunc): Likewise. * sysdeps/unix/sysv/linux/powerpc/time.c (time_ifunc): Likewise. * sysdeps/unix/sysv/linux/x86/gettimeofday.c (gettimeofday_ifunc): Likewise. * sysdeps/unix/sysv/linux/x86/time.c (time_ifunc): Likewise. * sysdeps/unix/sysv/linux/x86_64/x32/getcpu.c (getcpu_ifunc): Likewise. --- config.h.in | 4 ++++ configure.ac | 15 +++++++++++++++ elf/ifuncdep2.c | 3 +++ elf/ifuncmain6pie.c | 1 + elf/ifuncmain7.c | 1 + elf/ifuncmod1.c | 3 +++ elf/ifuncmod5.c | 3 +++ include/libc-symbols.h | 18 ++++++++++++++++-- nptl/pt-fork.c | 1 + nptl/pt-longjmp.c | 1 + nptl/pt-system.c | 1 + nptl/pt-vfork.c | 1 + rt/clock-compat.c | 4 +++- sysdeps/generic/ifunc-sel.h | 2 ++ sysdeps/nacl/nacl_interface_query.c | 1 + sysdeps/powerpc/ifunc-sel.h | 2 ++ sysdeps/unix/make-syscalls.sh | 1 + sysdeps/unix/sysv/linux/powerpc/gettimeofday.c | 1 + sysdeps/unix/sysv/linux/powerpc/time.c | 1 + sysdeps/unix/sysv/linux/x86/gettimeofday.c | 1 + sysdeps/unix/sysv/linux/x86/time.c | 1 + sysdeps/unix/sysv/linux/x86_64/x32/getcpu.c | 1 + sysdeps/x86_64/ifuncmod8.c | 1 + 23 files changed, 65 insertions(+), 3 deletions(-)