Skip to content

Commit

Permalink
Stop emitting CET prologues for naked functions
Browse files Browse the repository at this point in the history
We can apply nocf_check as a hack for now.
  • Loading branch information
workingjubilee committed Jul 7, 2022
1 parent 8824d13 commit 92174f9
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 1 deletion.
4 changes: 4 additions & 0 deletions compiler/rustc_codegen_llvm/src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,10 @@ pub fn from_fn_attrs<'ll, 'tcx>(
}
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
to_add.push(AttributeKind::Naked.create_attr(cx.llcx));
// HACK(jubilee): "indirect branch tracking" works by attaching prologues to functions.
// And it is a module-level attribute, so the alternative is pulling naked functions into new LLVM modules.
// Otherwise LLVM's "naked" functions come with endbr prefixes per https://github.com/rust-lang/rust/issues/98768
to_add.push(AttributeKind::NoCfCheck.create_attr(cx.llcx));
}
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::ALLOCATOR) {
// apply to return place instead of function (unlike all other attributes applied in this function)
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_llvm/src/llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ pub enum AttributeKind {
StackProtect = 32,
NoUndef = 33,
SanitizeMemTag = 34,
NoCfCheck = 35,
}

/// LLVMIntPredicate
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ enum LLVMRustAttribute {
StackProtect = 32,
NoUndef = 33,
SanitizeMemTag = 34,
NoCfCheck = 35,
};

typedef struct OpaqueRustString *RustStringRef;
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,8 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
return Attribute::NoAlias;
case NoCapture:
return Attribute::NoCapture;
case NoCfCheck:
return Attribute::NoCfCheck;
case NoInline:
return Attribute::NoInline;
case NonNull:
Expand Down
24 changes: 24 additions & 0 deletions src/test/assembly/x86_64-naked-fn-no-cet-prolog.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// compile-flags: -C no-prepopulate-passes -Zcf-protection=full
// assembly-output: emit-asm
// needs-asm-support
// only-x86_64

#![crate_type = "lib"]
#![feature(naked_functions)]
use std::arch::asm;

// The problem at hand: Rust has adopted a fairly strict meaning for "naked functions",
// meaning "no prologue whatsoever, no, really, not one instruction."
// Unfortunately, x86's control-flow enforcement, specifically indirect branch protection,
// works by using an instruction for each possible landing site,
// and LLVM implements this via making sure of that.
#[no_mangle]
#[naked]
pub unsafe extern "sysv64" fn will_halt() -> ! {
// CHECK-NOT: endbr{{32|64}}
// CHECK: hlt
asm!("hlt", options(noreturn))
}

// what about aarch64?
// "branch-protection"=false
2 changes: 1 addition & 1 deletion src/test/codegen/naked-noinline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ pub unsafe fn g() {
f();
}

// CHECK: attributes [[ATTR]] = { naked noinline{{.*}} }
// CHECK: attributes [[ATTR]] = { naked{{.*}}noinline{{.*}} }

0 comments on commit 92174f9

Please sign in to comment.