Rollup merge of #132259 - mrkajetanp:branch-protection-pauth-lr, r=davidtwco

rustc_codegen_llvm: Add a new 'pc' option to branch-protection

Add a new 'pc' option to -Z branch-protection for aarch64 that enables the use of PC as a diversifier in PAC branch protection code.

When the pauth-lr target feature is enabled in combination with -Z branch-protection=pac-ret,pc, the new 9.5-a instructions (pacibsppc, retaasppc, etc) will be generated.
This commit is contained in:
Matthias Krüger 2024-11-05 20:10:49 +01:00 committed by GitHub
commit c8247c0a19
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 97 additions and 17 deletions

View File

@ -419,7 +419,10 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
if bti {
to_add.push(llvm::CreateAttrString(cx.llcx, "branch-target-enforcement"));
}
if let Some(PacRet { leaf, key }) = pac_ret {
if let Some(PacRet { leaf, pc, key }) = pac_ret {
if pc {
to_add.push(llvm::CreateAttrString(cx.llcx, "branch-protection-pauth-lr"));
}
to_add.push(llvm::CreateAttrStringValue(
cx.llcx,
"sign-return-address",

View File

@ -308,7 +308,13 @@ pub(crate) unsafe fn create_module<'ll>(
"sign-return-address",
pac_ret.is_some().into(),
);
let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, key: PAuthKey::A });
let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, pc: false, key: PAuthKey::A });
llvm::add_module_flag_u32(
llmod,
llvm::ModuleFlagMergeBehavior::Min,
"branch-protection-pauth-lr",
pac_opts.pc.into(),
);
llvm::add_module_flag_u32(
llmod,
llvm::ModuleFlagMergeBehavior::Min,

View File

@ -764,7 +764,7 @@ macro_rules! tracked {
branch_protection,
Some(BranchProtection {
bti: true,
pac_ret: Some(PacRet { leaf: true, key: PAuthKey::B })
pac_ret: Some(PacRet { leaf: true, pc: true, key: PAuthKey::B })
})
);
tracked!(codegen_backend, Some("abc".to_string()));

View File

@ -1320,6 +1320,7 @@ pub enum PAuthKey {
#[derive(Clone, Copy, Hash, Debug, PartialEq)]
pub struct PacRet {
pub leaf: bool,
pub pc: bool,
pub key: PAuthKey,
}

View File

@ -442,8 +442,7 @@ mod desc {
pub(crate) const parse_polonius: &str = "either no value or `legacy` (the default), or `next`";
pub(crate) const parse_stack_protector: &str =
"one of (`none` (default), `basic`, `strong`, or `all`)";
pub(crate) const parse_branch_protection: &str =
"a `,` separated combination of `bti`, `b-key`, `pac-ret`, or `leaf`";
pub(crate) const parse_branch_protection: &str = "a `,` separated combination of `bti`, `pac-ret`, followed by a combination of `pc`, `b-key`, or `leaf`";
pub(crate) const parse_proc_macro_execution_strategy: &str =
"one of supported execution strategies (`same-thread`, or `cross-thread`)";
pub(crate) const parse_remap_path_scope: &str =
@ -1401,7 +1400,7 @@ pub(crate) fn parse_branch_protection(
match opt {
"bti" => slot.bti = true,
"pac-ret" if slot.pac_ret.is_none() => {
slot.pac_ret = Some(PacRet { leaf: false, key: PAuthKey::A })
slot.pac_ret = Some(PacRet { leaf: false, pc: false, key: PAuthKey::A })
}
"leaf" => match slot.pac_ret.as_mut() {
Some(pac) => pac.leaf = true,
@ -1411,6 +1410,10 @@ pub(crate) fn parse_branch_protection(
Some(pac) => pac.key = PAuthKey::B,
_ => return false,
},
"pc" => match slot.pac_ret.as_mut() {
Some(pac) => pac.pc = true,
_ => return false,
},
_ => return false,
};
}

View File

@ -9,11 +9,12 @@ This option is only accepted when targeting AArch64 architectures.
It takes some combination of the following values, separated by a `,`.
- `pac-ret` - Enable pointer authentication for non-leaf functions.
- `pc` - Use PC as a diversifier using PAuthLR instructions
- `leaf` - Enable pointer authentication for all functions, including leaf functions.
- `b-key` - Sign return addresses with key B, instead of the default key A.
- `bti` - Enable branch target identification.
`leaf` and `b-key` are only valid if `pac-ret` was previously specified.
`leaf`, `b-key` and `pc` are only valid if `pac-ret` was previously specified.
For example, `-Z branch-protection=bti,pac-ret,leaf` is valid, but
`-Z branch-protection=bti,leaf,pac-ret` is not.

View File

@ -1,9 +1,13 @@
// Test that PAC instructions are emitted when branch-protection is specified.
//@ revisions: PACRET PAUTHLR_NOP PAUTHLR
//@ assembly-output: emit-asm
//@ compile-flags: --target aarch64-unknown-linux-gnu
//@ compile-flags: -Z branch-protection=pac-ret,leaf
//@ needs-llvm-components: aarch64
//@ compile-flags: --target aarch64-unknown-linux-gnu
//@ [PACRET] compile-flags: -Z branch-protection=pac-ret,leaf
//@ [PAUTHLR_NOP] compile-flags: -Z branch-protection=pac-ret,pc,leaf
//@ [PAUTHLR] compile-flags: -C target-feature=+pauth-lr -Z branch-protection=pac-ret,pc,leaf
//@ min-llvm-version: 19
#![feature(no_core, lang_items)]
#![no_std]
@ -13,8 +17,13 @@
#[lang = "sized"]
trait Sized {}
// CHECK: hint #25
// CHECK: hint #29
// PACRET: hint #25
// PACRET: hint #29
// PAUTHLR_NOP: hint #25
// PAUTHLR_NOP: hint #39
// PAUTHLR_NOP: hint #29
// PAUTHLR: paciasppc
// PAUTHLR: autiasppc
#[no_mangle]
pub fn test() -> u8 {
42

View File

@ -1,11 +1,15 @@
// Test that the correct module flags are emitted with different branch protection flags.
//@ revisions: BTI PACRET LEAF BKEY NONE
//@ revisions: BTI PACRET LEAF BKEY PAUTHLR PAUTHLR_BKEY PAUTHLR_LEAF PAUTHLR_BTI NONE
//@ needs-llvm-components: aarch64
//@ [BTI] compile-flags: -Z branch-protection=bti
//@ [PACRET] compile-flags: -Z branch-protection=pac-ret
//@ [LEAF] compile-flags: -Z branch-protection=pac-ret,leaf
//@ [BKEY] compile-flags: -Z branch-protection=pac-ret,b-key
//@ [PAUTHLR] compile-flags: -Z branch-protection=pac-ret,pc
//@ [PAUTHLR_BKEY] compile-flags: -Z branch-protection=pac-ret,pc,b-key
//@ [PAUTHLR_LEAF] compile-flags: -Z branch-protection=pac-ret,pc,leaf
//@ [PAUTHLR_BTI] compile-flags: -Z branch-protection=bti,pac-ret,pc
//@ compile-flags: --target aarch64-unknown-linux-gnu
//@ min-llvm-version: 19
@ -24,6 +28,7 @@ pub fn test() {}
// BTI: attributes [[ATTR]] = {{.*}} "branch-target-enforcement"
// BTI: !"branch-target-enforcement", i32 1
// BTI: !"sign-return-address", i32 0
// BTI: !"branch-protection-pauth-lr", i32 0
// BTI: !"sign-return-address-all", i32 0
// BTI: !"sign-return-address-with-bkey", i32 0
@ -31,6 +36,7 @@ pub fn test() {}
// PACRET-SAME: "sign-return-address-key"="a_key"
// PACRET: !"branch-target-enforcement", i32 0
// PACRET: !"sign-return-address", i32 1
// PACRET: !"branch-protection-pauth-lr", i32 0
// PACRET: !"sign-return-address-all", i32 0
// PACRET: !"sign-return-address-with-bkey", i32 0
@ -38,6 +44,7 @@ pub fn test() {}
// LEAF-SAME: "sign-return-address-key"="a_key"
// LEAF: !"branch-target-enforcement", i32 0
// LEAF: !"sign-return-address", i32 1
// LEAF: !"branch-protection-pauth-lr", i32 0
// LEAF: !"sign-return-address-all", i32 1
// LEAF: !"sign-return-address-with-bkey", i32 0
@ -45,9 +52,42 @@ pub fn test() {}
// BKEY-SAME: "sign-return-address-key"="b_key"
// BKEY: !"branch-target-enforcement", i32 0
// BKEY: !"sign-return-address", i32 1
// BKEY: !"branch-protection-pauth-lr", i32 0
// BKEY: !"sign-return-address-all", i32 0
// BKEY: !"sign-return-address-with-bkey", i32 1
// PAUTHLR: attributes [[ATTR]] = {{.*}} "sign-return-address"="non-leaf"
// PAUTHLR-SAME: "sign-return-address-key"="a_key"
// PAUTHLR: !"branch-target-enforcement", i32 0
// PAUTHLR: !"sign-return-address", i32 1
// PAUTHLR: !"branch-protection-pauth-lr", i32 1
// PAUTHLR: !"sign-return-address-all", i32 0
// PAUTHLR: !"sign-return-address-with-bkey", i32 0
// PAUTHLR_BKEY: attributes [[ATTR]] = {{.*}} "sign-return-address"="non-leaf"
// PAUTHLR_BKEY-SAME: "sign-return-address-key"="b_key"
// PAUTHLR_BKEY: !"branch-target-enforcement", i32 0
// PAUTHLR_BKEY: !"sign-return-address", i32 1
// PAUTHLR_BKEY: !"branch-protection-pauth-lr", i32 1
// PAUTHLR_BKEY: !"sign-return-address-all", i32 0
// PAUTHLR_BKEY: !"sign-return-address-with-bkey", i32 1
// PAUTHLR_LEAF: attributes [[ATTR]] = {{.*}} "sign-return-address"="all"
// PAUTHLR_LEAF-SAME: "sign-return-address-key"="a_key"
// PAUTHLR_LEAF: !"branch-target-enforcement", i32 0
// PAUTHLR_LEAF: !"sign-return-address", i32 1
// PAUTHLR_LEAF: !"branch-protection-pauth-lr", i32 1
// PAUTHLR_LEAF: !"sign-return-address-all", i32 1
// PAUTHLR_LEAF: !"sign-return-address-with-bkey", i32 0
// PAUTHLR_BTI: attributes [[ATTR]] = {{.*}} "sign-return-address"="non-leaf"
// PAUTHLR_BTI-SAME: "sign-return-address-key"="a_key"
// PAUTHLR_BTI: !"branch-target-enforcement", i32 1
// PAUTHLR_BTI: !"sign-return-address", i32 1
// PAUTHLR_BTI: !"branch-protection-pauth-lr", i32 1
// PAUTHLR_BTI: !"sign-return-address-all", i32 0
// PAUTHLR_BTI: !"sign-return-address-with-bkey", i32 0
// NONE-NOT: branch-target-enforcement
// NONE-NOT: sign-return-address
// NONE-NOT: sign-return-address-all

View File

@ -1,7 +1,7 @@
// `-Z branch protection` is an unstable compiler feature which adds pointer-authentication
// code (PAC), a useful hashing measure for verifying that pointers have not been modified.
// This test checks that compilation and execution is successful when this feature is activated,
// with some of its possible extra arguments (bti, pac-ret, leaf).
// with some of its possible extra arguments (bti, pac-ret, pc, leaf, b-key).
// See https://github.com/rust-lang/rust/pull/88354
//@ only-aarch64
@ -25,4 +25,16 @@ fn main() {
llvm_ar().obj_to_ar().output_input("libtest.a", &obj_file).run();
rustc().arg("-Zbranch-protection=bti,pac-ret,leaf").input("test.rs").run();
run("test");
// FIXME: +pc was only recently added to LLVM
// cc().arg("-v")
// .arg("-c")
// .out_exe("test")
// .input("test.c")
// .arg("-mbranch-protection=bti+pac-ret+pc+leaf")
// .run();
// let obj_file = if is_msvc() { "test.obj" } else { "test" };
// llvm_ar().obj_to_ar().output_input("libtest.a", &obj_file).run();
// rustc().arg("-Zbranch-protection=bti,pac-ret,pc,leaf").input("test.rs").run();
// run("test");
}

View File

@ -1,2 +1,2 @@
error: incorrect value `leaf` for unstable option `branch-protection` - a `,` separated combination of `bti`, `b-key`, `pac-ret`, or `leaf` was expected
error: incorrect value `leaf` for unstable option `branch-protection` - a `,` separated combination of `bti`, `pac-ret`, followed by a combination of `pc`, `b-key`, or `leaf` was expected

View File

@ -0,0 +1,2 @@
error: incorrect value `pc` for unstable option `branch-protection` - a `,` separated combination of `bti`, `pac-ret`, followed by a combination of `pc`, `b-key`, or `leaf` was expected

View File

@ -1,7 +1,10 @@
//@ revisions: BADFLAGS BADTARGET
//@ revisions: BADFLAGS BADFLAGSPC BADTARGET
//@ [BADFLAGS] compile-flags: --target=aarch64-unknown-linux-gnu -Zbranch-protection=leaf
//@ [BADFLAGS] check-fail
//@ [BADFLAGS] needs-llvm-components: aarch64
//@ [BADFLAGSPC] compile-flags: --target=aarch64-unknown-linux-gnu -Zbranch-protection=pc
//@ [BADFLAGSPC] check-fail
//@ [BADFLAGSPC] needs-llvm-components: aarch64
//@ [BADTARGET] compile-flags: --target=x86_64-unknown-linux-gnu -Zbranch-protection=bti
//@ [BADTARGET] check-fail
//@ [BADTARGET] needs-llvm-components: x86