From f3416f1436a39c7ff4f69c31d037ac277de5a637 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Mon, 15 Jan 2024 12:35:44 +0000 Subject: [PATCH] Add hardening feature to convert linker warning messages into errors. https://fedoraproject.org/wiki/Changes/Linker_Error_On_Security_Issues --- buildflags.md | 40 +++++++++++++++++++++++++++++++++++----- macros | 9 ++++++++- redhat-rpm-config.spec | 7 ++++++- 3 files changed, 49 insertions(+), 7 deletions(-) diff --git a/buildflags.md b/buildflags.md index 9d32a5a..8db4dc8 100644 --- a/buildflags.md +++ b/buildflags.md @@ -654,11 +654,9 @@ to the compiler driver `gcc`, and not directly to the link editor * `-z defs`: Refuse to link shared objects (DSOs) with undefined symbols (optional, see above). -For hardened builds, the -`-specs=/usr/lib/rpm/redhat/redhat-hardened-ld` flag is added to the -compiler driver command line. (This can be disabled by undefining the -`%_hardened_build` macro; see above) This activates the following -linker flags: +For hardened builds, some more linker options are added to the +compiler driver command line. These can be disabled by undefining the +`%_hardened_build` macro - see above. * `-pie`: Produce a PIE binary. This is only activated for the main executable, and only if it is dynamically linked. This requires @@ -667,6 +665,10 @@ linker flags: By itself, `-pie` has only a slight performance impact because it disables some link editor optimization, however the `-fPIE` compiler flag has some overhead. + Note: this option is added via adding a spec file to the compiler + driver command line (`-specs=/usr/lib/rpm/redhat/redhat-hardened-ld`) + rather than using the `-Wl` mechanism mentioned above. As a result + this option is only enabled if the compiler driver is gcc. * `-z now`: Disable lazy binding and turn on the `BIND_NOW` dynamic linker feature. Lazy binding involves an array of function pointers which is writable at run time (which could be overwritten as part of @@ -674,6 +676,34 @@ linker flags: preferable to turn of lazy binding, although it increases startup time. +In addition hardened builds default to converting a couple of linker +warning messages into errors, because they represent potential +missed hardening opportunities, and warnings in the linker's output are +often ignored. This behaviour can be turned off by undefining the +`%_hardened_build` macro as mentioned above, or by undefining the +`%_hardened_linker_errors` macro. The linker options enabled by this +feature are: + +* `--error-rwx-segments`: Generates an error if an output binary would + contain a loadable memory segment with read, write and execute + permissions. It will also generate an error if a thread local + storage (TLS) segment is created with execute permission. The + error can be disabled on an individual basis by adding the + `--no-warn-rwx-segments` option to the linker command line. +* `--error-execstack`: Generates an error if an output binary would + contain a stack that is held in memory with execute permission. + If a binary is being intentionally created with an executable stack + then the linker command line option `-z execstack` can be used to + indicate this. + +Note: these options are added via a spec file on the compiler driver +command line (`-specs=/usr/lib/rpm/redhat/redhat-hardened-ld-errors`) +rather than using the `-Wl` mechanism mentioned above. As a result +these options are only enabled if the compiler driver is gcc. In +addition the spec file only adds the options if the `-fuse-ld=...` +option has not been enabled. This prevents the options from being +used when the gold or lld linkers are enabled. + # Support for extension builders Some packages include extension builders that allow users to build diff --git a/macros b/macros index 61a83e3..dfacd55 100644 --- a/macros +++ b/macros @@ -325,8 +325,15 @@ for k,_ in pairs(stripped_flags) do print(k .. " ") end %_hardening_gcc_cflags -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 %_hardening_clang_cflags --config /usr/lib/rpm/redhat/redhat-hardened-clang.cfg %_hardening_cflags %{expand:%%{_hardening_%{toolchain}_cflags}} -fstack-protector-strong + +# Have the linker generate errors instead of warnings for binaries that +# contain memory regions with both write and execute permissions. +# https://fedoraproject.org/wiki/Changes/Linker_Error_On_Security_Issues +%_hardening_linker_errors %[ "%{toolchain}" == "gcc" ? "-specs=/usr/lib/rpm/redhat/redhat-hardened-ld-errors" : "" ] +%_hardened_linker_errors 1 + # we don't escape symbols '~', '"', etc. so be careful when changing this -%_hardening_ldflags -Wl,-z,now %[ "%{toolchain}" == "gcc" ? "-specs=/usr/lib/rpm/redhat/redhat-hardened-ld" : "" ] +%_hardening_ldflags -Wl,-z,now %{?_hardened_linker_errors:%{_hardening_linker_errors}} %[ "%{toolchain}" == "gcc" ? "-specs=/usr/lib/rpm/redhat/redhat-hardened-ld" : "" ] # Harden packages by default for Fedora 23+: # https://fedorahosted.org/fesco/ticket/1384 (accepted on 2014-02-11) diff --git a/redhat-rpm-config.spec b/redhat-rpm-config.spec index c2f6716..2480a6c 100644 --- a/redhat-rpm-config.spec +++ b/redhat-rpm-config.spec @@ -4,7 +4,7 @@ # 2) When making changes, increment the version (in baserelease) by 1. # rpmdev-bumpspec and other tools update the macro below, which is used # in Version: to get the desired effect. -%global baserelease 277 +%global baserelease 278 Summary: Red Hat specific rpm configuration files Name: redhat-rpm-config @@ -22,6 +22,7 @@ Source1: rpmrc Source50: redhat-hardened-cc1 Source51: redhat-hardened-ld Source52: redhat-hardened-clang.cfg +Source53: redhat-hardened-ld-errors # gcc specs files for annobin builds Source60: redhat-annobin-cc1 @@ -258,6 +259,10 @@ install -p -m 644 -t %{buildroot}%{_rpmluadir}/fedora common.lua %doc buildflags.md %changelog +* Mon Jan 15 2024 Nick Clifton - 278-1 +- Add hardening feature to convert linker warning messages into errors. +- https://fedoraproject.org/wiki/Changes/Linker_Error_On_Security_Issues + * Mon Jan 15 2024 Florian Weimer - 277-1 - Switch C type safety level to 3 (GCC 14 default), and adjust for GCC 14