[WIP] 6 - Propagate discriminator logic through remaining get_fn_ptr calls sites#159084
[WIP] 6 - Propagate discriminator logic through remaining get_fn_ptr calls sites#159084jchlanda wants to merge 7 commits into
get_fn_ptr calls sites#159084Conversation
This comment has been minimized.
This comment has been minimized.
6f06f96 to
17ad6d3
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
17ad6d3 to
9a55906
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
9a55906 to
b331394
Compare
This comment has been minimized.
This comment has been minimized.
b331394 to
d42d5cf
Compare
This patch implements Rust's equivalent of Clang's function pointer type discriminator computation used in pointer authentication. Compatibility with Clang is a primary goal. The discriminator produced for a given external "C" function type must match the value computed by Clang so that function pointers can be exchanged safely between Rust and C code while preserving pointer authentication semantics. The implementation mirrors Clang's behavior in `ASTContext::encodeTypeForFunctionPointerAuth`, ensuring that identical C-compatible function types produce identical discriminators. See: <https://clang.llvm.org/doxygen/ASTContext_8cpp.html#abb1375e068e807917527842d05cadea3>.
d42d5cf to
aa26645
Compare
| // the Function object (via LLVM's `setPersonalityFn`) and consumed only by | ||
| // exception handling metadata generation (landing pads / unwind tables). | ||
| // LLVM never loads or invokes the personality via a function pointer value; | ||
| // it is not part of the program's call graph or data flow. |
There was a problem hiding this comment.
Could you please refer me to a test covering this? BTW, LLVM does sign personality value with a special signing schema late in backend when it's emitted - see llvm/llvm-project#119361.
I suppose that no rust-side handling special is needed here, I'm just wondering if this works as expected end-to-end. Like, when compiling to asm/obj (not just IR), do we expect to end up with a signed personality pointer (with discriminator 0x7EAD) in .data.DW.ref.__gxx_personality_v0 section or smth like this?
There was a problem hiding this comment.
This is slightly different. This code makes sure that we don't generate pathological IR which contains function signatures with eh personality wrapped in ptrauth themselves. Something looking like:
define void @func_that_can_panic(ptr align 8 %arg) unnamed_addr #1 personality ptrauth (ptr @rust_eh_personality, i32 0) {
...Looking at the upstream LLVM pr, it seems that from the IR perspective the only necessary thing is to provide "ptrauth-sign-personality" module flag, and the rest is handled by the backend at the object file emission time. This should be already happening for us.
I've run a simple rust program that panics and then inspected the binary.
llvm-readelf -sW ./eh_pers_rust | grep DW.ref.rust_eh_personality 2159: 000000000009f2f0 8 OBJECT LOCAL HIDDEN 26 DW.ref.rust_eh_personalityIt lives in the data section:
llvm-readelf -SW ./eh_pers_rust | grep '\[26\]' [26] .data PROGBITS 000000000009e880 06e880 000ad8 00 WA 0 0 16And I can see the desired discriminator (0x7ead) at the correct address (0x9f2f0):
llvm-readelf --hex-dump=.data ./eh_pers_rust | grep -A2 -B2 9f2f00x0009f2d0 00000000 00000000 03000000 00000000 ................
0x0009f2e0 00000000 00000000 00000000 00000000 ................
0x0009f2f0 00000000 ad7e0080 00000000 00000000 .....~..........
0x0009f300 00000000 00000000 00000000 00000000 ................
0x0009f310 00000000 00000000 00000000 00000000 ................There was a problem hiding this comment.
And we check for the correct rust_eh_personality spelling in: eec0477#diff-de25e464708ec5b026aee0d418419886c27fa316fe12808e6519d8f47fc4fea0R11
There was a problem hiding this comment.
Thanks! So if backend handles all this for us as expected - all is OK :)
| args, | ||
| ty::ClosureKind::FnOnce, | ||
| ); | ||
| assert!( |
There was a problem hiding this comment.
Is this assertion intended to be included in this PR or in the previous PR 5 (which contains changes to the code right after the assertion)?
There was a problem hiding this comment.
Good spot, moved over to the previous one.
| // used to obtain function pointers, both the user's `main` and `LangItem::Start` use the Rust | ||
| // ABI (currently pointer authentication is only supported for C/System ABI). The same applies | ||
| // to the logic in `create_entry_fn` further below. | ||
| let main_llfn = cx.get_fn_addr(instance, None); |
There was a problem hiding this comment.
Nit: maybe add some comment like /*pointer_authentication=*/None (or whatever the argument name is) here and in similar places (applies to all PRs from your stack) so a reader is not surprised by the above comment thinking like "why they are even talking about pointer signing"?
There was a problem hiding this comment.
Done (and in 2 other places that were using None).
| } | ||
|
|
||
| let main_llfn = cx.get_fn_addr(instance, cx.sess().pointer_authentication_functions()); | ||
| // No function pointer signing / type discriminator is needed here. Although `get_fn_addr` is |
There was a problem hiding this comment.
Nit: probably "type discrimination" is excess info in this and similar places - if we have no function pointer signing, it's implying that we do not have any discrimination as well (because discrimination only applies to signed pointers). So this extra info might just accidentally mislead non-pauth-aware reader while adding not that much new value on top of just pointer signing being mentioned.
Please let me know if I'm missing smth and this should be retained
There was a problem hiding this comment.
I would actually keep this one. Someone unfamiliar with pointer authentication might skip over it without giving the comment much thought. However, someone trying to understand the pointer authentication logic by tracing all uses of get_fn_addr might wonder why this particular case is considered safe to leave unsigned.
This patch introduces the following: * Extends `FnAbi` (`callconv`) with a `ptrauth_type_discriminator` field. This field is only used when emitting pointer authentication call bundles. It is stored in `FnAbi` because the call site is not guaranteed to have access to an `Instance`, so the discriminator cannot always be computed on demand. * Adds support for `llvm.ptrauth.resign`. This intrinsic will be used when support for semantic transmute is added. * Performs a minor API redesign as groundwork for allowing call sites to modify schemas in place.
Also remove error messages/tests that used to guarded it.
The codegen now walks the layout of static initializer types to find extern "C" function pointer fields, computes their type discriminators, and applies those discriminators when emitting authenticated function pointer relocations. Also make sure that type discrimination is never applied to init/fini entries.
602e8f8 to
ddc9997
Compare
94562e4 to
b7bbf74
Compare
Implement pointer authentication domain handling for function pointer transmutes. When function pointer type discrimination is enabled, transmuting between function pointer types with different authentication domains now re-signs the pointer using the appropriate discriminator.
…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.
b7bbf74 to
dcb6bf4
Compare
Fill in function pointer type discriminators logic across remaining
get_fn_addrcall sites and explicitly avoid applying it where discrimination is not meaningful.Some uses of
get_fn_addrare intentionally left unsigned, including the EH personality function, entry wrappers, and compiler-generated Rust ABI shims.This is part 6 of a sequence of 8 PRs, that together aim to bring function pointer type discrimination support:
Useful links:
pauthtestintroduction: Introduce aarch64-unknown-linux-pauthtest target #155722