diff --git a/buildflags.md b/buildflags.md index 4e53c85..0fee80c 100644 --- a/buildflags.md +++ b/buildflags.md @@ -117,7 +117,7 @@ or: ### Controlling Type Safety The macro `%build_type_safety_c` can be set to change the C type -safety level. The default level is 1, see below. It can be set to 0 +safety level. The default level is 3, see below. It can be set to 0 to get historic levels of type safety. Changing the type safety level may depend on correct `CFLAGS` propagation during the build. The `%build_type_safety_c` macro needs to be set before `CFLAGS`-related @@ -130,14 +130,14 @@ the `%build_type_safety_c` level to increase it, spec file should use a construct like this to avoid *lowering* a future default: ``` -%if %build_type_safety_c < 2 -%global build_type_safety_c 2 +%if %build_type_safety_c < 4 +%global build_type_safety_c 4 %endif ``` At level 0, all C constructs that GCC accepts for backwards compatibility with obsolete language standards are accepted during -package builds. +package builds. This is achieved by passing `-fpermissive` to GCC. At level 1, the following additional error categories are enabled: @@ -151,6 +151,12 @@ At level 1, the following additional error categories are enabled: Previously, such expressions where we compiled as if a declaration `extern int function_not_defined_anywhere ();` (a prototype-less function declaration) were in scope. +* `-Werror=return-mismatch`: Reject `return` statements with missing + or extra expressions, based on the declared return type of the + function. +* `-Wdeclaration-missing-parameter-type`: Reject function declarations + that contain unknown type names (which used to be treated as ignored + identifier names). At level 2, the following error category is enabled in addition: @@ -575,9 +581,9 @@ These compiler flags are enabled for all builds (hardened/annotated or not), but their selection depends on the architecture: * `-fcf-protection`: Instrument binaries to guard against - ROP/JOP attacks. Used on i686 and x86_64. + ROP/JOP exploitation techniques. Used on x86_64. * `-mbranch-protection=standard`: Instrument binaries to guard against - ROP/JOP attacks. Used on aarch64. + ROP/JOP exploitation techniques. Used on aarch64. * `-m64` and `-m32`: Some GCC builds support both 32-bit and 64-bit in the same compilation. For such architectures, the RPM build process explicitly selects the architecture variant by passing this compiler @@ -648,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 @@ -661,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 @@ -668,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 1389fcd..cb38b5a 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) @@ -403,14 +410,14 @@ for k,_ in pairs(stripped_flags) do print(k .. " ") end # This can be set to a positive integer to obtain increasing type # safety levels for C. See buildflags.md. -%build_type_safety_c 1 +%build_type_safety_c 3 # Some linkers default to a build-id algorithm that is not supported by rpmbuild, # so we need to specify the right algorithm to use. %_build_id_flags -Wl,--build-id=sha1 %_general_options -O2 %{?_lto_cflags} -fexceptions -g -grecord-gcc-switches -pipe -%_warning_options -Wall%[%__build_for_lang_any && "%toolchain" == "gcc" ? " -Wno-complain-wrong-lang" : ""]%[%__build_for_lang_c + %__build_for_lang_cxx ? " -Werror=format-security" : ""]%[%__build_for_lang_c && (%build_type_safety_c >= 1) ? " -Werror=implicit-function-declaration -Werror=implicit-int" : ""]%[%__build_for_lang_c && (%build_type_safety_c >= 2) ? " -Werror=int-conversion" : ""]%[%__build_for_lang_c && (%build_type_safety_c >= 3) ? " -Werror=incompatible-pointer-types" : ""] +%_warning_options -Wall%[%__build_for_lang_any && "%toolchain" == "gcc" ? " -Wno-complain-wrong-lang" : ""]%[%__build_for_lang_c + %__build_for_lang_cxx ? " -Werror=format-security" : ""]%[%__build_for_lang_c && (%build_type_safety_c == 0) ? " -fpermissive" : ""]%[%__build_for_lang_c && (%build_type_safety_c == 1) ? " -Wno-error=int-conversion" : ""]%[%__build_for_lang_c && (%build_type_safety_c > 0 && %build_type_safety_c < 3) ? " -Wno-error=incompatible-pointer-types" : ""] %_preprocessor_defines %{_fortify_level_flags} -Wp,-D_GLIBCXX_ASSERTIONS # Common variables are no longer generated by default by gcc and clang diff --git a/redhat-hardened-ld-errors b/redhat-hardened-ld-errors new file mode 100644 index 0000000..1a8ca26 --- /dev/null +++ b/redhat-hardened-ld-errors @@ -0,0 +1,2 @@ +*self_spec: ++ %{!fuse-ld*:%{!r:-Wl,--error-rwx-segments -Wl,--error-execstack}} diff --git a/redhat-rpm-config.spec b/redhat-rpm-config.spec index a887317..950e568 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 275 +%global baserelease 280 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 @@ -103,7 +104,9 @@ Requires: openblas-srpm-macros Requires: perl-srpm-macros # ↓ Has Python BRPs originaly present in redhat-rpm-config Requires: python-srpm-macros >= 3.11-7 +%if ! 0%{?rhel} Requires: qt5-srpm-macros +%endif Requires: qt6-srpm-macros # rust-srpm-macros v24 contains %%build_rustflags defintion Requires: rust-srpm-macros >= 24 @@ -137,7 +140,10 @@ Requires: (gawk if clang) # -fstack-clash-protection and -fcf-protection require GCC 8. Conflicts: gcc < 8.0.1-0.22 -Obsoletes: rpmautospec-rpm-macros < 0.3.6 +# Obsoletes intentionally without version: rpmautospec in Fedora <= 39 ships +# the macro package, and its version has long passed the one previously +# recorded here. +Obsoletes: rpmautospec-rpm-macros Provides: system-rpm-config = %{version}-%{release} @@ -256,13 +262,29 @@ install -p -m 644 -t %{buildroot}%{_rpmluadir}/fedora common.lua %doc buildflags.md %changelog -* Tue Jan 09 2024 David Abdurachmanov - 275-1.0.riscv64 +* Thu Feb 01 2024 David Abdurachmanov - 280-1.0.riscv64 - Set all LTO macros (_lto_cflags, _gcc_lto_cflags, _clang_lto_cflags) to nil as we want to increase build times for packages. - Add riscv64 to %%gap_arches, %%java_arches, and %%nodejs_arches - Set %%_clang_lto_cflags to %%nil as ld.gold is not implemented for riscv64 and thus LTO with Clang doesn't work. +* Tue Jan 16 2024 Florian Weimer - 280-1 +- Drop -fcf-protection for i686 because there won't be kernel support + +* Tue Jan 16 2024 Nils Philippsen - 279-1 +- Obsolete rpmautospec-rpm-macros without version + +* 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 + +* Thu Jan 11 2024 Jan Grulich - 276-1 +- Drop qt5-srpm-macros from RHEL 10 + * Fri Jan 05 2024 Yaakov Selkowitz - 275-1 - Define RUSTFLAGS only when rust macros are installed diff --git a/rpmrc b/rpmrc index a407129..cd37043 100644 --- a/rpmrc +++ b/rpmrc @@ -3,7 +3,7 @@ include: /usr/lib/rpm/rpmrc optflags: i386 %{__global_compiler_flags} -m32 -march=i386 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection optflags: i486 %{__global_compiler_flags} -m32 -march=i486 -fasynchronous-unwind-tables -fstack-clash-protection optflags: i586 %{__global_compiler_flags} -m32 -march=i586 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -optflags: i686 %{__global_compiler_flags} -m32 -march=i686 -mtune=generic -msse2 -mfpmath=sse -mstackrealign -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection +optflags: i686 %{__global_compiler_flags} -m32 -march=i686 -mtune=generic -msse2 -mfpmath=sse -mstackrealign -fasynchronous-unwind-tables -fstack-clash-protection optflags: athlon %{__global_compiler_flags} -m32 -march=athlon -fasynchronous-unwind-tables -fstack-clash-protection optflags: x86_64 %{__global_compiler_flags} -m64 %{__cflags_arch_x86_64} %__cflags_arch_x86_64_common optflags: x86_64_v2 %{__global_compiler_flags} -m64 -march=x86-64-v2 %__cflags_arch_x86_64_common