From 3eec07ec599649009c44abf7db5a5ac24bcda374 Mon Sep 17 00:00:00 2001 From: Robert Scott Date: Sun, 27 Apr 2025 12:34:00 +0100 Subject: [PATCH 1/2] cc-wrapper: add glibcxxassertions hardening flag no platforms "unsupported" because we don't have a nice mechanism for determining a platform's c++ lib and the flag should be harmlessly ignored by a other c++ libs --- doc/redirects.json | 3 ++ doc/stdenv/stdenv.chapter.md | 6 ++++ .../build-support/cc-wrapper/add-hardening.sh | 6 +++- pkgs/stdenv/generic/make-derivation.nix | 1 + pkgs/test/cc-wrapper/hardening.nix | 30 +++++++++++++++++++ pkgs/top-level/variants.nix | 1 + 6 files changed, 46 insertions(+), 1 deletion(-) diff --git a/doc/redirects.json b/doc/redirects.json index 7b0841c639b74..a6622543e1e88 100644 --- a/doc/redirects.json +++ b/doc/redirects.json @@ -574,6 +574,9 @@ "strictflexarrays3": [ "index.html#strictflexarrays3" ], + "glibcxxassertions": [ + "index.html#glibcxxassertions" + ], "tester-shfmt": [ "index.html#tester-shfmt" ], diff --git a/doc/stdenv/stdenv.chapter.md b/doc/stdenv/stdenv.chapter.md index 9cebd8818d03a..e797ef18e6433 100644 --- a/doc/stdenv/stdenv.chapter.md +++ b/doc/stdenv/stdenv.chapter.md @@ -1688,6 +1688,12 @@ This should be turned off or fixed for build errors such as: sorry, unimplemented: __builtin_clear_padding not supported for variable length aggregates ``` +#### `glibcxxassertions` {#glibcxxassertions} + +Adds the `-D_GLIBCXX_ASSERTIONS` compiler flag. This flag only has an effect on libstdc++ targets, and when defined, enables extra error checking in the form of precondition assertions, such as bounds checking in c++ strings and null pointer checks when dereferencing c++ smart pointers. + +These checks may have an impact on performance in some cases. + #### `pacret` {#pacret} This flag adds the `-mbranch-protection=pac-ret` compiler option on aarch64-linux targets. This uses ARM v8.3's Pointer Authentication feature to sign function return pointers before adding them to the stack. The pointer's authenticity is then validated before returning to its destination. This dramatically increases the difficulty of ROP exploitation techniques. diff --git a/pkgs/build-support/cc-wrapper/add-hardening.sh b/pkgs/build-support/cc-wrapper/add-hardening.sh index 319225a6ed874..4fd6d4b324636 100644 --- a/pkgs/build-support/cc-wrapper/add-hardening.sh +++ b/pkgs/build-support/cc-wrapper/add-hardening.sh @@ -52,7 +52,7 @@ fi if (( "${NIX_DEBUG:-0}" >= 1 )); then - declare -a allHardeningFlags=(fortify fortify3 shadowstack stackprotector stackclashprotection nostrictaliasing pacret strictflexarrays1 strictflexarrays3 pie pic strictoverflow format trivialautovarinit zerocallusedregs) + declare -a allHardeningFlags=(fortify fortify3 shadowstack stackprotector stackclashprotection nostrictaliasing pacret strictflexarrays1 strictflexarrays3 pie pic strictoverflow glibcxxassertions format trivialautovarinit zerocallusedregs) declare -A hardeningDisableMap=() # Determine which flags were effectively disabled so we can report below. @@ -111,6 +111,10 @@ for flag in "${!hardeningEnableMap[@]}"; do if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling pacret >&2; fi hardeningCFlagsBefore+=('-mbranch-protection=pac-ret') ;; + glibcxxassertions) + if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling glibcxxassertions >&2; fi + hardeningCFlagsBefore+=('-D_GLIBCXX_ASSERTIONS') + ;; stackprotector) if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling stackprotector >&2; fi hardeningCFlagsBefore+=('-fstack-protector-strong' '--param' 'ssp-buffer-size=4') diff --git a/pkgs/stdenv/generic/make-derivation.nix b/pkgs/stdenv/generic/make-derivation.nix index aed866aa454b9..49a1ebddc07ab 100644 --- a/pkgs/stdenv/generic/make-derivation.nix +++ b/pkgs/stdenv/generic/make-derivation.nix @@ -150,6 +150,7 @@ let "pie" "relro" "stackprotector" + "glibcxxassertions" "stackclashprotection" "strictoverflow" "trivialautovarinit" diff --git a/pkgs/test/cc-wrapper/hardening.nix b/pkgs/test/cc-wrapper/hardening.nix index 9f2de5243278d..f3e8d38d0ee8b 100644 --- a/pkgs/test/cc-wrapper/hardening.nix +++ b/pkgs/test/cc-wrapper/hardening.nix @@ -4,6 +4,7 @@ runCommand, runCommandWith, runCommandCC, + writeText, bintools, hello, debian-devscripts, @@ -40,6 +41,17 @@ let flexArrF2ExampleWithStdEnv = writeCBinWithStdenv ./flex-arrays-fortify-example.c; + checkGlibcxxassertionsWithStdEnv = + expectDefined: + writeCBinWithStdenv ( + writeText "main.cpp" '' + #if${if expectDefined then "n" else ""}def _GLIBCXX_ASSERTIONS + #error "Expected _GLIBCXX_ASSERTIONS to be ${if expectDefined then "" else "un"}defined" + #endif + int main() {} + '' + ); + # for when we need a slightly more complicated program helloWithStdEnv = stdenv': env: @@ -502,6 +514,10 @@ nameDrvAfterAttrName ( hardeningEnable = [ "shadowstack" ]; }) false; + glibcxxassertionsExplicitEnabled = checkGlibcxxassertionsWithStdEnv true stdenv { + hardeningEnable = [ "glibcxxassertions" ]; + }; + bindNowExplicitDisabled = checkTestBin (f2exampleWithStdEnv stdenv { @@ -697,6 +713,10 @@ nameDrvAfterAttrName ( hardeningDisable = [ "shadowstack" ]; }) true; + glibcxxassertionsExplicitDisabled = checkGlibcxxassertionsWithStdEnv false stdenv { + hardeningDisable = [ "glibcxxassertions" ]; + }; + # most flags can't be "unsupported" by compiler alone and # binutils doesn't have an accessible hardeningUnsupportedFlags # mechanism, so can only test a couple of flags through altered @@ -897,6 +917,12 @@ nameDrvAfterAttrName ( expectFailure = true; }; + glibcxxassertionsStdenvUnsupp = + checkGlibcxxassertionsWithStdEnv false (stdenvUnsupport [ "glibcxxassertions" ]) + { + hardeningEnable = [ "glibcxxassertions" ]; + }; + fortify3EnabledEnvEnablesFortify1 = checkTestBin (f1exampleWithStdEnv stdenv { @@ -1107,6 +1133,10 @@ nameDrvAfterAttrName ( allExplicitDisabledShadowStack = shadowStackTest (f1exampleWithStdEnv stdenv { hardeningDisable = [ "all" ]; }) true; + + glibcxxassertionsExplicitDisabled = checkGlibcxxassertionsWithStdEnv false stdenv { + hardeningDisable = [ "all" ]; + }; } ) ) diff --git a/pkgs/top-level/variants.nix b/pkgs/top-level/variants.nix index fb4890910cdfb..b4e970f98a342 100644 --- a/pkgs/top-level/variants.nix +++ b/pkgs/top-level/variants.nix @@ -164,6 +164,7 @@ self: super: { "shadowstack" "nostrictaliasing" "pacret" + "glibcxxassertions" "trivialautovarinit" ] ) super'.stdenv; From 1293be8892244428a5c1356b9e39bbc0b06ec971 Mon Sep 17 00:00:00 2001 From: Robert Scott Date: Sat, 10 May 2025 23:16:14 +0100 Subject: [PATCH 2/2] arrow-cpp: disable glibcxxassertions hardening flag --- pkgs/by-name/ar/arrow-cpp/package.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkgs/by-name/ar/arrow-cpp/package.nix b/pkgs/by-name/ar/arrow-cpp/package.nix index afc3879f6ad67..8c8cdebd117ee 100644 --- a/pkgs/by-name/ar/arrow-cpp/package.nix +++ b/pkgs/by-name/ar/arrow-cpp/package.nix @@ -178,6 +178,9 @@ stdenv.mkDerivation (finalAttrs: { ZSTD_ROOT = zstd.dev; }; + # fails tests on glibc with this enabled + hardeningDisable = [ "glibcxxassertions" ]; + preConfigure = '' patchShebangs build-support/ substituteInPlace "src/arrow/vendored/datetime/tz.cpp" \