Message ID | 20230705143822.275049-2-fberat@redhat.com |
---|---|
State | New |
Headers | show |
Series | Allow glibc to be built with _FORTIFY_SOURCE | expand |
On 2023-07-05 10:38, Frédéric Bérat wrote: > Add --enable-fortify-source option. > > It is now possible to enable fortification through a configure option. > The level may be given as parameter, if none is provided, the configure > script will determine what is the highest level possible that can be set > considering GCC built-ins availability and set it. > If level is explicitly set to 3, configure checks if the compiler > supports the built-in function necessary for it or raise an error if it > isn't. > > If the configure option isn't explicitly enabled, it _FORTIFY_SOURCE is > forcibly undefined (and therefore disabled). > > The result of the configure checks are new variables, ${fortify_source} > and ${no_fortify_source} that can be used to appropriately populate > CFLAGS. > > A dedicated patch will follow to make use of this variable in Makefiles > when necessary. > > Updated NEWS and INSTALL. > > Adding dedicated x86_64 variant that enables the configuration. > --- > INSTALL | 8 ++++ > Makeconfig | 35 +++++++++++++-- > NEWS | 6 +++ > config.make.in | 3 +- > configure | 83 ++++++++++++++++++++++++++++-------- > configure.ac | 60 ++++++++++++++++++-------- > elf/rtld-Rules | 2 +- > manual/install.texi | 8 ++++ > scripts/build-many-glibcs.py | 4 +- > 9 files changed, 167 insertions(+), 42 deletions(-) LGTM. Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org> > > diff --git a/INSTALL b/INSTALL > index fe591c7dae..51297189c0 100644 > --- a/INSTALL > +++ b/INSTALL > @@ -276,6 +276,14 @@ if ‘CFLAGS’ is specified it must enable optimization. For example: > the GNU C Library. The default value refers to the main > bug-reporting information for the GNU C Library. > > +‘--enable-fortify-source’ > +‘--enable-fortify-source=LEVEL’ > + Use -D_FORTIFY_SOURCE=‘LEVEL’ to control hardening in the GNU C > + Library. If not provided, ‘LEVEL’ defaults to highest possible > + value supported by the build compiler. > + > + Default is to disable fortification. > + > To build the library and related programs, type ‘make’. This will > produce a lot of output, some of which may look like errors from ‘make’ > but aren’t. Look for error messages from ‘make’ containing ‘***’. > diff --git a/Makeconfig b/Makeconfig > index 2514db35f6..77d7fd14df 100644 > --- a/Makeconfig > +++ b/Makeconfig > @@ -543,12 +543,13 @@ endif # +link > # ARM, gcc always produces different debugging symbols when invoked with > # a -O greater than 0 than when invoked with -O0, regardless of anything else > # we're using to suppress optimizations. Therefore, we need to explicitly pass > -# -O0 to it through CFLAGS. > +# -O0 to it through CFLAGS. As a result, any fortification needs to be disabled > +# as it needs -O greater than 0. > # Additionally, the build system will try to -include $(common-objpfx)/config.h > # when compiling the tests, which will throw an error if some special macros > # (such as __OPTIMIZE__ and IS_IN_build) aren't defined. To avoid this, we > # tell gcc to define IS_IN_build. > -CFLAGS-printers-tests := -O0 -ggdb3 -DIS_IN_build > +CFLAGS-printers-tests := -O0 -ggdb3 -DIS_IN_build $(no-fortify-source) > > ifeq (yes,$(build-shared)) > # These indicate whether to link using the built ld.so or the installed one. > @@ -901,6 +902,16 @@ define elide-stack-protector > $(if $(filter $(@F),$(patsubst %,%$(1),$(2))), $(no-stack-protector)) > endef > > +# We might want to compile with fortify-source > +ifneq ($(fortify-source),) > ++fortify-source=$(fortify-source) > +endif > + > +# Some routine can't be fortified like the ones used by fortify > +define elide-fortify-source > +$(if $(filter $(@F),$(patsubst %,%$(1),$(2))), $(no-fortify-source)) > +endef > + > # The program that makes Emacs-style TAGS files. > ETAGS := etags > > @@ -961,6 +972,18 @@ endif # $(+cflags) == "" > $(+stack-protector) -fno-common > +gcc-nowarn := -w > > +# We must filter out elf because the early bootstrap of the dynamic loader > +# cannot be fortified. Likewise we exclude dlfcn because it is entangled > +# with the loader. We must filter out csu because early startup, like the > +# loader, cannot be fortified. Lastly debug is the fortification routines > +# themselves and they cannot be fortified. > +do-fortify = $(filter-out elf dlfcn csu debug,$(subdir)) > +ifeq ($(do-fortify),$(subdir)) > ++cflags += $(+fortify-source) > +else > ++cflags += $(no-fortify-source) > +endif > + > # Each sysdeps directory can contain header files that both will be > # used to compile and will be installed. Each can also contain an > # include/ subdirectory, whose header files will be used to compile > @@ -1010,7 +1033,7 @@ module-cppflags = $(if $(filter %.mk.i %.v.i,$(@F)),,$(module-cppflags-real)) > # Note that we can't use -std=* in CPPFLAGS, because it overrides > # the implicit -lang-asm and breaks cpp behavior for .S files--notably > # it causes cpp to stop predefining __ASSEMBLER__. > -CPPFLAGS = $(config-extra-cppflags) $(CPPUNDEFS) $(CPPFLAGS-config) \ > +CPPFLAGS = $(config-extra-cppflags) $(CPPFLAGS-config) \ > $($(subdir)-CPPFLAGS) \ > $(+includes) $(defines) $(module-cppflags) \ > -include $(..)include/libc-symbols.h $(sysdep-CPPFLAGS) \ > @@ -1049,6 +1072,8 @@ object-suffixes := > CPPFLAGS-.o = $(pic-default) > # libc.a must be compiled with -fPIE/-fpie for static PIE. > CFLAGS-.o = $(filter %frame-pointer,$(+cflags)) $(pie-default) > +CFLAGS-.o += $(call elide-fortify-source,.o,$(routines_no_fortify)) > +CFLAGS-.o += $(call elide-fortify-source,_chk.o,$(routines_no_fortify)) > libtype.o := lib%.a > object-suffixes += .o > ifeq (yes,$(build-shared)) > @@ -1058,6 +1083,8 @@ object-suffixes += .os > pic-cppflags = -DPIC -DSHARED > CPPFLAGS-.os = $(pic-cppflags) > CFLAGS-.os = $(filter %frame-pointer,$(+cflags)) $(pic-ccflag) > +CFLAGS-.os += $(call elide-fortify-source,.os,$(routines_no_fortify)) > +CFLAGS-.os += $(call elide-fortify-source,_chk.os,$(routines_no_fortify)) > libtype.os := lib%_pic.a > # This can be changed by a sysdep makefile > pic-ccflag = -fPIC > @@ -1077,6 +1104,8 @@ object-suffixes += .op > CPPFLAGS-.op = -DPROF $(pic-default) > # libc_p.a must be compiled with -fPIE/-fpie for static PIE. > CFLAGS-.op = -pg $(pie-default) > +CFLAGS-.op += $(call elide-fortify-source,.op,$(routines_no_fortify)) > +CFLAGS-.op += $(call elide-fortify-source,_chk.op,$(routines_no_fortify)) > libtype.op = lib%_p.a > endif > > diff --git a/NEWS b/NEWS > index 709ee40e50..f976abccbd 100644 > --- a/NEWS > +++ b/NEWS > @@ -48,6 +48,12 @@ Major new features: > * The strlcpy and strlcat functions have been added. They are derived > from OpenBSD, and are expected to be added to a future POSIX version. > > +* A new configure option, "--enable-fortify-source", can be used to build the > + GNU C Library with _FORTIFY_SOURCE. The level of fortification can either be > + provided, or is set to the highest value supported by the compiler. If not > + explicitly enabled, then fortify source is forcibly disabled so to keep > + original behavior unchanged. > + > Deprecated and removed features, and other changes affecting compatibility: > > * In the Linux kernel for the hppa/parisc architecture some of the > diff --git a/config.make.in b/config.make.in > index 4afd37feaf..d487a4f4e9 100644 > --- a/config.make.in > +++ b/config.make.in > @@ -64,6 +64,8 @@ have-fpie = @libc_cv_fpie@ > have-ssp = @libc_cv_ssp@ > stack-protector = @stack_protector@ > no-stack-protector = @no_stack_protector@ > +fortify-source = @fortify_source@ > +no-fortify-source = @no_fortify_source@ > have-selinux = @have_selinux@ > have-libaudit = @have_libaudit@ > have-libcap = @have_libcap@ > @@ -101,7 +103,6 @@ CXX = @CXX@ > BUILD_CC = @BUILD_CC@ > CFLAGS = @CFLAGS@ > CPPFLAGS-config = @CPPFLAGS@ > -CPPUNDEFS = @CPPUNDEFS@ > extra-nonshared-cflags = @extra_nonshared_cflags@ > rtld-early-cflags = @rtld_early_cflags@ > ASFLAGS-config = @ASFLAGS_config@ > diff --git a/configure b/configure > index f84040644b..1833a4ce66 100755 > --- a/configure > +++ b/configure > @@ -611,7 +611,10 @@ libc_cv_gcc_unwind_find_fde > libc_extra_cppflags > libc_extra_cflags > libc_cv_cxx_thread_local > -CPPUNDEFS > +fortify_source > +no_fortify_source > +libc_cv_fortify_source > +enable_fortify_source > have_selinux > have_libcap > have_libaudit > @@ -782,6 +785,7 @@ enable_pt_chown > enable_mathvec > enable_cet > enable_scv > +enable_fortify_source > with_cpu > ' > ac_precious_vars='build_alias > @@ -1452,6 +1456,10 @@ Optional Features: > (CET), x86 only > --disable-scv syscalls will not use scv instruction, even if the > kernel supports it, powerpc only > + --enable-fortify-source[=1|2|3] > + Use -D_FORTIFY_SOURCE=[1|2|3] to control code > + hardening, defaults to highest possible value > + supported by the build compiler. > > Optional Packages: > --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] > @@ -3717,6 +3725,18 @@ if test "$use_scv" != "no"; then : > > fi > > +# Check whether --enable-fortify-source was given. > +if test "${enable_fortify_source+set}" = set; then : > + enableval=$enable_fortify_source; enable_fortify_source=$enableval > +else > + enable_fortify_source=no > +fi > + > +case "$enable_fortify_source" in > +1|2|3|no|yes) ;; > +*) as_fn_error $? "Not a valid argument for --enable-fortify-source: \"$enable_fortify_source\"" "$LINENO" 5;; > +esac > + > # We keep the original values in `$config_*' and never modify them, so we > # can write them unchanged into config.make. Everything else uses > # $machine, $vendor, and $os, and changes them whenever convenient. > @@ -6353,40 +6373,67 @@ $as_echo "#define HAVE_LIBCAP 1" >>confdefs.h > fi > > > -CPPUNDEFS= > -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FORTIFY_SOURCE predefine" >&5 > -$as_echo_n "checking for _FORTIFY_SOURCE predefine... " >&6; } > -if ${libc_cv_predef_fortify_source+:} false; then : > +no_fortify_source="-Wp,-U_FORTIFY_SOURCE" > +fortify_source="${no_fortify_source}" > + > +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_dynamic_object_size" >&5 > +$as_echo_n "checking for __builtin_dynamic_object_size... " >&6; } > +if ${libc_cv___builtin_dynamic_object_size+:} false; then : > $as_echo_n "(cached) " >&6 > else > - cat confdefs.h - <<_ACEOF >conftest.$ac_ext > + > + cat confdefs.h - <<_ACEOF >conftest.$ac_ext > /* end confdefs.h. */ > > int > main () > { > - > -#ifdef _FORTIFY_SOURCE > -# error bogon > -#endif > +__builtin_dynamic_object_size("", 0) > ; > return 0; > } > _ACEOF > -if ac_fn_c_try_compile "$LINENO"; then : > - libc_cv_predef_fortify_source=no > +if ac_fn_c_try_link "$LINENO"; then : > + libc_cv___builtin_dynamic_object_size=yes > + if test "$enable_fortify_source" = yes; then : > + enable_fortify_source=3 > +fi > else > - libc_cv_predef_fortify_source=yes > + libc_cv___builtin_dynamic_object_size=no > + if test "$enable_fortify_source" = yes; then : > + enable_fortify_source=2 > fi > -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext > fi > -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_predef_fortify_source" >&5 > -$as_echo "$libc_cv_predef_fortify_source" >&6; } > -if test $libc_cv_predef_fortify_source = yes; then > - CPPUNDEFS="${CPPUNDEFS:+$CPPUNDEFS }-U_FORTIFY_SOURCE" > +rm -f core conftest.err conftest.$ac_objext \ > + conftest$ac_exeext conftest.$ac_ext > + > +fi > +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv___builtin_dynamic_object_size" >&5 > +$as_echo "$libc_cv___builtin_dynamic_object_size" >&6; } > + > +case $enable_fortify_source in #( > + 1|2) : > + libc_cv_fortify_source=yes ;; #( > + 3) : > + if test "$libc_cv___builtin_dynamic_object_size" = yes; then : > + libc_cv_fortify_source=yes > +else > + as_fn_error $? "Compiler doesn't provide necessary support for _FORTIFY_SOURCE=3" "$LINENO" 5 > +fi ;; #( > + *) : > + libc_cv_fortify_source=no ;; > +esac > + > +if test "$libc_cv_fortify_source" = yes; then : > + fortify_source="${fortify_source},-D_FORTIFY_SOURCE=${enable_fortify_source}" > + > fi > > > + > + > + > + > { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the assembler requires one version per symbol" >&5 > $as_echo_n "checking whether the assembler requires one version per symbol... " >&6; } > if ${libc_cv_symver_needs_alias+:} false; then : > diff --git a/configure.ac b/configure.ac > index 21879c933c..860109e60a 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -466,6 +466,17 @@ AC_ARG_ENABLE([scv], > > AS_IF([[test "$use_scv" != "no"]],[AC_DEFINE(USE_PPC_SCV)]) > > +dnl Build glibc with _FORTIFY_SOURCE > +AC_ARG_ENABLE(fortify-source, > + AS_HELP_STRING([--enable-fortify-source@<:@=1|2|3@:>@], > + [Use -D_FORTIFY_SOURCE=[1|2|3] to control code hardening, defaults to highest possible value supported by the build compiler.]), > + [enable_fortify_source=$enableval], > + [enable_fortify_source=no]) > +case "$enable_fortify_source" in > +1|2|3|no|yes) ;; > +*) AC_MSG_ERROR([Not a valid argument for --enable-fortify-source: "$enable_fortify_source"]);; > +esac > + > # We keep the original values in `$config_*' and never modify them, so we > # can write them unchanged into config.make. Everything else uses > # $machine, $vendor, and $os, and changes them whenever convenient. > @@ -1559,24 +1570,37 @@ if test "x$have_selinux" = xyes; then > fi > AC_SUBST(have_selinux) > > -CPPUNDEFS= > -dnl Check for silly hacked compilers predefining _FORTIFY_SOURCE. > -dnl Since we are building the implementations of the fortified functions here, > -dnl having the macro defined interacts very badly. > -dnl _FORTIFY_SOURCE requires compiler optimization level 1 (gcc -O1) > -dnl and above (see "man FEATURE_TEST_MACROS"). > -dnl So do NOT replace AC_COMPILE_IFELSE with AC_PREPROC_IFELSE. > -AC_CACHE_CHECK([for _FORTIFY_SOURCE predefine], libc_cv_predef_fortify_source, > -[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[ > -#ifdef _FORTIFY_SOURCE > -# error bogon > -#endif]])], > - [libc_cv_predef_fortify_source=no], > - [libc_cv_predef_fortify_source=yes])]) > -if test $libc_cv_predef_fortify_source = yes; then > - CPPUNDEFS="${CPPUNDEFS:+$CPPUNDEFS }-U_FORTIFY_SOURCE" > -fi > -AC_SUBST(CPPUNDEFS) > +dnl Check if we support the requested _FORTIFY_SOURCE level > +dnl If not, then don't use it. > +dnl Note that _FORTIFY_SOURCE may have been set through FLAGS too. > +dnl _FORTIFY_SOURCE value will be selectively disabled for function that can't > +dnl support it > +no_fortify_source="-Wp,-U_FORTIFY_SOURCE" > +fortify_source="${no_fortify_source}" > + > +AC_CACHE_CHECK([for __builtin_dynamic_object_size], [libc_cv___builtin_dynamic_object_size], [ > + AC_LINK_IFELSE([AC_LANG_PROGRAM([], [__builtin_dynamic_object_size("", 0)])], > + [libc_cv___builtin_dynamic_object_size=yes > + AS_IF([test "$enable_fortify_source" = yes], [enable_fortify_source=3])], > + [libc_cv___builtin_dynamic_object_size=no > + AS_IF([test "$enable_fortify_source" = yes], [enable_fortify_source=2])]) > +]) > + > +AS_CASE([$enable_fortify_source], > + [1|2], [libc_cv_fortify_source=yes], > + [3], [AS_IF([test "$libc_cv___builtin_dynamic_object_size" = yes], > + [libc_cv_fortify_source=yes], > + [AC_MSG_ERROR([Compiler doesn't provide necessary support for _FORTIFY_SOURCE=3])])], > + [libc_cv_fortify_source=no]) > + > +AS_IF([test "$libc_cv_fortify_source" = yes], > + [fortify_source="${fortify_source},-D_FORTIFY_SOURCE=${enable_fortify_source}"] > + ) > + > +AC_SUBST(enable_fortify_source) > +AC_SUBST(libc_cv_fortify_source) > +AC_SUBST(no_fortify_source) > +AC_SUBST(fortify_source) > > dnl Starting with binutils 2.35, GAS can attach multiple symbol versions > dnl to one symbol (PR 23840). > diff --git a/elf/rtld-Rules b/elf/rtld-Rules > index 56bc4543de..365a3408f3 100644 > --- a/elf/rtld-Rules > +++ b/elf/rtld-Rules > @@ -144,6 +144,6 @@ cpp-srcs-left := $(rtld-modules:%.os=%) > lib := rtld > include $(patsubst %,$(..)libof-iterator.mk,$(cpp-srcs-left)) > > -rtld-CFLAGS += $(no-stack-protector) > +rtld-CFLAGS += $(no-stack-protector) $(no-fortify-source) > > endif > diff --git a/manual/install.texi b/manual/install.texi > index a44a552d1f..e9c66ba499 100644 > --- a/manual/install.texi > +++ b/manual/install.texi > @@ -303,6 +303,14 @@ Specify the URL that users should visit if they wish to report a bug, > to be included in @option{--help} output from programs installed with > @theglibc{}. The default value refers to the main bug-reporting > information for @theglibc{}. > + > +@item --enable-fortify-source > +@itemx --enable-fortify-source=@var{LEVEL} > +Use -D_FORTIFY_SOURCE=@option{LEVEL} to control hardening in the GNU C Library. > +If not provided, @option{LEVEL} defaults to highest possible value supported by > +the build compiler. > + > +Default is to disable fortification. > @end table > > To build the library and related programs, type @code{make}. This will > diff --git a/scripts/build-many-glibcs.py b/scripts/build-many-glibcs.py > index e022abe284..e4eaec01e3 100755 > --- a/scripts/build-many-glibcs.py > +++ b/scripts/build-many-glibcs.py > @@ -464,7 +464,9 @@ class Context(object): > {'arch': 'i486', > 'ccopts': '-m32 -march=i486'}, > {'arch': 'i586', > - 'ccopts': '-m32 -march=i586'}]) > + 'ccopts': '-m32 -march=i586'}, > + {'variant': 'enable-fortify-source', > + 'cfg': ['--enable-fortify-source']}]) > self.add_config(arch='x86_64', > os_name='gnu', > gcc_cfg=['--disable-multilib'])
diff --git a/INSTALL b/INSTALL index fe591c7dae..51297189c0 100644 --- a/INSTALL +++ b/INSTALL @@ -276,6 +276,14 @@ if ‘CFLAGS’ is specified it must enable optimization. For example: the GNU C Library. The default value refers to the main bug-reporting information for the GNU C Library. +‘--enable-fortify-source’ +‘--enable-fortify-source=LEVEL’ + Use -D_FORTIFY_SOURCE=‘LEVEL’ to control hardening in the GNU C + Library. If not provided, ‘LEVEL’ defaults to highest possible + value supported by the build compiler. + + Default is to disable fortification. + To build the library and related programs, type ‘make’. This will produce a lot of output, some of which may look like errors from ‘make’ but aren’t. Look for error messages from ‘make’ containing ‘***’. diff --git a/Makeconfig b/Makeconfig index 2514db35f6..77d7fd14df 100644 --- a/Makeconfig +++ b/Makeconfig @@ -543,12 +543,13 @@ endif # +link # ARM, gcc always produces different debugging symbols when invoked with # a -O greater than 0 than when invoked with -O0, regardless of anything else # we're using to suppress optimizations. Therefore, we need to explicitly pass -# -O0 to it through CFLAGS. +# -O0 to it through CFLAGS. As a result, any fortification needs to be disabled +# as it needs -O greater than 0. # Additionally, the build system will try to -include $(common-objpfx)/config.h # when compiling the tests, which will throw an error if some special macros # (such as __OPTIMIZE__ and IS_IN_build) aren't defined. To avoid this, we # tell gcc to define IS_IN_build. -CFLAGS-printers-tests := -O0 -ggdb3 -DIS_IN_build +CFLAGS-printers-tests := -O0 -ggdb3 -DIS_IN_build $(no-fortify-source) ifeq (yes,$(build-shared)) # These indicate whether to link using the built ld.so or the installed one. @@ -901,6 +902,16 @@ define elide-stack-protector $(if $(filter $(@F),$(patsubst %,%$(1),$(2))), $(no-stack-protector)) endef +# We might want to compile with fortify-source +ifneq ($(fortify-source),) ++fortify-source=$(fortify-source) +endif + +# Some routine can't be fortified like the ones used by fortify +define elide-fortify-source +$(if $(filter $(@F),$(patsubst %,%$(1),$(2))), $(no-fortify-source)) +endef + # The program that makes Emacs-style TAGS files. ETAGS := etags @@ -961,6 +972,18 @@ endif # $(+cflags) == "" $(+stack-protector) -fno-common +gcc-nowarn := -w +# We must filter out elf because the early bootstrap of the dynamic loader +# cannot be fortified. Likewise we exclude dlfcn because it is entangled +# with the loader. We must filter out csu because early startup, like the +# loader, cannot be fortified. Lastly debug is the fortification routines +# themselves and they cannot be fortified. +do-fortify = $(filter-out elf dlfcn csu debug,$(subdir)) +ifeq ($(do-fortify),$(subdir)) ++cflags += $(+fortify-source) +else ++cflags += $(no-fortify-source) +endif + # Each sysdeps directory can contain header files that both will be # used to compile and will be installed. Each can also contain an # include/ subdirectory, whose header files will be used to compile @@ -1010,7 +1033,7 @@ module-cppflags = $(if $(filter %.mk.i %.v.i,$(@F)),,$(module-cppflags-real)) # Note that we can't use -std=* in CPPFLAGS, because it overrides # the implicit -lang-asm and breaks cpp behavior for .S files--notably # it causes cpp to stop predefining __ASSEMBLER__. -CPPFLAGS = $(config-extra-cppflags) $(CPPUNDEFS) $(CPPFLAGS-config) \ +CPPFLAGS = $(config-extra-cppflags) $(CPPFLAGS-config) \ $($(subdir)-CPPFLAGS) \ $(+includes) $(defines) $(module-cppflags) \ -include $(..)include/libc-symbols.h $(sysdep-CPPFLAGS) \ @@ -1049,6 +1072,8 @@ object-suffixes := CPPFLAGS-.o = $(pic-default) # libc.a must be compiled with -fPIE/-fpie for static PIE. CFLAGS-.o = $(filter %frame-pointer,$(+cflags)) $(pie-default) +CFLAGS-.o += $(call elide-fortify-source,.o,$(routines_no_fortify)) +CFLAGS-.o += $(call elide-fortify-source,_chk.o,$(routines_no_fortify)) libtype.o := lib%.a object-suffixes += .o ifeq (yes,$(build-shared)) @@ -1058,6 +1083,8 @@ object-suffixes += .os pic-cppflags = -DPIC -DSHARED CPPFLAGS-.os = $(pic-cppflags) CFLAGS-.os = $(filter %frame-pointer,$(+cflags)) $(pic-ccflag) +CFLAGS-.os += $(call elide-fortify-source,.os,$(routines_no_fortify)) +CFLAGS-.os += $(call elide-fortify-source,_chk.os,$(routines_no_fortify)) libtype.os := lib%_pic.a # This can be changed by a sysdep makefile pic-ccflag = -fPIC @@ -1077,6 +1104,8 @@ object-suffixes += .op CPPFLAGS-.op = -DPROF $(pic-default) # libc_p.a must be compiled with -fPIE/-fpie for static PIE. CFLAGS-.op = -pg $(pie-default) +CFLAGS-.op += $(call elide-fortify-source,.op,$(routines_no_fortify)) +CFLAGS-.op += $(call elide-fortify-source,_chk.op,$(routines_no_fortify)) libtype.op = lib%_p.a endif diff --git a/NEWS b/NEWS index 709ee40e50..f976abccbd 100644 --- a/NEWS +++ b/NEWS @@ -48,6 +48,12 @@ Major new features: * The strlcpy and strlcat functions have been added. They are derived from OpenBSD, and are expected to be added to a future POSIX version. +* A new configure option, "--enable-fortify-source", can be used to build the + GNU C Library with _FORTIFY_SOURCE. The level of fortification can either be + provided, or is set to the highest value supported by the compiler. If not + explicitly enabled, then fortify source is forcibly disabled so to keep + original behavior unchanged. + Deprecated and removed features, and other changes affecting compatibility: * In the Linux kernel for the hppa/parisc architecture some of the diff --git a/config.make.in b/config.make.in index 4afd37feaf..d487a4f4e9 100644 --- a/config.make.in +++ b/config.make.in @@ -64,6 +64,8 @@ have-fpie = @libc_cv_fpie@ have-ssp = @libc_cv_ssp@ stack-protector = @stack_protector@ no-stack-protector = @no_stack_protector@ +fortify-source = @fortify_source@ +no-fortify-source = @no_fortify_source@ have-selinux = @have_selinux@ have-libaudit = @have_libaudit@ have-libcap = @have_libcap@ @@ -101,7 +103,6 @@ CXX = @CXX@ BUILD_CC = @BUILD_CC@ CFLAGS = @CFLAGS@ CPPFLAGS-config = @CPPFLAGS@ -CPPUNDEFS = @CPPUNDEFS@ extra-nonshared-cflags = @extra_nonshared_cflags@ rtld-early-cflags = @rtld_early_cflags@ ASFLAGS-config = @ASFLAGS_config@ diff --git a/configure b/configure index f84040644b..1833a4ce66 100755 --- a/configure +++ b/configure @@ -611,7 +611,10 @@ libc_cv_gcc_unwind_find_fde libc_extra_cppflags libc_extra_cflags libc_cv_cxx_thread_local -CPPUNDEFS +fortify_source +no_fortify_source +libc_cv_fortify_source +enable_fortify_source have_selinux have_libcap have_libaudit @@ -782,6 +785,7 @@ enable_pt_chown enable_mathvec enable_cet enable_scv +enable_fortify_source with_cpu ' ac_precious_vars='build_alias @@ -1452,6 +1456,10 @@ Optional Features: (CET), x86 only --disable-scv syscalls will not use scv instruction, even if the kernel supports it, powerpc only + --enable-fortify-source[=1|2|3] + Use -D_FORTIFY_SOURCE=[1|2|3] to control code + hardening, defaults to highest possible value + supported by the build compiler. Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -3717,6 +3725,18 @@ if test "$use_scv" != "no"; then : fi +# Check whether --enable-fortify-source was given. +if test "${enable_fortify_source+set}" = set; then : + enableval=$enable_fortify_source; enable_fortify_source=$enableval +else + enable_fortify_source=no +fi + +case "$enable_fortify_source" in +1|2|3|no|yes) ;; +*) as_fn_error $? "Not a valid argument for --enable-fortify-source: \"$enable_fortify_source\"" "$LINENO" 5;; +esac + # We keep the original values in `$config_*' and never modify them, so we # can write them unchanged into config.make. Everything else uses # $machine, $vendor, and $os, and changes them whenever convenient. @@ -6353,40 +6373,67 @@ $as_echo "#define HAVE_LIBCAP 1" >>confdefs.h fi -CPPUNDEFS= -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FORTIFY_SOURCE predefine" >&5 -$as_echo_n "checking for _FORTIFY_SOURCE predefine... " >&6; } -if ${libc_cv_predef_fortify_source+:} false; then : +no_fortify_source="-Wp,-U_FORTIFY_SOURCE" +fortify_source="${no_fortify_source}" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_dynamic_object_size" >&5 +$as_echo_n "checking for __builtin_dynamic_object_size... " >&6; } +if ${libc_cv___builtin_dynamic_object_size+:} false; then : $as_echo_n "(cached) " >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { - -#ifdef _FORTIFY_SOURCE -# error bogon -#endif +__builtin_dynamic_object_size("", 0) ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - libc_cv_predef_fortify_source=no +if ac_fn_c_try_link "$LINENO"; then : + libc_cv___builtin_dynamic_object_size=yes + if test "$enable_fortify_source" = yes; then : + enable_fortify_source=3 +fi else - libc_cv_predef_fortify_source=yes + libc_cv___builtin_dynamic_object_size=no + if test "$enable_fortify_source" = yes; then : + enable_fortify_source=2 fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_predef_fortify_source" >&5 -$as_echo "$libc_cv_predef_fortify_source" >&6; } -if test $libc_cv_predef_fortify_source = yes; then - CPPUNDEFS="${CPPUNDEFS:+$CPPUNDEFS }-U_FORTIFY_SOURCE" +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv___builtin_dynamic_object_size" >&5 +$as_echo "$libc_cv___builtin_dynamic_object_size" >&6; } + +case $enable_fortify_source in #( + 1|2) : + libc_cv_fortify_source=yes ;; #( + 3) : + if test "$libc_cv___builtin_dynamic_object_size" = yes; then : + libc_cv_fortify_source=yes +else + as_fn_error $? "Compiler doesn't provide necessary support for _FORTIFY_SOURCE=3" "$LINENO" 5 +fi ;; #( + *) : + libc_cv_fortify_source=no ;; +esac + +if test "$libc_cv_fortify_source" = yes; then : + fortify_source="${fortify_source},-D_FORTIFY_SOURCE=${enable_fortify_source}" + fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the assembler requires one version per symbol" >&5 $as_echo_n "checking whether the assembler requires one version per symbol... " >&6; } if ${libc_cv_symver_needs_alias+:} false; then : diff --git a/configure.ac b/configure.ac index 21879c933c..860109e60a 100644 --- a/configure.ac +++ b/configure.ac @@ -466,6 +466,17 @@ AC_ARG_ENABLE([scv], AS_IF([[test "$use_scv" != "no"]],[AC_DEFINE(USE_PPC_SCV)]) +dnl Build glibc with _FORTIFY_SOURCE +AC_ARG_ENABLE(fortify-source, + AS_HELP_STRING([--enable-fortify-source@<:@=1|2|3@:>@], + [Use -D_FORTIFY_SOURCE=[1|2|3] to control code hardening, defaults to highest possible value supported by the build compiler.]), + [enable_fortify_source=$enableval], + [enable_fortify_source=no]) +case "$enable_fortify_source" in +1|2|3|no|yes) ;; +*) AC_MSG_ERROR([Not a valid argument for --enable-fortify-source: "$enable_fortify_source"]);; +esac + # We keep the original values in `$config_*' and never modify them, so we # can write them unchanged into config.make. Everything else uses # $machine, $vendor, and $os, and changes them whenever convenient. @@ -1559,24 +1570,37 @@ if test "x$have_selinux" = xyes; then fi AC_SUBST(have_selinux) -CPPUNDEFS= -dnl Check for silly hacked compilers predefining _FORTIFY_SOURCE. -dnl Since we are building the implementations of the fortified functions here, -dnl having the macro defined interacts very badly. -dnl _FORTIFY_SOURCE requires compiler optimization level 1 (gcc -O1) -dnl and above (see "man FEATURE_TEST_MACROS"). -dnl So do NOT replace AC_COMPILE_IFELSE with AC_PREPROC_IFELSE. -AC_CACHE_CHECK([for _FORTIFY_SOURCE predefine], libc_cv_predef_fortify_source, -[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[ -#ifdef _FORTIFY_SOURCE -# error bogon -#endif]])], - [libc_cv_predef_fortify_source=no], - [libc_cv_predef_fortify_source=yes])]) -if test $libc_cv_predef_fortify_source = yes; then - CPPUNDEFS="${CPPUNDEFS:+$CPPUNDEFS }-U_FORTIFY_SOURCE" -fi -AC_SUBST(CPPUNDEFS) +dnl Check if we support the requested _FORTIFY_SOURCE level +dnl If not, then don't use it. +dnl Note that _FORTIFY_SOURCE may have been set through FLAGS too. +dnl _FORTIFY_SOURCE value will be selectively disabled for function that can't +dnl support it +no_fortify_source="-Wp,-U_FORTIFY_SOURCE" +fortify_source="${no_fortify_source}" + +AC_CACHE_CHECK([for __builtin_dynamic_object_size], [libc_cv___builtin_dynamic_object_size], [ + AC_LINK_IFELSE([AC_LANG_PROGRAM([], [__builtin_dynamic_object_size("", 0)])], + [libc_cv___builtin_dynamic_object_size=yes + AS_IF([test "$enable_fortify_source" = yes], [enable_fortify_source=3])], + [libc_cv___builtin_dynamic_object_size=no + AS_IF([test "$enable_fortify_source" = yes], [enable_fortify_source=2])]) +]) + +AS_CASE([$enable_fortify_source], + [1|2], [libc_cv_fortify_source=yes], + [3], [AS_IF([test "$libc_cv___builtin_dynamic_object_size" = yes], + [libc_cv_fortify_source=yes], + [AC_MSG_ERROR([Compiler doesn't provide necessary support for _FORTIFY_SOURCE=3])])], + [libc_cv_fortify_source=no]) + +AS_IF([test "$libc_cv_fortify_source" = yes], + [fortify_source="${fortify_source},-D_FORTIFY_SOURCE=${enable_fortify_source}"] + ) + +AC_SUBST(enable_fortify_source) +AC_SUBST(libc_cv_fortify_source) +AC_SUBST(no_fortify_source) +AC_SUBST(fortify_source) dnl Starting with binutils 2.35, GAS can attach multiple symbol versions dnl to one symbol (PR 23840). diff --git a/elf/rtld-Rules b/elf/rtld-Rules index 56bc4543de..365a3408f3 100644 --- a/elf/rtld-Rules +++ b/elf/rtld-Rules @@ -144,6 +144,6 @@ cpp-srcs-left := $(rtld-modules:%.os=%) lib := rtld include $(patsubst %,$(..)libof-iterator.mk,$(cpp-srcs-left)) -rtld-CFLAGS += $(no-stack-protector) +rtld-CFLAGS += $(no-stack-protector) $(no-fortify-source) endif diff --git a/manual/install.texi b/manual/install.texi index a44a552d1f..e9c66ba499 100644 --- a/manual/install.texi +++ b/manual/install.texi @@ -303,6 +303,14 @@ Specify the URL that users should visit if they wish to report a bug, to be included in @option{--help} output from programs installed with @theglibc{}. The default value refers to the main bug-reporting information for @theglibc{}. + +@item --enable-fortify-source +@itemx --enable-fortify-source=@var{LEVEL} +Use -D_FORTIFY_SOURCE=@option{LEVEL} to control hardening in the GNU C Library. +If not provided, @option{LEVEL} defaults to highest possible value supported by +the build compiler. + +Default is to disable fortification. @end table To build the library and related programs, type @code{make}. This will diff --git a/scripts/build-many-glibcs.py b/scripts/build-many-glibcs.py index e022abe284..e4eaec01e3 100755 --- a/scripts/build-many-glibcs.py +++ b/scripts/build-many-glibcs.py @@ -464,7 +464,9 @@ class Context(object): {'arch': 'i486', 'ccopts': '-m32 -march=i486'}, {'arch': 'i586', - 'ccopts': '-m32 -march=i586'}]) + 'ccopts': '-m32 -march=i586'}, + {'variant': 'enable-fortify-source', + 'cfg': ['--enable-fortify-source']}]) self.add_config(arch='x86_64', os_name='gnu', gcc_cfg=['--disable-multilib'])