Skip to content

Commit

Permalink
Auto merge of rust-lang#93516 - nagisa:branch-protection, r=cjgillot
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
bors authored and ehuss committed Mar 3, 2022
1 parent 150cc0c commit 7eda329
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 58 deletions.
60 changes: 30 additions & 30 deletions compiler/rustc_codegen_llvm/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,36 +269,36 @@ pub unsafe fn create_module<'ll>(
}
}

if sess.target.arch == "aarch64" {
let BranchProtection { bti, pac_ret: pac } = sess.opts.debugging_opts.branch_protection;

llvm::LLVMRustAddModuleFlag(
llmod,
llvm::LLVMModFlagBehavior::Error,
"branch-target-enforcement\0".as_ptr().cast(),
bti.into(),
);

llvm::LLVMRustAddModuleFlag(
llmod,
llvm::LLVMModFlagBehavior::Error,
"sign-return-address\0".as_ptr().cast(),
pac.is_some().into(),
);
let pac_opts = pac.unwrap_or(PacRet { leaf: false, key: PAuthKey::A });
llvm::LLVMRustAddModuleFlag(
llmod,
llvm::LLVMModFlagBehavior::Error,
"sign-return-address-all\0".as_ptr().cast(),
pac_opts.leaf.into(),
);
let is_bkey: bool = pac_opts.key != PAuthKey::A;
llvm::LLVMRustAddModuleFlag(
llmod,
llvm::LLVMModFlagBehavior::Error,
"sign-return-address-with-bkey\0".as_ptr().cast(),
is_bkey.into(),
);
if let Some(BranchProtection { bti, pac_ret }) = sess.opts.debugging_opts.branch_protection {
if sess.target.arch != "aarch64" {
sess.err("-Zbranch-protection is only supported on aarch64");
} else {
llvm::LLVMRustAddModuleFlag(
llmod,
llvm::LLVMModFlagBehavior::Error,
"branch-target-enforcement\0".as_ptr().cast(),
bti.into(),
);
llvm::LLVMRustAddModuleFlag(
llmod,
llvm::LLVMModFlagBehavior::Error,
"sign-return-address\0".as_ptr().cast(),
pac_ret.is_some().into(),
);
let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, key: PAuthKey::A });
llvm::LLVMRustAddModuleFlag(
llmod,
llvm::LLVMModFlagBehavior::Error,
"sign-return-address-all\0".as_ptr().cast(),
pac_opts.leaf.into(),
);
llvm::LLVMRustAddModuleFlag(
llmod,
llvm::LLVMModFlagBehavior::Error,
"sign-return-address-with-bkey\0".as_ptr().cast(),
u32::from(pac_opts.key == PAuthKey::B),
);
}
}

// Pass on the control-flow protection flags to LLVM (equivalent to `-fcf-protection` in Clang).
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_interface/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -721,7 +721,10 @@ fn test_debugging_options_tracking_hash() {
tracked!(binary_dep_depinfo, true);
tracked!(
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!(codegen_backend, Some("abc".to_string()));
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_session/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#![feature(derive_default_enum)]
#![feature(min_specialization)]
#![feature(once_cell)]
#![feature(option_get_or_insert_default)]
#![recursion_limit = "256"]
#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]

Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_session/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -984,9 +984,10 @@ mod parse {
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 {
Some(s) => {
let slot = slot.get_or_insert_default();
for opt in s.split(',') {
match opt {
"bti" => slot.bti = true,
Expand Down Expand Up @@ -1161,7 +1162,7 @@ options! {
(default: no)"),
borrowck: String = ("migrate".to_string(), parse_string, [UNTRACKED],
"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"),
cf_protection: CFProtection = (CFProtection::None, parse_cfprotection, [TRACKED],
"instrument control-flow architecture protection"),
Expand Down
53 changes: 29 additions & 24 deletions src/test/codegen/branch-protection.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// 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
// needs-llvm-components: aarch64
// [bti] compile-flags: -Z branch-protection=bti
// [pac-ret] compile-flags: -Z branch-protection=pac-ret
// [leaf] compile-flags: -Z branch-protection=pac-ret,leaf
// [b-key] compile-flags: -Z branch-protection=pac-ret,b-key
// [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
// compile-flags: --target aarch64-unknown-linux-gnu

#![crate_type = "lib"]
Expand All @@ -20,22 +20,27 @@ trait Sized { }
pub fn test() {
}

// bti: !"branch-target-enforcement", i32 1
// bti: !"sign-return-address", i32 0
// bti: !"sign-return-address-all", i32 0
// bti: !"sign-return-address-with-bkey", i32 0

// pac-ret: !"branch-target-enforcement", i32 0
// pac-ret: !"sign-return-address", i32 1
// pac-ret: !"sign-return-address-all", i32 0
// pac-ret: !"sign-return-address-with-bkey", i32 0

// leaf: !"branch-target-enforcement", i32 0
// leaf: !"sign-return-address", i32 1
// leaf: !"sign-return-address-all", i32 1
// leaf: !"sign-return-address-with-bkey", i32 0

// b-key: !"branch-target-enforcement", i32 0
// b-key: !"sign-return-address", i32 1
// b-key: !"sign-return-address-all", i32 0
// b-key: !"sign-return-address-with-bkey", i32 1
// BTI: !"branch-target-enforcement", i32 1
// BTI: !"sign-return-address", i32 0
// BTI: !"sign-return-address-all", i32 0
// BTI: !"sign-return-address-with-bkey", i32 0

// PACRET: !"branch-target-enforcement", i32 0
// PACRET: !"sign-return-address", i32 1
// PACRET: !"sign-return-address-all", i32 0
// PACRET: !"sign-return-address-with-bkey", i32 0

// LEAF: !"branch-target-enforcement", i32 0
// LEAF: !"sign-return-address", i32 1
// LEAF: !"sign-return-address-all", i32 1
// LEAF: !"sign-return-address-with-bkey", i32 0

// BKEY: !"branch-target-enforcement", i32 0
// BKEY: !"sign-return-address", i32 1
// BKEY: !"sign-return-address-all", i32 0
// 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
error: -Zbranch-protection is only supported on aarch64

error: aborting due to previous error

Original file line number Diff line number Diff line change
@@ -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 { }

0 comments on commit 7eda329

Please sign in to comment.