Skip to content

Commit 17ad6d3

Browse files
committed
[PAC] Propagate function pointer type discrimination through get_fn_addr call sites
Fill in function pointer type discriminators logic across remaining `get_fn_addr` call sites and explicitly avoid applying it where discrimination is not meaningful. Some uses of `get_fn_addr` are intentionally left unsigned, including the EH personality function, entry wrappers, and compiler-generated Rust ABI shims.
1 parent 589c793 commit 17ad6d3

4 files changed

Lines changed: 84 additions & 23 deletions

File tree

compiler/rustc_codegen_llvm/src/context.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -973,6 +973,16 @@ impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
973973

974974
let tcx = self.tcx;
975975
let llfn = match tcx.lang_items().eh_personality() {
976+
// We intentionally do NOT apply pointer authentication (and/or function type
977+
// discriminators to the EH personality function).
978+
//
979+
// Although `get_fn_addr` normally produces a signed function pointer for
980+
// externally-callable functions, the EH personality is not an indirect call
981+
// target in the SSA sense. Instead, it is a compile-time constant attached to
982+
// the Function object (via LLVM's `setPersonalityFn`) and consumed only by
983+
// exception handling metadata generation (landing pads / unwind tables).
984+
// LLVM never loads or invokes the personality via a function pointer value;
985+
// it is not part of the program's call graph or data flow.
976986
Some(def_id) if name.is_none() => self.get_fn_addr(
977987
ty::Instance::expect_resolve(
978988
tcx,
@@ -981,7 +991,7 @@ impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
981991
ty::List::empty(),
982992
DUMMY_SP,
983993
),
984-
tcx.sess.pointer_authentication_functions(),
994+
None,
985995
),
986996
_ => {
987997
let name = name.unwrap_or("rust_eh_personality");

compiler/rustc_codegen_ssa/src/base.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -493,8 +493,11 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
493493
// We want to create the wrapper only when the codegen unit is the primary one
494494
return None;
495495
}
496-
497-
let main_llfn = cx.get_fn_addr(instance, cx.sess().pointer_authentication_functions());
496+
// No function pointer signing / type discriminator is needed here. Although `get_fn_addr` is
497+
// used to obtain function pointers, both the user's `main` and `LangItem::Start` use the Rust
498+
// ABI (currently pointer authentication is only supported for C/System ABI). The same applies
499+
// to the logic in `create_entry_fn` further below.
500+
let main_llfn = cx.get_fn_addr(instance, None);
498501

499502
let entry_fn = create_entry_fn::<Bx>(cx, main_llfn, main_def_id, entry_type);
500503
return Some(entry_fn);
@@ -555,8 +558,8 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
555558
cx.tcx().mk_args(&[main_ret_ty.into()]),
556559
DUMMY_SP,
557560
);
558-
let start_fn =
559-
cx.get_fn_addr(start_instance, cx.sess().pointer_authentication_functions());
561+
562+
let start_fn = cx.get_fn_addr(start_instance, None);
560563

561564
let i8_ty = cx.type_i8();
562565
let arg_sigpipe = bx.const_u8(sigpipe);

compiler/rustc_codegen_ssa/src/common.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
use rustc_hir::LangItem;
44
use rustc_hir::attrs::PeImportNameType;
5+
use rustc_middle::ptrauth::{
6+
build_fn_ptr_type_discriminator_input_from_instance, compute_fn_ptr_type_discriminator,
7+
};
58
use rustc_middle::ty::layout::TyAndLayout;
69
use rustc_middle::ty::{self, Instance, TyCtxt};
710
use rustc_middle::{bug, mir, span_bug};
@@ -117,11 +120,19 @@ pub(crate) fn build_langcall<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
117120
let tcx = bx.tcx();
118121
let def_id = tcx.require_lang_item(li, span);
119122
let instance = ty::Instance::mono(tcx, def_id);
120-
(
121-
bx.fn_abi_of_instance(instance, ty::List::empty()),
122-
bx.get_fn_addr(instance, tcx.sess.pointer_authentication_functions()),
123-
instance,
124-
)
123+
let mut schema = bx.sess().pointer_authentication_functions().clone();
124+
125+
if let Some(ref mut s) = schema
126+
&& bx.sess().pointer_authentication_fn_ptr_type_discrimination()
127+
{
128+
// It is unlikely that any of LangItem will follow the extern C/System ABI, but it future
129+
// proofs the implementation.
130+
let disc_input = build_fn_ptr_type_discriminator_input_from_instance(tcx, instance);
131+
let disc = compute_fn_ptr_type_discriminator(tcx, &disc_input) as u16;
132+
133+
s.constant_discriminator = disc;
134+
}
135+
(bx.fn_abi_of_instance(instance, ty::List::empty()), bx.get_fn_addr(instance, schema), instance)
125136
}
126137

127138
pub(crate) fn shift_mask_val<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(

compiler/rustc_codegen_ssa/src/mir/block.rs

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ use rustc_hir::attrs::AttributeKind;
1111
use rustc_hir::lang_items::LangItem;
1212
use rustc_lint_defs::builtin::TAIL_CALL_TRACK_CALLER;
1313
use rustc_middle::mir::{self, AssertKind, InlineAsmMacro, SwitchTargets, UnwindTerminateReason};
14+
use rustc_middle::ptrauth::{
15+
build_fn_ptr_type_discriminator_input_from_instance, compute_fn_ptr_type_discriminator,
16+
};
1417
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
1518
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
1619
use rustc_middle::ty::{self, Instance, Ty, TypeVisitableExt};
@@ -684,12 +687,25 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
684687
virtual_drop,
685688
)
686689
}
687-
_ => (
688-
false,
689-
bx.get_fn_addr(drop_fn, bx.sess().pointer_authentication_functions()),
690-
bx.fn_abi_of_instance(drop_fn, ty::List::empty()),
691-
drop_fn,
692-
),
690+
_ => {
691+
let mut schema = bx.sess().pointer_authentication_functions().clone();
692+
693+
if let Some(ref mut s) = schema
694+
&& bx.sess().pointer_authentication_fn_ptr_type_discrimination()
695+
{
696+
let disc_input =
697+
build_fn_ptr_type_discriminator_input_from_instance(bx.tcx(), drop_fn);
698+
let disc = compute_fn_ptr_type_discriminator(bx.tcx(), &disc_input) as u16;
699+
700+
s.constant_discriminator = disc;
701+
}
702+
(
703+
false,
704+
bx.get_fn_addr(drop_fn, schema),
705+
bx.fn_abi_of_instance(drop_fn, ty::List::empty()),
706+
drop_fn,
707+
)
708+
}
693709
};
694710

695711
// We generate a null check for the drop_fn. This saves a bunch of relocations being
@@ -1102,13 +1118,22 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
11021118
)
11031119
.unwrap();
11041120

1105-
(
1106-
None,
1107-
Some(bx.get_fn_addr(
1121+
let mut schema = bx.sess().pointer_authentication_functions().clone();
1122+
1123+
if let Some(ref mut s) = schema
1124+
&& bx.sess().pointer_authentication_fn_ptr_type_discrimination()
1125+
{
1126+
let disc_input = build_fn_ptr_type_discriminator_input_from_instance(
1127+
bx.tcx(),
11081128
instance,
1109-
bx.sess().pointer_authentication_functions(),
1110-
)),
1111-
)
1129+
);
1130+
let disc =
1131+
compute_fn_ptr_type_discriminator(bx.tcx(), &disc_input) as u16;
1132+
1133+
s.constant_discriminator = disc;
1134+
};
1135+
1136+
(None, Some(bx.get_fn_addr(instance, schema)))
11121137
}
11131138
_ => (Some(instance), None),
11141139
}
@@ -1422,7 +1447,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
14221447

14231448
let fn_ptr = match (instance, llfn) {
14241449
(Some(instance), None) => {
1425-
bx.get_fn_addr(instance, bx.sess().pointer_authentication_functions())
1450+
let mut schema = bx.sess().pointer_authentication_functions().clone();
1451+
1452+
if let Some(ref mut s) = schema
1453+
&& bx.sess().pointer_authentication_fn_ptr_type_discrimination()
1454+
{
1455+
let disc_input =
1456+
build_fn_ptr_type_discriminator_input_from_instance(bx.tcx(), instance);
1457+
let disc = compute_fn_ptr_type_discriminator(bx.tcx(), &disc_input) as u16;
1458+
1459+
s.constant_discriminator = disc;
1460+
}
1461+
1462+
bx.get_fn_addr(instance, schema)
14261463
}
14271464
(_, Some(llfn)) => llfn,
14281465
_ => span_bug!(fn_span, "no instance or llfn for call"),

0 commit comments

Comments
 (0)