[WIP] 4 - Static allocs#159081
Conversation
9052b2a to
5b223de
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
5b223de to
45f422b
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
45f422b to
8659b72
Compare
This comment has been minimized.
This comment has been minimized.
8659b72 to
8392cdf
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>.
8392cdf to
5399226
Compare
| /// emitted at that offset. | ||
| /// | ||
| /// Offsets are relative to the beginning of the allocation. | ||
| pub(crate) struct FnPtrDiscriminatorAtOffset { |
There was a problem hiding this comment.
What is the established naming convention in rust for such kind of things? Should this be plural (discriminators)? Especially given the fact that we already have collect_fn_ptr_discriminators
There was a problem hiding this comment.
Sure, FnPtrDiscriminatorsAtOffset it is.
| let variant = def.non_enum_variant(); | ||
|
|
||
| let Some((_, field)) = variant.fields.iter_enumerated().next() else { | ||
| return; |
There was a problem hiding this comment.
Could you please refer me to tests covering these early-return paths (from this case and from the below cases)? The logic by itself looks sound, but it definitely deserves its own test coverage (which I'm not sure I can correctly identify by myself in the new test suite from PR 8)
There was a problem hiding this comment.
Interesting, this is actually redundant. I initially though it would serve for something like:
#[repr(transparent)]
struct Wrapper(extern "C" fn(i32));
impl Sync for Wrapper {}
static T_WRAPPED_FN_PTR: Wrapper = Wrapper(g);in https://github.com/jchlanda/rust/blob/fb279532dbf253c1f78dd02a3268bfdde8d6d7ad/tests/codegen-llvm/pauth/pauth-fn-ptr-type-discrimination-struct-members.rs#L1, but turns out struct arm handles it just fine. Removing.
While at it, I added a test case for Tupel which was missing (T_TUPLE, T_TUPLE_2 and test_8_tuple_members in the same file). Tests added to the 8th PR.
Thanks!
ef6b34d to
e08ffe7
Compare
| .as_ref() | ||
| .and_then(|m| m.map.get(&Size::from_bytes(offset as u64))); | ||
|
|
||
| // Init/fini entries must not participate in function pointer type discrimination. |
There was a problem hiding this comment.
Nit: maybe worth slightly re-phrasing this - now it might be understood as "init/fini pointers are zero-discriminated", while in reality they receive their own special constant discriminator
| // FIXME: should we cache `const_alloc_to_llvm` to avoid repeating this for the | ||
| // same `ConstAllocation`? | ||
| let cv = const_alloc_to_llvm(self, alloc.inner(), IsStatic::No, IsInitOrFini::No); | ||
| let cv = const_alloc_to_llvm(self, alloc.inner(), IsStatic::No, IsInitOrFini::No, None); |
There was a problem hiding this comment.
Could you please explain why fn_ptr_discriminators is guaranteed to be None here? Is ConstAllocation something which is guaranteed not to contain nested function pointers?
There was a problem hiding this comment.
Looked at this code again, and I think this is incorrect. Type discrimination should also be applied when computing addresses for statics; it just didn't come up in the existing tests.
From a quick look, this seems a little more involved because we don't have the necessary type information when calling static_addr_of. We'll likely need to either extend its API or compute the discriminator map at the call sites that still have access to the Rust type.
I've added an in-code FIXME to capture this, and if you're okay with it, I'd like to address it in a follow-up PR.
| alloc: &Allocation, | ||
| is_static: IsStatic, | ||
| is_init_fini: IsInitOrFini, | ||
| fn_ptr_discriminators: Option<&FnPtrDiscriminatorsAtOffset>, |
There was a problem hiding this comment.
Nit: I'm not sure of a particular suggestion, but just as a thought - it might be worth somehow prefixing such things with ptrauth_ in order to (a) indicate that it's ptrauth-specific for readers wondering what's it all about (b) make it easier to grep ptrauth-related stuff.
If just adding prefix right now, the identifier would become too long though. So maybe the rest of the name could be somehow reconsidered.
I would appreciate if you could do a pass over all newly added data structures/variables/argument names which exist in "generic" non-ptrauth-specific context and ensure if in all such places it's clear that the corresponding item is ptrauth-specific
There was a problem hiding this comment.
For new fields that are extending already existing data structures, I'll add the ptrauth_ prefix.
I'll also do a follow-up PR to take another look at session.rs, as it doesn't really belong in this patch series. At that point I'll also review the names of the data structures/functions we're introducing. I agree that public-facing identifiers should be prefixed, but for local, throwaway-style types/funcs I'm less convinced. Since they're context-specific, they should be easier to reason about without additional prefixes.
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.
e08ffe7 to
f77edea
Compare
The codegen now walks the layout of statically initialized 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.
This is part 4 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