Merge pull request #324429 from risicle/ris-pacret

cc-wrapper: add support for `pacret` hardening flag on aarch64
This commit is contained in:
Emily 2024-07-28 20:25:44 +01:00 committed by GitHub
commit 06a221947e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 24 additions and 1 deletions

View File

@ -1564,6 +1564,14 @@ sorry, unimplemented: __builtin_clear_padding not supported for variable length
This flag adds the `-fstack-clash-protection` compiler option, which causes growth of a program's stack to access each successive page in order. This should force the guard page to be accessed and cause an attempt to "jump over" this guard page to crash.
#### `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.
This may cause problems with code that does advanced stack manipulation, and debugging/stack-unwinding tools need to be pac-ret aware to work correctly when these features are in operation.
Pre-ARM v8.3 processors will ignore Pointer Authentication instructions, so code built with this flag will continue to work on older processors, though without any of the intended protections. If enabling this flag, it is recommended to ensure the resultant packages are tested against an ARM v8.3+ linux system with known-working Pointer Authentication support so that any breakage caused by this feature is actually detected.
[^footnote-stdenv-ignored-build-platform]: The build platform is ignored because it is a mere implementation detail of the package satisfying the dependency: As a general programming principle, dependencies are always *specified* as interfaces, not concrete implementation.
[^footnote-stdenv-native-dependencies-in-path]: Currently, this means for native builds all dependencies are put on the `PATH`. But in the future that may not be the case for sake of matching cross: the platforms would be assumed to be unique for native and cross builds alike, so only the `depsBuild*` and `nativeBuildInputs` would be added to the `PATH`.
[^footnote-stdenv-propagated-dependencies]: Nix itself already takes a packages transitive dependencies into account, but this propagation ensures nixpkgs-specific infrastructure like [setup hooks](#ssec-setup-hooks) also are run as if it were a propagated dependency.

View File

@ -265,6 +265,8 @@
- The `stackclashprotection` hardening flag has been added, though disabled by default.
- The `pacret` hardening flag has been added, though disabled by default.
- `cargoSha256` in `rustPlatform.buildRustPackage` has been deprecated in favor
of `cargoHash` which supports SRI hashes. See
[buildRustPackage: Compiling Rust applications with Cargo](https://nixos.org/manual/nixpkgs/unstable/#compiling-rust-applications-with-cargo)

View File

@ -32,7 +32,7 @@ if [[ -n "${hardeningEnableMap[fortify3]-}" ]]; then
fi
if (( "${NIX_DEBUG:-0}" >= 1 )); then
declare -a allHardeningFlags=(fortify fortify3 shadowstack stackprotector stackclashprotection pie pic strictoverflow format trivialautovarinit zerocallusedregs)
declare -a allHardeningFlags=(fortify fortify3 shadowstack stackprotector stackclashprotection pacret pie pic strictoverflow format trivialautovarinit zerocallusedregs)
declare -A hardeningDisableMap=()
# Determine which flags were effectively disabled so we can report below.
@ -79,6 +79,10 @@ for flag in "${!hardeningEnableMap[@]}"; do
if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling shadowstack >&2; fi
hardeningCFlagsBefore+=('-fcf-protection=return')
;;
pacret)
if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling pacret >&2; fi
hardeningCFlagsBefore+=('-mbranch-protection=pac-ret')
;;
stackprotector)
if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling stackprotector >&2; fi
hardeningCFlagsBefore+=('-fstack-protector-strong' '--param' 'ssp-buffer-size=4')

View File

@ -437,6 +437,7 @@ pipe ((callFile ./common/builder.nix {}) ({
&& targetPlatform.isx86_64
&& targetPlatform.libc == "glibc"
)) "shadowstack"
++ optional (!(atLeast9 && targetPlatform.isLinux && targetPlatform.isAarch64)) "pacret"
++ optionals (langFortran) [ "fortify" "format" ];
};

View File

@ -143,6 +143,11 @@ let
|| !targetPlatform.isLinux
|| !targetPlatform.isx86_64
) "shadowstack"
++ lib.optional (
(lib.versionOlder release_version "8")
|| !targetPlatform.isAarch64
|| !targetPlatform.isLinux
) "pacret"
++ lib.optional (
(lib.versionOlder release_version "11")
|| (targetPlatform.isAarch64 && (lib.versionOlder release_version "18.1"))

View File

@ -116,6 +116,7 @@ let
"fortify"
"fortify3"
"shadowstack"
"pacret"
"pic"
"pie"
"relro"

View File

@ -18,6 +18,7 @@ derivation ({
hardeningUnsupportedFlags = [
"fortify3"
"shadowstack"
"pacret"
"stackclashprotection"
"trivialautovarinit"
"zerocallusedregs"

View File

@ -323,6 +323,7 @@ let
stdenv = super'.withDefaultHardeningFlags (
super'.stdenv.cc.defaultHardeningFlags ++ [
"shadowstack"
"pacret"
"stackclashprotection"
"trivialautovarinit"
]