From 74c381f304679ff1feff40e46dbc180cff7b94fd Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Mon, 9 Feb 2015 20:52:50 -0700 Subject: Restrict default creation of PIE binaries (-fPIE and -pie) to Linux. OpenBSD also supports PIE but enables it by default so we don't need to do anything. This fixes problems on systems with a version of GNU ld that accepts -pie but where the run-time linker doesn't actually support PIE. Also verify that a trivial PIE binary works unless PIE is explicitly enabled. --- INSTALL | 17 ++++-- NEWS | 4 ++ TROUBLESHOOTING | 9 ++++ aclocal.m4 | 17 ++++++ configure | 157 +++++++++++++++++++++++++++++++++++++++++++++++++------- configure.in | 63 ++++++++++++++++------- 6 files changed, 225 insertions(+), 42 deletions(-) diff --git a/INSTALL b/INSTALL index 91b79751f..1c2e4e676 100644 --- a/INSTALL +++ b/INSTALL @@ -121,6 +121,18 @@ Special features/options: so configure and the compiler will look there for libraries. Multiple directories may be specified as with --with-incpath. + --enable-pie + Build sudo and related programs as as a position independent + executables (PIE). This improves the effectiveness of address + space layout randomization (ASLR) on systems that support it. + Sudo will create PIE binaries by default on Linux systems. + + --disable-pie + Disable the creation of position independent executables (PIE), + even if the compiler creates PIE binaries by default. This + option may be needed on some Linux systems where PIE binaries + are not fully supported. + --with-rpath Tells configure to use -Rpath in addition to -Lpath when passing library paths to the loader. This option is on @@ -657,11 +669,6 @@ The following options are also configurable at runtime: _FORTIFY_SOURCE defined to 2, building with -fstack-protector and linking with -zrelro, where supported. - --disable-pie - Disable the creation of position independent executables (PIE) - even when the compiler and linker support them. - By default, sudo will be built as a PIE where possible. - --enable-admin-flag Enable the creation of an Ubuntu-style admin flag file the first time sudo is run. diff --git a/NEWS b/NEWS index 4e1b932b8..e22a32199 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,10 @@ What's new in Sudo 1.7.10p9? * The TZ environment variable is now checked for safety instead of simply being copied to the environment of the command. + * Sudo now only builds Position Independent Executables (PIE) + by default on Linux systems and verifies that a trivial test + program builds and runs. + What's new in Sudo 1.7.10p8? * Sudo's exit code now indicates a failure if the user does not diff --git a/TROUBLESHOOTING b/TROUBLESHOOTING index e5e1bdebd..9ce9ef4b0 100644 --- a/TROUBLESHOOTING +++ b/TROUBLESHOOTING @@ -266,6 +266,15 @@ A) AIX's Enhanced RBAC is preventing sudo from running. To fix innateprivs = PV_DAC_GID,PV_DAC_O,PV_DAC_R,PV_DAC_UID,PV_DAC_W,PV_DAC_X,PV_FS_CHOWN,PV_PROC_ENV,PV_PROC_PRIO,PV_PROC_RAC secflags = FSF_EPS +Q) Sudo configures and builds without error but when I run it I get + a Segmentation fault. +A) If you are on a Linux system, the first thing to try is to run + configure with the --disable-pie option, then "make clean" and + "make". If that fixes the problem then your operating system + does not properly support position independent executables. + Please send a message to sudo@sudo.ws with system details such + as the Linux distro, kernel version and CPU architecture. + Q) How do you pronounce `sudo'? A) The official pronunciation is soo-doo (for su "do"). However, an alternate pronunciation, a homophone of "pseudo", is also common. diff --git a/aclocal.m4 b/aclocal.m4 index a0b7aa445..6ffa53e4a 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -172,6 +172,23 @@ rm -f core core.* *.core]) AC_MSG_RESULT($sudo_cv_func_fnmatch) AS_IF([test $sudo_cv_func_fnmatch = yes], [$1], [$2])]) +dnl +dnl Attempt to check for working PIE support. +dnl This is a bit of a hack but on Solaris 10 with GNU ld and GNU as +dnl we can end up with strange values from malloc(). +dnl A better check would be to verify that ASLR works with PIE. +dnl +AC_DEFUN([SUDO_WORKING_PIE], +[AC_MSG_CHECKING([for working PIE support]) +AC_CACHE_VAL(sudo_cv_working_pie, +[rm -f conftestdata; > conftestdata +AC_RUN_IFELSE([AC_LANG_SOURCE([AC_INCLUDES_DEFAULT +main() { char *p = malloc(1024); if (p == NULL) return 1; memset(p, 0, 1024); return 0; }])], [sudo_cv_working_pie=yes], [sudo_cv_working_pie=no], + [sudo_cv_working_pie=no]) +rm -f core core.* *.core]) +AC_MSG_RESULT($sudo_cv_working_pie) +AS_IF([test $sudo_cv_working_pie = yes], [$1], [$2])]) + dnl dnl check for isblank(3) dnl diff --git a/configure b/configure index 3fae65685..d6bc4749e 100755 --- a/configure +++ b/configure @@ -1557,8 +1557,7 @@ Optional Features: --enable-werror Whether to enable the -Werror compiler option --disable-hardening Do not use compiler/linker exploit mitigation options - --disable-pie Do not build position independent executables, even - if the compiler/linker supports them + --enable-pie Build sudo as a position independent executable. --enable-admin-flag Whether to create a Ubuntu-style admin flag file --enable-gss-krb5-ccache-name Use GSS-API to set the Kerberos V cred cache name @@ -5631,8 +5630,6 @@ fi # Check whether --enable-pie was given. if test "${enable_pie+set}" = set; then : enableval=$enable_pie; -else - enable_pie=yes fi @@ -14423,11 +14420,6 @@ done CHECKSHADOW="false" test -z "$with_pam" && AUTH_EXCL_DEF="PAM" : ${with_logincap='maybe'} - # PIE is broken on FreeBSD/ia64 - case "$host_cpu" in - ia64*) - enable_pie=no;; - esac ;; *-*-*openbsd*) # OpenBSD has a real setreuid(2) starting with 3.3 but @@ -20040,8 +20032,100 @@ done fi -if test "$enable_pie" != "no" -a -n "$GCC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -fPIE" >&5 + +ac_c_werror_flag=yes + +if test -n "$GCC"; then + if test -z "$enable_pie"; then + case "$host_os" in + linux*) + # Attempt to build with PIE support + enable_pie="maybe" + ;; + esac + fi + if test -n "$enable_pie"; then + if test "$enable_pie" = "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -fno-pie" >&5 +$as_echo_n "checking whether C compiler accepts -fno-pie... " >&6; } +if ${ax_cv_check_cflags___fno_pie+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ax_check_save_flags=$CFLAGS + CFLAGS="$CFLAGS -fno-pie" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ax_cv_check_cflags___fno_pie=yes +else + ax_cv_check_cflags___fno_pie=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$ax_check_save_flags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___fno_pie" >&5 +$as_echo "$ax_cv_check_cflags___fno_pie" >&6; } +if test x"$ax_cv_check_cflags___fno_pie" = xyes; then : + + _CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -fno-pie" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -nopie" >&5 +$as_echo_n "checking whether the linker accepts -nopie... " >&6; } +if ${ax_cv_check_ldflags___nopie+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ax_check_save_flags=$LDFLAGS + LDFLAGS="$LDFLAGS -nopie" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_cv_check_ldflags___nopie=yes +else + ax_cv_check_ldflags___nopie=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$ax_check_save_flags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___nopie" >&5 +$as_echo "$ax_cv_check_ldflags___nopie" >&6; } +if test x"$ax_cv_check_ldflags___nopie" = xyes; then : + + PIE_CFLAGS="-fno-pie" + PIE_LDFLAGS="-nopie" + +else + : +fi + + CFLAGS="$_CFLAGS" + +else + : +fi + + else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -fPIE" >&5 $as_echo_n "checking whether C compiler accepts -fPIE... " >&6; } if ${ax_cv_check_cflags___fPIE+:} false; then : $as_echo_n "(cached) " >&6 @@ -20072,9 +20156,9 @@ fi $as_echo "$ax_cv_check_cflags___fPIE" >&6; } if test x"$ax_cv_check_cflags___fPIE" = xyes; then : - _CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -fPIE" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -pie" >&5 + _CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -fPIE" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -pie" >&5 $as_echo_n "checking whether the linker accepts -pie... " >&6; } if ${ax_cv_check_ldflags___pie+:} false; then : $as_echo_n "(cached) " >&6 @@ -20106,24 +20190,59 @@ fi $as_echo "$ax_cv_check_ldflags___pie" >&6; } if test x"$ax_cv_check_ldflags___pie" = xyes; then : - PIE_CFLAGS="-fPIE" - PIE_LDFLAGS="-pie" + if test "$enable_pie" = "maybe"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working PIE support" >&5 +$as_echo_n "checking for working PIE support... " >&6; } +if ${sudo_cv_working_pie+:} false; then : + $as_echo_n "(cached) " >&6 +else + rm -f conftestdata; > conftestdata +if test "$cross_compiling" = yes; then : + sudo_cv_working_pie=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +main() { char *p = malloc(1024); if (p == NULL) return 1; memset(p, 0, 1024); return 0; } +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + sudo_cv_working_pie=yes +else + sudo_cv_working_pie=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +rm -f core core.* *.core +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_working_pie" >&5 +$as_echo "$sudo_cv_working_pie" >&6; } +if test $sudo_cv_working_pie = yes; then : + enable_pie=yes +fi + fi + if test "$enable_pie" = "yes"; then + PIE_CFLAGS="-fPIE" + PIE_LDFLAGS="-fPIE -pie" + fi else : fi - CFLAGS="$_CFLAGS" + CFLAGS="$_CFLAGS" else : fi + fi + fi fi if test "$enable_hardening" != "no"; then - -ac_c_werror_flag=yes if test -n "$GCC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -fstack-protector-all" >&5 $as_echo_n "checking whether C compiler accepts -fstack-protector-all... " >&6; } diff --git a/configure.in b/configure.in index 2191f6a03..a4cc98c27 100644 --- a/configure.in +++ b/configure.in @@ -1339,8 +1339,7 @@ AC_ARG_ENABLE(hardening, [], [enable_hardening=yes]) AC_ARG_ENABLE(pie, -[AS_HELP_STRING([--disable-pie], [Do not build position independent executables, even if the compiler/linker supports them])], -[], [enable_pie=yes]) +[AS_HELP_STRING([--enable-pie], [Build sudo as a position independent executable.])]) AC_ARG_ENABLE(admin-flag, [AS_HELP_STRING([--enable-admin-flag], [Whether to create a Ubuntu-style admin flag file])], @@ -1827,11 +1826,6 @@ case "$host" in CHECKSHADOW="false" test -z "$with_pam" && AUTH_EXCL_DEF="PAM" : ${with_logincap='maybe'} - # PIE is broken on FreeBSD/ia64 - case "$host_cpu" in - ia64*) - enable_pie=no;; - esac ;; *-*-*openbsd*) # OpenBSD has a real setreuid(2) starting with 3.3 but @@ -3030,20 +3024,54 @@ if test "${with_iologdir-yes}" != "no"; then ]) fi +dnl +dnl Turn warnings into errors. +dnl All compiler/loader tests after this point will fail if +dnl a warning is displayed (nornally, warnings are not fata). +dnl +AC_LANG_WERROR + dnl dnl Check for PIE executable support if using gcc. dnl This test relies on AC_LANG_WERROR dnl -if test "$enable_pie" != "no" -a -n "$GCC"; then - AX_CHECK_COMPILE_FLAG([-fPIE], [ - _CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -fPIE" - AX_CHECK_LINK_FLAG([-pie], [ - PIE_CFLAGS="-fPIE" - PIE_LDFLAGS="-pie" - ]) - CFLAGS="$_CFLAGS" - ]) +if test -n "$GCC"; then + if test -z "$enable_pie"; then + case "$host_os" in + linux*) + # Attempt to build with PIE support + enable_pie="maybe" + ;; + esac + fi + if test -n "$enable_pie"; then + if test "$enable_pie" = "no"; then + AX_CHECK_COMPILE_FLAG([-fno-pie], [ + _CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -fno-pie" + AX_CHECK_LINK_FLAG([-nopie], [ + PIE_CFLAGS="-fno-pie" + PIE_LDFLAGS="-nopie" + ]) + CFLAGS="$_CFLAGS" + ]) + else + AX_CHECK_COMPILE_FLAG([-fPIE], [ + _CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -fPIE" + AX_CHECK_LINK_FLAG([-pie], [ + if test "$enable_pie" = "maybe"; then + SUDO_WORKING_PIE([enable_pie=yes], []) + fi + if test "$enable_pie" = "yes"; then + PIE_CFLAGS="-fPIE" + PIE_LDFLAGS="-fPIE -pie" + fi + ]) + CFLAGS="$_CFLAGS" + ]) + fi + fi fi dnl @@ -3052,7 +3080,6 @@ dnl This must be towards the end as it turns warnings dnl into fatal errors (and there is no way to undo that) dnl if test "$enable_hardening" != "no"; then - AC_LANG_WERROR if test -n "$GCC"; then AX_CHECK_COMPILE_FLAG([-fstack-protector-all], [ AX_CHECK_LINK_FLAG([-fstack-protector-all], [ -- cgit v1.2.1