Auto merge of #93516 - nagisa:branch-protection, r=cjgillot

No branch protection metadata unless enabled

Even if we emit metadata disabling branch protection, this metadata may
conflict with other modules (e.g. during LTO) that have different branch
protection metadata set.

This is an unstable flag and feature, so ideally the flag not being
specified should act as if the feature wasn't implemented in the first
place.

Additionally this PR also ensures we emit an error if
`-Zbranch-protection` is set on targets other than the supported
aarch64. For now the error is being output from codegen, but ideally it
should be moved to earlier in the pipeline before stabilization.
This commit is contained in:
bors 2022-02-26 21:53:03 +00:00
commit 761e888485
8 changed files with 82 additions and 55 deletions

View file

@ -269,36 +269,36 @@ pub unsafe fn create_module<'ll>(
} }
} }
if sess.target.arch == "aarch64" { if let Some(BranchProtection { bti, pac_ret }) = sess.opts.debugging_opts.branch_protection {
let BranchProtection { bti, pac_ret: pac } = sess.opts.debugging_opts.branch_protection; if sess.target.arch != "aarch64" {
sess.err("-Zbranch-protection is only supported on aarch64");
llvm::LLVMRustAddModuleFlag( } else {
llmod, llvm::LLVMRustAddModuleFlag(
llvm::LLVMModFlagBehavior::Error, llmod,
"branch-target-enforcement\0".as_ptr().cast(), llvm::LLVMModFlagBehavior::Error,
bti.into(), "branch-target-enforcement\0".as_ptr().cast(),
); bti.into(),
);
llvm::LLVMRustAddModuleFlag( llvm::LLVMRustAddModuleFlag(
llmod, llmod,
llvm::LLVMModFlagBehavior::Error, llvm::LLVMModFlagBehavior::Error,
"sign-return-address\0".as_ptr().cast(), "sign-return-address\0".as_ptr().cast(),
pac.is_some().into(), pac_ret.is_some().into(),
); );
let pac_opts = pac.unwrap_or(PacRet { leaf: false, key: PAuthKey::A }); let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, key: PAuthKey::A });
llvm::LLVMRustAddModuleFlag( llvm::LLVMRustAddModuleFlag(
llmod, llmod,
llvm::LLVMModFlagBehavior::Error, llvm::LLVMModFlagBehavior::Error,
"sign-return-address-all\0".as_ptr().cast(), "sign-return-address-all\0".as_ptr().cast(),
pac_opts.leaf.into(), pac_opts.leaf.into(),
); );
let is_bkey: bool = pac_opts.key != PAuthKey::A; llvm::LLVMRustAddModuleFlag(
llvm::LLVMRustAddModuleFlag( llmod,
llmod, llvm::LLVMModFlagBehavior::Error,
llvm::LLVMModFlagBehavior::Error, "sign-return-address-with-bkey\0".as_ptr().cast(),
"sign-return-address-with-bkey\0".as_ptr().cast(), u32::from(pac_opts.key == PAuthKey::B),
is_bkey.into(), );
); }
} }
// Pass on the control-flow protection flags to LLVM (equivalent to `-fcf-protection` in Clang). // Pass on the control-flow protection flags to LLVM (equivalent to `-fcf-protection` in Clang).

View file

@ -721,7 +721,10 @@ fn test_debugging_options_tracking_hash() {
tracked!(binary_dep_depinfo, true); tracked!(binary_dep_depinfo, true);
tracked!( tracked!(
branch_protection, branch_protection,
BranchProtection { bti: true, pac_ret: Some(PacRet { leaf: true, key: PAuthKey::B }) } Some(BranchProtection {
bti: true,
pac_ret: Some(PacRet { leaf: true, key: PAuthKey::B })
})
); );
tracked!(chalk, true); tracked!(chalk, true);
tracked!(codegen_backend, Some("abc".to_string())); tracked!(codegen_backend, Some("abc".to_string()));

View file

@ -3,6 +3,7 @@
#![feature(let_else)] #![feature(let_else)]
#![feature(min_specialization)] #![feature(min_specialization)]
#![feature(once_cell)] #![feature(once_cell)]
#![feature(option_get_or_insert_default)]
#![recursion_limit = "256"] #![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)] #![allow(rustc::potential_query_instability)]

View file

@ -978,9 +978,10 @@ mod parse {
true true
} }
crate fn parse_branch_protection(slot: &mut BranchProtection, v: Option<&str>) -> bool { crate fn parse_branch_protection(slot: &mut Option<BranchProtection>, v: Option<&str>) -> bool {
match v { match v {
Some(s) => { Some(s) => {
let slot = slot.get_or_insert_default();
for opt in s.split(',') { for opt in s.split(',') {
match opt { match opt {
"bti" => slot.bti = true, "bti" => slot.bti = true,
@ -1155,7 +1156,7 @@ options! {
(default: no)"), (default: no)"),
borrowck: String = ("migrate".to_string(), parse_string, [UNTRACKED], borrowck: String = ("migrate".to_string(), parse_string, [UNTRACKED],
"select which borrowck is used (`mir` or `migrate`) (default: `migrate`)"), "select which borrowck is used (`mir` or `migrate`) (default: `migrate`)"),
branch_protection: BranchProtection = (BranchProtection::default(), parse_branch_protection, [TRACKED], branch_protection: Option<BranchProtection> = (None, parse_branch_protection, [TRACKED],
"set options for branch target identification and pointer authentication on AArch64"), "set options for branch target identification and pointer authentication on AArch64"),
cf_protection: CFProtection = (CFProtection::None, parse_cfprotection, [TRACKED], cf_protection: CFProtection = (CFProtection::None, parse_cfprotection, [TRACKED],
"instrument control-flow architecture protection"), "instrument control-flow architecture protection"),

View file

@ -1,12 +1,12 @@
// Test that the correct module flags are emitted with different branch protection flags. // Test that the correct module flags are emitted with different branch protection flags.
// revisions: bti pac-ret leaf b-key // revisions: BTI PACRET LEAF BKEY NONE
// min-llvm-version: 12.0.0 // min-llvm-version: 12.0.0
// needs-llvm-components: aarch64 // needs-llvm-components: aarch64
// [bti] compile-flags: -Z branch-protection=bti // [BTI] compile-flags: -Z branch-protection=bti
// [pac-ret] compile-flags: -Z branch-protection=pac-ret // [PACRET] compile-flags: -Z branch-protection=pac-ret
// [leaf] compile-flags: -Z branch-protection=pac-ret,leaf // [LEAF] compile-flags: -Z branch-protection=pac-ret,leaf
// [b-key] compile-flags: -Z branch-protection=pac-ret,b-key // [BKEY] compile-flags: -Z branch-protection=pac-ret,b-key
// compile-flags: --target aarch64-unknown-linux-gnu // compile-flags: --target aarch64-unknown-linux-gnu
#![crate_type = "lib"] #![crate_type = "lib"]
@ -20,22 +20,27 @@ trait Sized { }
pub fn test() { pub fn test() {
} }
// bti: !"branch-target-enforcement", i32 1 // BTI: !"branch-target-enforcement", i32 1
// bti: !"sign-return-address", i32 0 // BTI: !"sign-return-address", i32 0
// bti: !"sign-return-address-all", i32 0 // BTI: !"sign-return-address-all", i32 0
// bti: !"sign-return-address-with-bkey", i32 0 // BTI: !"sign-return-address-with-bkey", i32 0
// pac-ret: !"branch-target-enforcement", i32 0 // PACRET: !"branch-target-enforcement", i32 0
// pac-ret: !"sign-return-address", i32 1 // PACRET: !"sign-return-address", i32 1
// pac-ret: !"sign-return-address-all", i32 0 // PACRET: !"sign-return-address-all", i32 0
// pac-ret: !"sign-return-address-with-bkey", i32 0 // PACRET: !"sign-return-address-with-bkey", i32 0
// leaf: !"branch-target-enforcement", i32 0 // LEAF: !"branch-target-enforcement", i32 0
// leaf: !"sign-return-address", i32 1 // LEAF: !"sign-return-address", i32 1
// leaf: !"sign-return-address-all", i32 1 // LEAF: !"sign-return-address-all", i32 1
// leaf: !"sign-return-address-with-bkey", i32 0 // LEAF: !"sign-return-address-with-bkey", i32 0
// b-key: !"branch-target-enforcement", i32 0 // BKEY: !"branch-target-enforcement", i32 0
// b-key: !"sign-return-address", i32 1 // BKEY: !"sign-return-address", i32 1
// b-key: !"sign-return-address-all", i32 0 // BKEY: !"sign-return-address-all", i32 0
// b-key: !"sign-return-address-with-bkey", i32 1 // BKEY: !"sign-return-address-with-bkey", i32 1
// NONE-NOT: branch-target-enforcement
// NONE-NOT: sign-return-address
// NONE-NOT: sign-return-address-all
// NONE-NOT: sign-return-address-with-bkey

View file

@ -0,0 +1,4 @@
error: -Zbranch-protection is only supported on aarch64
error: aborting due to previous error

View file

@ -1 +1,14 @@
// compile-flags: -Z branch-protection=leaf // revisions: BADFLAGS BADTARGET
// [BADFLAGS] compile-flags: --target=aarch64-unknown-linux-gnu -Zbranch-protection=leaf
// [BADFLAGS] check-fail
// [BADFLAGS] needs-llvm-components: aarch64
// [BADTARGET] compile-flags: --target=x86_64-unknown-linux-gnu -Zbranch-protection=bti
// [BADTARGET] build-fail
// [BADTARGET] needs-llvm-components: x86
#![crate_type = "lib"]
#![feature(no_core, lang_items)]
#![no_core]
#[lang="sized"]
trait Sized { }