Skip to content

[WIP] pac ty disc#158567

Draft
jchlanda wants to merge 23 commits into
rust-lang:mainfrom
jchlanda:jakub/pac_ty_disc
Draft

[WIP] pac ty disc#158567
jchlanda wants to merge 23 commits into
rust-lang:mainfrom
jchlanda:jakub/pac_ty_disc

Conversation

@jchlanda

@jchlanda jchlanda commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

@rustbot rustbot added A-compiletest Area: The compiletest test runner A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. A-run-make Area: port run-make Makefiles to rmake.rs A-test-infra-minicore Area: `minicore` test auxiliary and `//@ add-core-stubs` A-testsuite Area: The testsuite used to check the correctness of rustc S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Jun 29, 2026
@rust-log-analyzer

This comment has been minimized.

cv: Scalar,
layout: abi::Scalar,
llty: Self::Type,
schema: Option<PointerAuthSchema>,

@bjorn3 bjorn3 Jun 29, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function should have access to the Session already through self.tcx.sess.

View changes since the review

fn get_fn_addr(
&self,
instance: Instance<'tcx>,
pointer_auth_schema: Option<PointerAuthSchema>,

@bjorn3 bjorn3 Jun 29, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jchlanda jchlanda force-pushed the jakub/pac_ty_disc branch from 2d3b257 to f5fa52a Compare June 30, 2026 11:57
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@jchlanda jchlanda force-pushed the jakub/pac_ty_disc branch from d6ce62a to 755b0b7 Compare June 30, 2026 15:08
@rust-log-analyzer

This comment has been minimized.

@jchlanda jchlanda force-pushed the jakub/pac_ty_disc branch from 755b0b7 to c3fd17f Compare June 30, 2026 15:23
@rust-log-analyzer

This comment has been minimized.

@jchlanda jchlanda force-pushed the jakub/pac_ty_disc branch from c3fd17f to 8b6e351 Compare July 1, 2026 06:23
@rust-log-analyzer

This comment has been minimized.

@jchlanda jchlanda force-pushed the jakub/pac_ty_disc branch from 8b6e351 to 5b8ba19 Compare July 1, 2026 07:24
@rust-log-analyzer

This comment has been minimized.

@jchlanda jchlanda force-pushed the jakub/pac_ty_disc branch from 5b8ba19 to 9545275 Compare July 1, 2026 08:41
@jchlanda jchlanda force-pushed the jakub/pac_ty_disc branch from 4301abb to 9545275 Compare July 1, 2026 15:06
_new_key: u32,
_new_discriminator: u64,
) -> Self::Value {
bug!("Resigning of pointers not implemented");

@kovdan01 kovdan01 Jul 1, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a test for this (ensuring that it's not supported) or is it infeasible to reach this path?

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not a user facing function, so the only way it could be triggered is if we wrote incorrect code within the compiler itself, hence the bug!. The relevant call chain for this function starts inside codegen_transmute and is guarded by a function pointer support check.

// Direct function pointer.
if let Some(input) = build_fn_ptr_type_discriminator_input(tcx, ty) {
// Only support about extern "C".
if matches!(input.abi(), ExternAbi::C { .. } | ExternAbi::System { .. }) {

@kovdan01 kovdan01 Jul 1, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please explain what ExternAbi::System stands for? I would appreciate if you also refer me to the corresponding test

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

System means the platform’s default system ABI for foreign functions, whatever the platform uses by default for system libraries. I was told in one of the PRs that for all practical cases they should match. Hence the inclusion of both.

The docs.


let address_space = cx.tcx.global_alloc(prov.alloc_id()).address_space(cx);
let schema = if cx.sess().pointer_authentication() {
let mut schema = if cx.sess().pointer_authentication() {

@kovdan01 kovdan01 Jul 1, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need mut here?

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because we then retrieve the discriminator and store it in the schema.

operand: OperandRef<'tcx, Bx::Value>,
cast: TyAndLayout<'tcx>,
) -> OperandValue<Bx::Value> {
debug!(

@kovdan01 kovdan01 Jul 1, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this intended to be included in the PR or is it a development-stage-only debug printing?

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intended. This serves the same purpose as LLVM_DEBUG(dbgs()...) in llvm.

pub mod middle;
pub mod mir;
pub mod mono;
pub mod ptrauth;

@kovdan01 kovdan01 Jul 1, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are no other changes in the file - so, is this actually needed?

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes.
This says something along the lines of: "There is a module called ptrauth, and it should be included in the library’s public interface.If you go toptrauthdirectory you'll see themod.rs` which in turns tells us what is publicly exported from the module.
So the flow of visibility is: lib.rs -> ptrauth -> discriminator / llvm_siphash (where the last two are controlled by https://github.com/jchlanda/rust/blob/9545275cededc9e307c61ef9d640d256ae59eab3/compiler/rustc_middle/src/ptrauth/mod.rs#L5)

@kovdan01 kovdan01 Jul 1, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This deleted test should also be removed from the markdown documentation file which includes it in test coverage

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeap, need to work on that file a bit more.

Comment thread compiler/rustc_public/src/abi.rs Outdated
pub c_variadic: bool,

/// Computed type discriminator for pointer authentication purpose.
pub type_discriminator: u64,

@kovdan01 kovdan01 Jul 1, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's probably worth prefixing ptrauth-related things with smth like ptrauth_ in such "generic" places (which are not ptrauth-specific). A comment here contains explanation, but when constructing struct objects we have type_discriminator: XXX which non-ptrauth-aware reader would not easily understand

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, renamed to ptrauth_type_discriminator.

fixed_count: self.fixed_count,
conv: self.conv.stable(tables, cx),
c_variadic: self.c_variadic,
type_discriminator: 0,

@kovdan01 kovdan01 Jul 1, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please explain why we have 0 here and are there any cases when non-zero discriminator would be needed here?

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you are on to something. There are 3 structs with the same name (FnAbi): public, callconv and gcc. I wonder if we could get away with only extending callconv.

I'll get back to you on this one.

@jchlanda jchlanda Jul 3, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeap, the only one we need is the callconv, refactored.

Comment thread compiler/rustc_codegen_gcc/src/int.rs Outdated
fixed_count: 3,
conv: CanonAbi::C,
can_unwind: false,
type_discriminator: 0,

@kovdan01 kovdan01 Jul 1, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably deserves a comment that it's just a placeholder value since gcc backend is not supported for pointer authentication (if I got your reasoning right)

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

fn_ptr_discriminators.as_ref().and_then(|m| m.get(Size::from_bytes(offset as u64)));

if let (Some(schema), Some(discr)) = (schema.as_mut(), discr) {
schema.constant_discriminator = discr as u16;

@kovdan01 kovdan01 Jul 1, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this override discriminator value for init/fini if fn ptr type discr is enabled? If so, it looks diverging from how clang handles this - and my understanding is that it actually makes sense to have hard-coded separate discriminator for init/fini since these are (a) known type (b) we need to know discriminator in dynamic loader.

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you saying that discriminator for init/fini must always be 0xd9d4, regardless if fn ptr type discrimination is on or not? If so, than we've got a bug, as it would be indeed overridden. Let me see what clang does and come back to you.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, we do have a bug. Clang does:

  • no init/fini, no fn ptr ty disc:
@llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 90, ptr @foo, ptr null }]
  • init/fini, no fn ptr ty disc:
@llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 90, ptr ptrauth (ptr @foo, i32 0, i64 55764, ptr inttoptr (i64 1 to ptr)), ptr null }]
  • no init/fini, fn ptr ty disc:
@llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 90, ptr @foo, ptr null }]
  • init/fini, fn ptr ty disc:
@llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 90, ptr ptrauth (ptr @foo, i32 0, i64 55764, ptr inttoptr (i64 1 to ptr)), ptr null }]

I'll have to fix that in rust.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, fixed now, extended the test with O{0|3}_PAUTH-INIT-FINI-FN-TY-DISC.

@rust-log-analyzer

This comment has been minimized.

@jchlanda jchlanda force-pushed the jakub/pac_ty_disc branch from 3a40e3c to 697c5ce Compare July 2, 2026 14:55
jchlanda added 7 commits July 3, 2026 10:35
This patch brings:
* unified handling of pointer authentication options through:
  `-Zpointer-authentication`, with possible values:
  `aarch64-jump-table-hardening`, `auth-traps`, `calls`, `elf-got`,
  `function-pointer-type-discrimination`, `indirect-gotos`, `init-fini`,
  `init-fini-address-discrimination`, `return-addresses`. Toggled with
  `+`/`-`.
* centralized handling of pointer authentication features. Session holds
  `pointer_auth_config: Option<PointerAuthConfig>`
* encapsulation of schema for function pointers and init/fini through
  `PointerAuthSchema`. This allowed for retiring of `PacMetadata`.
* refactor enabling of pointer authentication in code, instead of
  relying on the target (`pauthtest`) use the session
- warning on unsupported test
- error on type discrimination
- removal of PointerAuthKind
Also improve the API design of pointer_authentication_functions, by
making it return Option<&PointerAuthSchema>, rather than bool.
@jchlanda jchlanda force-pushed the jakub/pac_ty_disc branch from 697c5ce to eef2752 Compare July 3, 2026 14:44
jchlanda added 10 commits July 3, 2026 14:44
Alongside Rust implementation of LLVM's SipHash-2-4.
This is only to be used when emitting an operand bundle, which might not
have access to an Instance of the function, but for which FnAbi is
guaranteed to be correct.
Start moving away from global schema, by cloning it into users.
Helpers for fn ptr type discrimination status and value of the key.
This is a move away from a blind bitcast between the types. Now, when
dealing with function pointers, transmute will detect a domain change
(change of fn ptr type) and issue resigning.
@jchlanda jchlanda force-pushed the jakub/pac_ty_disc branch from eef2752 to 96d5f58 Compare July 3, 2026 14:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-compiletest Area: The compiletest test runner A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. A-run-make Area: port run-make Makefiles to rmake.rs A-test-infra-minicore Area: `minicore` test auxiliary and `//@ add-core-stubs` A-testsuite Area: The testsuite used to check the correctness of rustc S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants