From dd4394b2493940ce0ec4525a21be4e2e9db483d0 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Fri, 22 Aug 2025 15:56:41 -0700 Subject: [PATCH] x86: Set have-protected-data to no if unsupported If the building compiler enables no direct external data access by default, access to protected data in shared libraries from executables must be compiled with no direct external data access. If the testing compiler doesn't support it, set have-protected-data to no to disable the tests which requires no direct external data access. Add LIBC_TRY_CC_COMMAND to test a building compiler option or options with an input file. This fixes BZ #33286. Signed-off-by: H.J. Lu Reviewed-by: Sam James --- aclocal.m4 | 17 +++++ sysdeps/x86/Makefile | 6 ++ sysdeps/x86/configure | 131 +++++++++++++++++++++++++++++++++++++++ sysdeps/x86/configure.ac | 70 +++++++++++++++++++++ 4 files changed, 224 insertions(+) diff --git a/aclocal.m4 b/aclocal.m4 index 21801429fb..cfe9c0b538 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -326,6 +326,23 @@ case "$prefix" in ;; esac]) +dnl Test a CC compiler option or options with an input file. +dnl LIBC_TRY_CC_COMMAND([message], [code], [options], +dnl [CC-cache-id], [CC-action-if-true], [CC-action-if-false]) +AC_DEFUN([LIBC_TRY_CC_COMMAND], +[ +cat > conftest.c <&AS_MESSAGE_LOG_FD]) + then + [$5] + else + [$6] + fi]) +rm -f conftest*]) + dnl Run a test with TEST_CC. dnl LIBC_CHECK_TEST_CC([commands]) AC_DEFUN([LIBC_CHECK_TEST_CC], diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile index 9e1c8cce85..e32a430bb9 100644 --- a/sysdeps/x86/Makefile +++ b/sysdeps/x86/Makefile @@ -144,6 +144,12 @@ $(objpfx)check-gnu2-tls.out: $(common-objpfx)libc.so | grep GLIBC_ABI_GNU2_TLS > $@; \ $(evaluate-test) generated += check-gnu2-tls.out + +ifneq (,$(test-cc-cflags-no-direct-extern-access)) +CFLAGS-tst-protected1a.c += $(test-cc-cflags-no-direct-extern-access) +CFLAGS-tst-protected1b.c += $(test-cc-cflags-no-direct-extern-access) +CFLAGS-vismain.c += $(test-cc-cflags-no-direct-extern-access) +endif endif ifeq ($(subdir),gmon) diff --git a/sysdeps/x86/configure b/sysdeps/x86/configure index dff26e9b83..f495f69894 100644 --- a/sysdeps/x86/configure +++ b/sysdeps/x86/configure @@ -213,6 +213,137 @@ CC="$saved_CC" config_vars="$config_vars have-test-cc-cflags-mfpmath-387 = $libc_cv_have_test_cc_cflags_mfpmath_387" +conftest_code=" +extern int foo; +int * +foo_p (void) +{ + return &foo; +} +" + +cat > conftest.c <&5 +printf %s "checking if no direct extern access is enabled by default... " >&6; } +if test ${libc_cv_cc_no_direct_extern_access+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -S -O2 -fno-pic conftest.c -o conftest 1>&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } + then + +libc_cv_cc_cflags_no_direct_extern_access=no +if test "$base_machine" = x86_64; then + if grep -E -q "mov[lq][ ]+foo@GOTPCREL\(%rip\)," conftest; then + libc_cv_cc_no_direct_extern_access=yes + fi +elif test "$base_machine" = i386; then + if grep -E -q "movl[ ]+foo@GOT," conftest; then + libc_cv_cc_no_direct_extern_access=yes + fi +else + echo unsupported machine: $base_machine + rm -f conftest* + exit 1 +fi + + else + +echo failed to check no direct external data access +rm -f conftest* +exit 1 + + fi ;; +esac +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_cc_no_direct_extern_access" >&5 +printf "%s\n" "$libc_cv_cc_no_direct_extern_access" >&6; } +rm -f conftest* + + + +saved_CC="$CC" +CC="$TEST_CC" +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if -mno-direct-extern-access works in testing" >&5 +printf %s "checking if -mno-direct-extern-access works in testing... " >&6; } +if test ${libc_cv_test_cc_cflags_mno_direct_extern_access+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) if { ac_try='${CC-cc} -Werror -mno-direct-extern-access -xc /dev/null -S -o /dev/null' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } +then : + libc_cv_test_cc_cflags_mno_direct_extern_access=yes +else case e in #( + e) libc_cv_test_cc_cflags_mno_direct_extern_access=no + ;; +esac +fi ;; +esac +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_test_cc_cflags_mno_direct_extern_access" >&5 +printf "%s\n" "$libc_cv_test_cc_cflags_mno_direct_extern_access" >&6; } + +CC="$saved_CC" + + + + + +saved_CC="$CC" +CC="$TEST_CC" +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if -fno-direct-access-external-data works in testing" >&5 +printf %s "checking if -fno-direct-access-external-data works in testing... " >&6; } +if test ${libc_cv_test_cc_cflags_fno_direct_access_external_data+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) if { ac_try='${CC-cc} -Werror -fno-direct-access-external-data -xc /dev/null -S -o /dev/null' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } +then : + libc_cv_test_cc_cflags_fno_direct_access_external_data=yes +else case e in #( + e) libc_cv_test_cc_cflags_fno_direct_access_external_data=no + ;; +esac +fi ;; +esac +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_test_cc_cflags_fno_direct_access_external_data" >&5 +printf "%s\n" "$libc_cv_test_cc_cflags_fno_direct_access_external_data" >&6; } + +CC="$saved_CC" + + + +if test $libc_cv_test_cc_cflags_mno_direct_extern_access = yes; then + libc_cv_test_cc_cflags_no_direct_extern_access="-mno-direct-extern-access" +elif test $libc_cv_test_cc_cflags_fno_direct_access_external_data = yes; then + libc_cv_test_cc_cflags_no_direct_extern_access="-fno-direct-access-external-data" +fi + +config_vars="$config_vars +test-cc-cflags-no-direct-extern-access = $libc_cv_test_cc_cflags_no_direct_extern_access" + +if test "${libc_cv_cc_no_direct_extern_access}${libc_cv_test_cc_cflags_no_direct_extern_access}" = yes; then + libc_cv_protected_data=no +fi + printf "%s\n" "#define SUPPORT_STATIC_PIE 1" >>confdefs.h diff --git a/sysdeps/x86/configure.ac b/sysdeps/x86/configure.ac index 54960a71c9..77ba6721ec 100644 --- a/sysdeps/x86/configure.ac +++ b/sysdeps/x86/configure.ac @@ -132,5 +132,75 @@ LIBC_TRY_TEST_CC_OPTION([if -mfpmath=387 works], LIBC_CONFIG_VAR(have-test-cc-cflags-mfpmath-387, $libc_cv_have_test_cc_cflags_mfpmath_387) +conftest_code=" +extern int foo; +int * +foo_p (void) +{ + return &foo; +} +" +dnl Check if CC enables no direct extern access by default. +LIBC_TRY_CC_COMMAND([if no direct extern access is enabled by default], + [$conftest_code], + [-S -O2 -fno-pic], + libc_cv_cc_no_direct_extern_access, + [ +libc_cv_cc_cflags_no_direct_extern_access=no +if test "$base_machine" = x86_64; then + if grep -E -q "mov[lq][ ]+foo@GOTPCREL\(%rip\)," conftest; then + libc_cv_cc_no_direct_extern_access=yes + fi +elif test "$base_machine" = i386; then + if grep -E -q "movl[ ]+foo@GOT," conftest; then + libc_cv_cc_no_direct_extern_access=yes + fi +else + echo unsupported machine: $base_machine + rm -f conftest* + exit 1 +fi + ], + [ +echo failed to check no direct external data access +rm -f conftest* +exit 1 +]) + +dnl Check if TEST_CC supports -mno-direct-extern-access. +LIBC_TRY_TEST_CC_OPTION([if -mno-direct-extern-access works], + [-Werror -mno-direct-extern-access], + libc_cv_test_cc_cflags_mno_direct_extern_access, + [libc_cv_test_cc_cflags_mno_direct_extern_access=yes], + [libc_cv_test_cc_cflags_mno_direct_extern_access=no] +) + +dnl Check if TEST_CC supports -fno-direct-access-external-data. +LIBC_TRY_TEST_CC_OPTION([if -fno-direct-access-external-data works], + [-Werror -fno-direct-access-external-data], + libc_cv_test_cc_cflags_fno_direct_access_external_data, + [libc_cv_test_cc_cflags_fno_direct_access_external_data=yes], + [libc_cv_test_cc_cflags_fno_direct_access_external_data=no] +) + +if test $libc_cv_test_cc_cflags_mno_direct_extern_access = yes; then + libc_cv_test_cc_cflags_no_direct_extern_access="-mno-direct-extern-access" +elif test $libc_cv_test_cc_cflags_fno_direct_access_external_data = yes; then + libc_cv_test_cc_cflags_no_direct_extern_access="-fno-direct-access-external-data" +fi + +LIBC_CONFIG_VAR(test-cc-cflags-no-direct-extern-access, + $libc_cv_test_cc_cflags_no_direct_extern_access) + +dnl If the building compiler enables no direct external data access by +dnl default, access to protected data in shared libraries from executables +dnl must be compiled with no direct external data access. If the testing +dnl compiler doesn't support it, set have-protected-data to no to disable +dnl the tests which requires no direct external data access. +dnl +if test "${libc_cv_cc_no_direct_extern_access}${libc_cv_test_cc_cflags_no_direct_extern_access}" = yes; then + libc_cv_protected_data=no +fi + dnl Static PIE is supported. AC_DEFINE(SUPPORT_STATIC_PIE) -- 2.47.3