summaryrefslogtreecommitdiffstats
path: root/m4/hardening.m4
blob: 45c501ff7e19e87b5724a12b6faabba7907b81e9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
AC_DEFUN([SUDO_CHECK_HARDENING], [
    if test "$enable_hardening" != "no"; then
	#
	# Attempt to use _FORTIFY_SOURCE with sprintf.  If the headers support
	# it but libc does not, __sprintf_chk should be an undefined symbol.
	#
	O_CPPFLAGS="$CPPFLAGS"
	AX_APPEND_FLAG([-D_FORTIFY_SOURCE=2], [CPPFLAGS])
	AC_CACHE_CHECK([whether _FORTIFY_SOURCE may be specified],
	    [sudo_cv_use_fortify_source],
	    [AC_LINK_IFELSE([
		    AC_LANG_PROGRAM(
			[[#include <stdio.h>]],
			[[char buf[4]; sprintf(buf, "%s", "foo"); return buf[0];]]
		    )],
		    [sudo_cv_use_fortify_source=yes],
		    [sudo_cv_use_fortify_source=no]
		)
	    ]
	)
	if test "$sudo_cv_use_fortify_source" != yes; then
	    CPPFLAGS="$O_CPPFLAGS"
	fi

	dnl
	dnl The following tests rely on AC_LANG_WERROR.
	dnl
	if test -n "$GCC" -a "$enable_ssp" != "no"; then
	    AC_CACHE_CHECK([for compiler stack protector support],
		[sudo_cv_var_stack_protector],
		[
		    # Avoid CFLAGS since the compiler might optimize away our
		    # test.  We don't want CPPFLAGS or LIBS to interfere with
		    # the test but keep LDFLAGS as it may have an rpath needed
		    # to find the ssp lib.
		    _CPPFLAGS="$CPPFLAGS"
		    _CFLAGS="$CFLAGS"
		    _LDFLAGS="$LDFLAGS"
		    _LIBS="$LIBS"
		    CPPFLAGS=
		    LIBS=

		    sudo_cv_var_stack_protector="-fstack-protector-strong"
		    CFLAGS="$sudo_cv_var_stack_protector"
		    LDFLAGS="$_LDFLAGS $sudo_cv_var_stack_protector"
		    AC_LINK_IFELSE([
			AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT],
			[[char buf[1024]; buf[1023] = '\0';]])
		    ], [], [
			sudo_cv_var_stack_protector="-fstack-protector-all"
			CFLAGS="$sudo_cv_var_stack_protector"
			LDFLAGS="$_LDFLAGS $sudo_cv_var_stack_protector"
			AC_LINK_IFELSE([
			    AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT],
			    [[char buf[1024]; buf[1023] = '\0';]])
			], [], [
			    sudo_cv_var_stack_protector="-fstack-protector"
			    CFLAGS="$sudo_cv_var_stack_protector"
			    LDFLAGS="$_LDFLAGS $sudo_cv_var_stack_protector"
			    AC_LINK_IFELSE([
				AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT],
				[[char buf[1024]; buf[1023] = '\0';]])
			    ], [], [
				sudo_cv_var_stack_protector=no
			    ])
			])
		    ])
		    CPPFLAGS="$_CPPFLAGS"
		    CFLAGS="$_CFLAGS"
		    LDFLAGS="$_LDFLAGS"
		    LIBS="$_LIBS"
		]
	    )
	    if test X"$sudo_cv_var_stack_protector" != X"no"; then
		HARDENING_CFLAGS="$sudo_cv_var_stack_protector"
		HARDENING_LDFLAGS="-Wc,$sudo_cv_var_stack_protector"
	    fi
	fi

	# The gcc front-end may accept -fstack-clash-protection even if the
	# machine-specific code does not support it.  We use a test program
	# with a large stack allocation to try to cause the compiler to
	# insert the stack clash protection code, or fail if not supported.
	if test -n "$GCC"; then
	    AC_CACHE_CHECK([whether C compiler supports -fstack-clash-protection],
		[sudo_cv_check_cflags___fstack_clash_protection],
		[
		    _CFLAGS="$CFLAGS"
		    CFLAGS="$CFLAGS -fstack-clash-protection"
		    AC_COMPILE_IFELSE([
			AC_LANG_SOURCE([[int main(int argc, char *argv[]) { char buf[16384], *src = argv[0], *dst = buf; while ((*dst++ = *src++) != '\0') { continue; } return buf[argc]; }]])
		    ], [sudo_cv_check_cflags___fstack_clash_protection=yes], [sudo_cv_check_cflags___fstack_clash_protection=no])
		    CFLAGS="$_CFLAGS"
		]
	    )
	    if test X"$sudo_cv_check_cflags___fstack_clash_protection" = X"yes"; then
		AX_CHECK_LINK_FLAG([-fstack-clash-protection], [
		    AX_APPEND_FLAG([-fstack-clash-protection], [HARDENING_CFLAGS])
		    AX_APPEND_FLAG([-Wc,-fstack-clash-protection], [HARDENING_LDFLAGS])
		])
	    fi

	    # Check for control-flow transfer instrumentation (Intel CET).
	    AX_CHECK_COMPILE_FLAG([-fcf-protection], [
		AX_CHECK_LINK_FLAG([-fcf-protection], [
		    AX_APPEND_FLAG([-fcf-protection], [HARDENING_CFLAGS])
		    AX_APPEND_FLAG([-Wc,-fcf-protection], [HARDENING_LDFLAGS])
		])
	    ])
	fi

	# Linker-specific hardening flags.
	if test X"$with_gnu_ld" = X"yes"; then
	    # GNU ld, and similar (gold, lld, etc).
	    AX_CHECK_LINK_FLAG([-Wl,-z,relro], [AX_APPEND_FLAG([-Wl,-z,relro], [HARDENING_LDFLAGS])])
	    AX_CHECK_LINK_FLAG([-Wl,-z,now], [AX_APPEND_FLAG([-Wl,-z,now], [HARDENING_LDFLAGS])])
	    AX_CHECK_LINK_FLAG([-Wl,-z,noexecstack], [AX_APPEND_FLAG([-Wl,-z,noexecstack], [HARDENING_LDFLAGS])])
	fi
    fi])