diff --git a/glibc-rh1276761-1.patch b/glibc-rh1276761-1.patch new file mode 100644 index 0000000..2f74625 --- /dev/null +++ b/glibc-rh1276761-1.patch @@ -0,0 +1,66 @@ +commit a014cecd82b71b70a6a843e250e06b541ad524f7 +Author: Florian Weimer +Date: Thu Oct 15 09:23:07 2015 +0200 + + Always enable pointer guard [BZ #18928] + + Honoring the LD_POINTER_GUARD environment variable in AT_SECURE mode + has security implications. This commit enables pointer guard + unconditionally, and the environment variable is now ignored. + +Index: b/elf/rtld.c +=================================================================== +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -160,7 +160,6 @@ struct rtld_global_ro _rtld_global_ro at + ._dl_hwcap_mask = HWCAP_IMPORTANT, + ._dl_lazy = 1, + ._dl_fpu_control = _FPU_DEFAULT, +- ._dl_pointer_guard = 1, + ._dl_pagesize = EXEC_PAGESIZE, + ._dl_inhibit_cache = 0, + +@@ -707,15 +706,12 @@ security_init (void) + #endif + + /* Set up the pointer guard as well, if necessary. */ +- if (GLRO(dl_pointer_guard)) +- { +- uintptr_t pointer_chk_guard = _dl_setup_pointer_guard (_dl_random, +- stack_chk_guard); ++ uintptr_t pointer_chk_guard ++ = _dl_setup_pointer_guard (_dl_random, stack_chk_guard); + #ifdef THREAD_SET_POINTER_GUARD +- THREAD_SET_POINTER_GUARD (pointer_chk_guard); ++ THREAD_SET_POINTER_GUARD (pointer_chk_guard); + #endif +- __pointer_chk_guard_local = pointer_chk_guard; +- } ++ __pointer_chk_guard_local = pointer_chk_guard; + + /* We do not need the _dl_random value anymore. The less + information we leave behind, the better, so clear the +@@ -2467,9 +2463,6 @@ process_envvars (enum mode *modep) + GLRO(dl_use_load_bias) = envline[14] == '1' ? -1 : 0; + break; + } +- +- if (memcmp (envline, "POINTER_GUARD", 13) == 0) +- GLRO(dl_pointer_guard) = envline[14] != '0'; + break; + + case 14: +Index: b/sysdeps/generic/ldsodefs.h +=================================================================== +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -592,9 +592,6 @@ struct rtld_global_ro + /* List of auditing interfaces. */ + struct audit_ifaces *_dl_audit; + unsigned int _dl_naudit; +- +- /* 0 if internal pointer values should not be guarded, 1 if they should. */ +- EXTERN int _dl_pointer_guard; + }; + # define __rtld_global_attribute__ + # if IS_IN (rtld) diff --git a/glibc-rh1276761-2.patch b/glibc-rh1276761-2.patch new file mode 100644 index 0000000..2d387a5 --- /dev/null +++ b/glibc-rh1276761-2.patch @@ -0,0 +1,377 @@ +commit 99e1dc0a688d6c25d3f422bc9f3fa29adb483339 +Author: Florian Weimer +Date: Tue Oct 6 21:27:55 2015 +0200 + + Add a test case for C++11 thread_local support + + This requires a C++ compiler with thread_local support, and a new + configure check is needed. + +Index: b/config.make.in +=================================================================== +--- a/config.make.in ++++ b/config.make.in +@@ -67,6 +67,7 @@ bind-now = @bindnow@ + have-hash-style = @libc_cv_hashstyle@ + use-default-link = @use_default_link@ + output-format = @libc_cv_output_format@ ++have-cxx-thread_local = @libc_cv_cxx_thread_local@ + + static-libgcc = @libc_cv_gcc_static_libgcc@ + +Index: b/configure +=================================================================== +--- a/configure ++++ b/configure +@@ -614,6 +614,7 @@ use_nscd + libc_cv_gcc_unwind_find_fde + libc_extra_cppflags + libc_extra_cflags ++libc_cv_cxx_thread_local + CPPUNDEFS + sizeof_long_double + have_selinux +@@ -7202,6 +7203,61 @@ if test $libc_cv_builtin_trap = yes; the + + fi + ++ac_ext=cpp ++ac_cpp='$CXXCPP $CPPFLAGS' ++ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ++ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ++ac_compiler_gnu=$ac_cv_cxx_compiler_gnu ++ ++ ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C++ compiler supports thread_local" >&5 ++$as_echo_n "checking whether the C++ compiler supports thread_local... " >&6; } ++if ${libc_cv_cxx_thread_local+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ++old_CXXFLAGS="$CXXFLAGS" ++CXXFLAGS="$CXXFLAGS -std=gnu++11" ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++#include ++ ++// Compiler support. ++struct S ++{ ++ S (); ++ ~S (); ++}; ++thread_local S s; ++S * get () { return &s; } ++ ++// libstdc++ support. ++#ifndef _GLIBCXX_HAVE___CXA_THREAD_ATEXIT_IMPL ++#error __cxa_thread_atexit_impl not supported ++#endif ++ ++_ACEOF ++if ac_fn_cxx_try_compile "$LINENO"; then : ++ libc_cv_cxx_thread_local=yes ++else ++ libc_cv_cxx_thread_local=no ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++CXXFLAGS="$old_CXXFLAGS" ++ ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_cxx_thread_local" >&5 ++$as_echo "$libc_cv_cxx_thread_local" >&6; } ++ ++ ++ac_ext=c ++ac_cpp='$CPP $CPPFLAGS' ++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ++ac_compiler_gnu=$ac_cv_c_compiler_gnu ++ ++ + ### End of automated tests. + ### Now run sysdeps configure fragments. + +Index: b/configure.ac +=================================================================== +--- a/configure.ac ++++ b/configure.ac +@@ -1976,6 +1976,39 @@ if test $libc_cv_builtin_trap = yes; the + AC_DEFINE([HAVE_BUILTIN_TRAP]) + fi + ++dnl C++ feature tests. ++AC_LANG_PUSH([C++]) ++ ++AC_CACHE_CHECK([whether the C++ compiler supports thread_local], ++ libc_cv_cxx_thread_local, [ ++old_CXXFLAGS="$CXXFLAGS" ++CXXFLAGS="$CXXFLAGS -std=gnu++11" ++AC_COMPILE_IFELSE([AC_LANG_SOURCE([ ++#include ++ ++// Compiler support. ++struct S ++{ ++ S (); ++ ~S (); ++}; ++thread_local S s; ++S * get () { return &s; } ++ ++// libstdc++ support. ++#ifndef _GLIBCXX_HAVE___CXA_THREAD_ATEXIT_IMPL ++#error __cxa_thread_atexit_impl not supported ++#endif ++])], ++ [libc_cv_cxx_thread_local=yes], ++ [libc_cv_cxx_thread_local=no]) ++CXXFLAGS="$old_CXXFLAGS" ++]) ++AC_SUBST(libc_cv_cxx_thread_local) ++ ++AC_LANG_POP([C++]) ++dnl End of C++ feature tests. ++ + ### End of automated tests. + ### Now run sysdeps configure fragments. + +Index: b/nptl/Makefile +=================================================================== +--- a/nptl/Makefile ++++ b/nptl/Makefile +@@ -214,6 +214,8 @@ CFLAGS-recvfrom.c = -fexceptions -fasync + CFLAGS-pt-system.c = -fexceptions + + LDLIBS-tst-once5 = -lstdc++ ++CFLAGS-tst-thread_local1.o = -std=gnu++11 ++LDLIBS-tst-thread_local1 = -lstdc++ + + tests = tst-typesizes \ + tst-attr1 tst-attr2 tst-attr3 tst-default-attr \ +@@ -285,7 +287,8 @@ tests = tst-typesizes \ + tst-getpid3 \ + tst-setuid3 \ + tst-initializers1 $(addprefix tst-initializers1-,c89 gnu89 c99 gnu99) \ +- tst-bad-schedattr ++ tst-bad-schedattr \ ++ tst-thread_local1 + xtests = tst-setuid1 tst-setuid1-static tst-setuid2 \ + tst-mutexpp1 tst-mutexpp6 tst-mutexpp10 + test-srcs = tst-oddstacklimit +@@ -405,6 +408,10 @@ ifeq (,$(CXX)) + # These tests require a C++ compiler and runtime. + tests-unsupported += tst-cancel24 tst-cancel24-static tst-once5 + endif ++# These tests require a C++ compiler and runtime with thread_local support. ++ifneq ($(have-cxx-thread_local),yes) ++tests-unsupported += tst-thread_local1 ++endif + + include ../Rules + +Index: b/nptl/tst-thread_local1.cc +=================================================================== +--- /dev/null ++++ b/nptl/tst-thread_local1.cc +@@ -0,0 +1,199 @@ ++/* Test basic thread_local support. ++ Copyright (C) 2015 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++struct counter ++{ ++ int constructed {}; ++ int destructed {}; ++ ++ void reset (); ++}; ++ ++void ++counter::reset () ++{ ++ constructed = 0; ++ destructed = 0; ++} ++ ++static std::string ++to_string (const counter &c) ++{ ++ char buf[128]; ++ snprintf (buf, sizeof (buf), "%d/%d", ++ c.constructed, c.destructed); ++ return buf; ++} ++ ++template ++struct counting ++{ ++ counting () __attribute__ ((noinline, noclone)); ++ ~counting () __attribute__ ((noinline, noclone)); ++ void operation () __attribute__ ((noinline, noclone)); ++}; ++ ++template ++__attribute__ ((noinline, noclone)) ++counting::counting () ++{ ++ ++Counter->constructed; ++} ++ ++template ++__attribute__ ((noinline, noclone)) ++counting::~counting () ++{ ++ ++Counter->destructed; ++} ++ ++template ++void __attribute__ ((noinline, noclone)) ++counting::operation () ++{ ++ // Optimization barrier. ++ asm (""); ++} ++ ++static counter counter_static; ++static counter counter_anonymous_namespace; ++static counter counter_extern; ++static counter counter_function_local; ++static bool errors (false); ++ ++static std::string ++all_counters () ++{ ++ return to_string (counter_static) ++ + ' ' + to_string (counter_anonymous_namespace) ++ + ' ' + to_string (counter_extern) ++ + ' ' + to_string (counter_function_local); ++} ++ ++static void ++check_counters (const char *name, const char *expected) ++{ ++ std::string actual{all_counters ()}; ++ if (actual != expected) ++ { ++ printf ("error: %s: (%s) != (%s)\n", ++ name, actual.c_str (), expected); ++ errors = true; ++ } ++} ++ ++static void ++reset_all () ++{ ++ counter_static.reset (); ++ counter_anonymous_namespace.reset (); ++ counter_extern.reset (); ++ counter_function_local.reset (); ++} ++ ++static thread_local counting<&counter_static> counting_static; ++namespace { ++ thread_local counting<&counter_anonymous_namespace> ++ counting_anonymous_namespace; ++} ++extern thread_local counting<&counter_extern> counting_extern; ++thread_local counting<&counter_extern> counting_extern; ++ ++static void * ++thread_without_access (void *) ++{ ++ return nullptr; ++} ++ ++static void * ++thread_with_access (void *) ++{ ++ thread_local counting<&counter_function_local> counting_function_local; ++ counting_function_local.operation (); ++ check_counters ("early in thread_with_access", "0/0 0/0 0/0 1/0"); ++ counting_static.operation (); ++ counting_anonymous_namespace.operation (); ++ counting_extern.operation (); ++ check_counters ("in thread_with_access", "1/0 1/0 1/0 1/0"); ++ return nullptr; ++} ++ ++static int ++do_test (void) ++{ ++ std::function do_pthread = ++ [](void *(func) (void *)) ++ { ++ pthread_t thr; ++ int ret = pthread_create (&thr, nullptr, func, nullptr); ++ if (ret != 0) ++ { ++ errno = ret; ++ printf ("error: pthread_create: %m\n"); ++ errors = true; ++ return; ++ } ++ ret = pthread_join (thr, nullptr); ++ if (ret != 0) ++ { ++ errno = ret; ++ printf ("error: pthread_join: %m\n"); ++ errors = true; ++ return; ++ } ++ }; ++ std::function do_std_thread = ++ [](void *(func) (void *)) ++ { ++ std::thread thr{[func] {func (nullptr);}}; ++ thr.join (); ++ }; ++ ++ std::array>, 2> ++ do_thread_X ++ {{ ++ {"pthread_create", do_pthread}, ++ {"std::thread", do_std_thread}, ++ }}; ++ ++ for (auto do_thread : do_thread_X) ++ { ++ printf ("info: testing %s\n", do_thread.first); ++ check_counters ("initial", "0/0 0/0 0/0 0/0"); ++ do_thread.second (thread_without_access); ++ check_counters ("after thread_without_access", "0/0 0/0 0/0 0/0"); ++ reset_all (); ++ do_thread.second (thread_with_access); ++ check_counters ("after thread_with_access", "1/1 1/1 1/1 1/1"); ++ reset_all (); ++ } ++ ++ return errors; ++} ++ ++#define TEST_FUNCTION do_test () ++#include "../test-skeleton.c" diff --git a/glibc-rh1276761-3.patch b/glibc-rh1276761-3.patch new file mode 100644 index 0000000..9c89bce --- /dev/null +++ b/glibc-rh1276761-3.patch @@ -0,0 +1,36 @@ +commit f586e1328681b400078c995a0bb6ad301ef73549 +Author: Florian Weimer +Date: Tue Oct 6 13:12:36 2015 +0200 + + Harden tls_dtor_list with pointer mangling [BZ #19018] + +diff --git a/stdlib/cxa_thread_atexit_impl.c b/stdlib/cxa_thread_atexit_impl.c +index 2d5d56a..5717f09 100644 +--- a/stdlib/cxa_thread_atexit_impl.c ++++ b/stdlib/cxa_thread_atexit_impl.c +@@ -98,6 +98,10 @@ static __thread struct link_map *lm_cache; + int + __cxa_thread_atexit_impl (dtor_func func, void *obj, void *dso_symbol) + { ++#ifdef PTR_MANGLE ++ PTR_MANGLE (func); ++#endif ++ + /* Prepend. */ + struct dtor_list *new = calloc (1, sizeof (struct dtor_list)); + new->func = func; +@@ -142,9 +146,13 @@ __call_tls_dtors (void) + while (tls_dtor_list) + { + struct dtor_list *cur = tls_dtor_list; ++ dtor_func func = cur->func; ++#ifdef PTR_DEMANGLE ++ PTR_DEMANGLE (func); ++#endif + + tls_dtor_list = tls_dtor_list->next; +- cur->func (cur->obj); ++ func (cur->obj); + + /* Ensure that the MAP dereference happens before + l_tls_dtor_count decrement. That way, we protect this access from a diff --git a/glibc.spec b/glibc.spec index 63633b5..2784a49 100644 --- a/glibc.spec +++ b/glibc.spec @@ -218,6 +218,9 @@ Patch0055: glibc-rtkaio-libof.patch Patch1000: glibc-rh1276711.patch Patch1001: glibc-rh1288662.patch +Patch1002: glibc-rh1276761-1.patch +Patch1003: glibc-rh1276761-2.patch +Patch1004: glibc-rh1276761-3.patch ############################################################################## # @@ -622,6 +625,9 @@ microbenchmark tests on the system. %patch0055 -p1 %patch1000 -p1 %patch1001 -p1 +%patch1002 -p1 +%patch1003 -p1 +%patch1004 -p1 ############################################################################## # %%prep - Additional prep required... @@ -1839,6 +1845,7 @@ rm -f *.filelist* %changelog * Sat Dec 5 2015 Florian Weimer - 2.22-6 - Re-enable large file support in openat. (#1288662) +- Apply additional pointer guard hardening. (#1276761) * Mon Nov 9 2015 Carlos O'Donell - 2.22-5 - Remove invalid strcoll optimization (#1276711). diff --git a/series b/series index e6c058e..2ec94f9 100644 --- a/series +++ b/series @@ -46,3 +46,6 @@ glibc-rh1238412-unicode-8.0.0-update.patch -p1 --fuzz=0 glibc-rtkaio-libof.patch -p1 --fuzz=0 glibc-rh1276711.patch -p1 --fuzz=0 glibc-rh1288662.patch +glibc-rh1276761-1.patch +glibc-rh1276761-2.patch +glibc-rh1276761-3.patch