Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CFI: Strip auto traits off Virtual calls #122879

Merged
merged 2 commits into from
Mar 24, 2024
Merged

Conversation

maurer
Copy link
Contributor

@maurer maurer commented Mar 22, 2024

We already use Instance at declaration sites when available to glean additional information about possible abstractions of the type in use. This does the same when possible at callsites as well.

The primary purpose of this change is to allow CFI to alter how it generates type information for indirect calls through Virtual instances.

This is needed for the "separate machinery" version of my approach to the vtable issues (#122573), because we need to respond differently to a Virtual call to the same type as a non-virtual call, specifically stripping auto traits off the receiver's Self because there isn't a separate vtable for Foo vs Foo + Send.

This would also make a more general underlying mechanism that could be used by rcvalle's proposed drop detection / encoding if we end up using his approach, as we could condition out on the def_id in the CFI code rather than requiring the generating code to explicitly note whether it was calling drop.

@rustbot
Copy link
Collaborator

rustbot commented Mar 22, 2024

r? @Nadrieril

rustbot has assigned @Nadrieril.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Mar 22, 2024
@rustbot
Copy link
Collaborator

rustbot commented Mar 22, 2024

Some changes occurred in compiler/rustc_codegen_gcc

cc @antoyo, @GuillaumeGomez

@maurer
Copy link
Contributor Author

maurer commented Mar 22, 2024

r? workingjubilee

@rustbot rustbot assigned workingjubilee and unassigned Nadrieril Mar 22, 2024
@workingjubilee
Copy link
Member

workingjubilee commented Mar 22, 2024

@bjorn3 The code says cg_clif uses Instance already, yes? Does it also use it for resolving these kinds of calls/invokes, or just the other reasons? Only asking because it doesn't go through cg_ssa.

Comment on lines 150 to 153
///
/// You must provide `instance` if it might affect the alias set of the target.
/// This will never be the case for direct calls. It is currently only required
/// for `Virtual` calls, but providing it when available will avoid complications.
Copy link
Member

Choose a reason for hiding this comment

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

I'm somewhat concerned about this requiring such "high-context" information. Most people have no idea what the hell this means by "alias set". Is there truly no other way to get the relevant Instance?

Copy link
Contributor Author

@maurer maurer Mar 22, 2024

Choose a reason for hiding this comment

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

The only value we have that is a per-instance argument in this function right now is the fn_ptr, and I don't think the backends generally store instances for those because not all of them have one.

I do think your point about it being high-context whether an instance is necessary is reasonable though. Perhaps it would be better to describe it in terms of things you don't need an Instance for? The reworded comment might read:

You must provide instance unless you are making a non-Virtual direct call or calling a raw fn pointer.

Copy link
Member

@workingjubilee workingjubilee Mar 22, 2024

Choose a reason for hiding this comment

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

sure, that makes more sense.

@bors
Copy link
Contributor

bors commented Mar 22, 2024

☔ The latest upstream changes (presumably #122580) made this pull request unmergeable. Please resolve the merge conflicts.

@workingjubilee
Copy link
Member

given #122580 adds an Instance arg anyways I withdraw my remarks about that concern and yeah, basically this looks good to me.

@workingjubilee
Copy link
Member

cc @saethlin the reason the Instance is an Option is because no monomorphization may actually have been done, right? and it has to be forwarded all the time now?

@saethlin
Copy link
Member

the reason the Instance is an Option is because no monomorphization may actually have been done, right?

Nope. It's an Option because nobody pressed me on this before 🙈 and I didn't really look into it deeply.

At the bottom of codegen_call_terminator, we can have either an Instance or just a backend function pointer. So I thought oh well in some cases we don't have an Instance so it has to be optional. But upon re-reading the code, I think we do always discover an Instance at some point in this function which is the function we're calling. The backend function pointer is derived from this code, which requires that we have found an Instance before:

'make_args: for (i, arg) in first_args.iter().enumerate() {
let mut op = self.codegen_operand(bx, &arg.node);
if let (0, Some(ty::InstanceDef::Virtual(_, idx))) = (i, def) {

@maurer maurer force-pushed the callsite-instances branch from 250dd9b to 90e363a Compare March 22, 2024 20:40
@workingjubilee
Copy link
Member

@saethlin Then it would be correct to simply force all callers to pass Instance without leaving them any option about it?

@maurer
Copy link
Contributor Author

maurer commented Mar 22, 2024

the reason the Instance is an Option is because no monomorphization may actually have been done, right?

Nope. It's an Option because nobody pressed me on this before 🙈 and I didn't really look into it deeply.

At the bottom of codegen_call_terminator, we can have either an Instance or just a backend function pointer. So I thought oh well in some cases we don't have an Instance so it has to be optional. But upon re-reading the code, I think we do always discover an Instance at some point in this function which is the function we're calling. The backend function pointer is derived from this code, which requires that we have found an Instance before:

'make_args: for (i, arg) in first_args.iter().enumerate() {
let mut op = self.codegen_operand(bx, &arg.node);
if let (0, Some(ty::InstanceDef::Virtual(_, idx))) = (i, def) {

I belive that the function pointer case

ty::FnPtr(_) => (None, Some(callee.immediate())),

case (non-virtual indirect call) still doesn't have an instance. The block you identified is the only place llfn is assigned to, but its initial definition can have a Some value in the branch I highlighted. Attempting to unwrap the instance at the end also fails empirically.

@saethlin
Copy link
Member

Ah, yes, I see. I didn't trace def far enough back up through the function. Bummer, looks like this needs to stay optional.

@workingjubilee
Copy link
Member

alas.

@workingjubilee
Copy link
Member

workingjubilee commented Mar 22, 2024

@maurer This needs to land a test that would depend on this to prevent it from randomly regressing, then? I think?

@rustbot
Copy link
Collaborator

rustbot commented Mar 22, 2024

Some changes occurred in tests/ui/sanitizer

cc @rust-lang/project-exploit-mitigations, @rcvalle

Some changes occurred in compiler/rustc_symbol_mangling/src/typeid

cc @rust-lang/project-exploit-mitigations, @rcvalle

@rustbot rustbot added the PG-exploit-mitigations Project group: Exploit mitigations label Mar 22, 2024
@maurer maurer changed the title CFI: Use Instance at callsites CFI: Strip auto traits off Virtual calls Mar 22, 2024
@maurer
Copy link
Contributor Author

maurer commented Mar 22, 2024

I added my usage of this onto this PR to make it testable. I changed the name of the PR to reflect that.

In addition to feeding the Instance through, it now uses it in the mangling to remove auto traits from virtual calls. This allows &(dyn Foo + Send) receivers to successfully access &self functions on the Foo trait.

@workingjubilee
Copy link
Member

Nice!

@bors r+

@bors
Copy link
Contributor

bors commented Mar 23, 2024

📌 Commit 042e05b has been approved by workingjubilee

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 23, 2024
workingjubilee added a commit to workingjubilee/rustc that referenced this pull request Mar 23, 2024
…ngjubilee

CFI: Strip auto traits off Virtual calls

We already use `Instance` at declaration sites when available to glean additional information about possible abstractions of the type in use. This does the same when possible at callsites as well.

The primary purpose of this change is to allow CFI to alter how it generates type information for indirect calls through `Virtual` instances.

This is needed for the "separate machinery" version of my approach to the vtable issues (rust-lang#122573), because we need to respond differently to a `Virtual` call to the same type as a non-virtual call, specifically [stripping auto traits off the receiver's `Self`](rust-lang@54b15b0) because there isn't a separate vtable for `Foo` vs `Foo + Send`.

This would also make a more general underlying mechanism that could be used by rcvalle's [proposed drop detection / encoding](rust-lang@edcd1e2) if we end up using his approach, as we could condition out on the `def_id` in the CFI code rather than requiring the generating code to explicitly note whether it was calling drop.
bors added a commit to rust-lang-ci/rust that referenced this pull request Mar 23, 2024
…kingjubilee

Rollup of 10 pull requests

Successful merges:

 - rust-lang#121940 (Mention Register Size in `#[warn(asm_sub_register)]`)
 - rust-lang#122460 (Rework rmake support library API)
 - rust-lang#122698 (Cancel `cargo update` job if there's no updates)
 - rust-lang#122780 (Rename `hir::Local` into `hir::LetStmt`)
 - rust-lang#122875 (CFI: Support self_cell-like recursion)
 - rust-lang#122879 (CFI: Strip auto traits off Virtual calls)
 - rust-lang#122915 (Delay a bug if no RPITITs were found)
 - rust-lang#122916 (docs(sync): normalize dot in fn summaries)
 - rust-lang#122922 (-Zprint-type-sizes: print the types of awaitees and unnamed coroutine locals.)
 - rust-lang#122927 (Change an ICE regression test to use the original reproducer)

r? `@ghost`
`@rustbot` modify labels: rollup
@bors
Copy link
Contributor

bors commented Mar 23, 2024

☔ The latest upstream changes (presumably #122582) made this pull request unmergeable. Please resolve the merge conflicts.

@bors bors added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Mar 23, 2024
maurer added 2 commits March 23, 2024 18:30
We already use `Instance` at declaration sites when available to glean
additional information about possible abstractions of the type in use.
This does the same when possible at callsites as well.

The primary purpose of this change is to allow CFI to alter how it
generates type information for indirect calls through `Virtual`
instances.
Additional trait bounds beyond the principal trait and its implications
are not possible in the vtable. This means that if a receiver is
`&dyn Foo + Send`, the function will only be expecting `&dyn Foo`.

This strips those auto traits off before CFI encoding.
@maurer maurer force-pushed the callsite-instances branch from 042e05b to f434c27 Compare March 23, 2024 18:34
@maurer
Copy link
Contributor Author

maurer commented Mar 23, 2024

Conflict resolved, there was a minor use statement ordering conflict.

@maurer
Copy link
Contributor Author

maurer commented Mar 23, 2024

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Mar 23, 2024
@workingjubilee
Copy link
Member

@bors r+

@bors
Copy link
Contributor

bors commented Mar 23, 2024

📌 Commit f434c27 has been approved by workingjubilee

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 23, 2024
workingjubilee added a commit to workingjubilee/rustc that referenced this pull request Mar 24, 2024
…ngjubilee

CFI: Strip auto traits off Virtual calls

We already use `Instance` at declaration sites when available to glean additional information about possible abstractions of the type in use. This does the same when possible at callsites as well.

The primary purpose of this change is to allow CFI to alter how it generates type information for indirect calls through `Virtual` instances.

This is needed for the "separate machinery" version of my approach to the vtable issues (rust-lang#122573), because we need to respond differently to a `Virtual` call to the same type as a non-virtual call, specifically [stripping auto traits off the receiver's `Self`](rust-lang@54b15b0) because there isn't a separate vtable for `Foo` vs `Foo + Send`.

This would also make a more general underlying mechanism that could be used by rcvalle's [proposed drop detection / encoding](rust-lang@edcd1e2) if we end up using his approach, as we could condition out on the `def_id` in the CFI code rather than requiring the generating code to explicitly note whether it was calling drop.
bors added a commit to rust-lang-ci/rust that referenced this pull request Mar 24, 2024
…kingjubilee

Rollup of 13 pull requests

Successful merges:

 - rust-lang#121281 (regression test for rust-lang#103626)
 - rust-lang#121940 (Mention Register Size in `#[warn(asm_sub_register)]`)
 - rust-lang#122217 (Handle str literals written with `'` lexed as lifetime)
 - rust-lang#122379 (transmute: caution against int2ptr transmutation)
 - rust-lang#122460 (Rework rmake support library API)
 - rust-lang#122797 (Fix compile of wasm64-unknown-unknown target)
 - rust-lang#122875 (CFI: Support self_cell-like recursion)
 - rust-lang#122879 (CFI: Strip auto traits off Virtual calls)
 - rust-lang#122895 (add some ice tests 5xxxx to 9xxxx)
 - rust-lang#122907 (Uniquify `ReError` on input mode in canonicalizer)
 - rust-lang#122923 (In `pretty_print_type()`, print `async fn` futures' paths instead of spans.)
 - rust-lang#122942 (Add test in higher ranked subtype)
 - rust-lang#122963 (core/panicking: fix outdated comment)

r? `@ghost`
`@rustbot` modify labels: rollup
workingjubilee added a commit to workingjubilee/rustc that referenced this pull request Mar 24, 2024
…ngjubilee

CFI: Strip auto traits off Virtual calls

We already use `Instance` at declaration sites when available to glean additional information about possible abstractions of the type in use. This does the same when possible at callsites as well.

The primary purpose of this change is to allow CFI to alter how it generates type information for indirect calls through `Virtual` instances.

This is needed for the "separate machinery" version of my approach to the vtable issues (rust-lang#122573), because we need to respond differently to a `Virtual` call to the same type as a non-virtual call, specifically [stripping auto traits off the receiver's `Self`](rust-lang@54b15b0) because there isn't a separate vtable for `Foo` vs `Foo + Send`.

This would also make a more general underlying mechanism that could be used by rcvalle's [proposed drop detection / encoding](rust-lang@edcd1e2) if we end up using his approach, as we could condition out on the `def_id` in the CFI code rather than requiring the generating code to explicitly note whether it was calling drop.
workingjubilee added a commit to workingjubilee/rustc that referenced this pull request Mar 24, 2024
…ngjubilee

CFI: Strip auto traits off Virtual calls

We already use `Instance` at declaration sites when available to glean additional information about possible abstractions of the type in use. This does the same when possible at callsites as well.

The primary purpose of this change is to allow CFI to alter how it generates type information for indirect calls through `Virtual` instances.

This is needed for the "separate machinery" version of my approach to the vtable issues (rust-lang#122573), because we need to respond differently to a `Virtual` call to the same type as a non-virtual call, specifically [stripping auto traits off the receiver's `Self`](rust-lang@54b15b0) because there isn't a separate vtable for `Foo` vs `Foo + Send`.

This would also make a more general underlying mechanism that could be used by rcvalle's [proposed drop detection / encoding](rust-lang@edcd1e2) if we end up using his approach, as we could condition out on the `def_id` in the CFI code rather than requiring the generating code to explicitly note whether it was calling drop.
bors added a commit to rust-lang-ci/rust that referenced this pull request Mar 24, 2024
…kingjubilee

Rollup of 7 pull requests

Successful merges:

 - rust-lang#120419 (Expand sys/os for UEFI)
 - rust-lang#121940 (Mention Register Size in `#[warn(asm_sub_register)]`)
 - rust-lang#122762 (fix typo of endianness)
 - rust-lang#122797 (Fix compile of wasm64-unknown-unknown target)
 - rust-lang#122875 (CFI: Support self_cell-like recursion)
 - rust-lang#122879 (CFI: Strip auto traits off Virtual calls)
 - rust-lang#122969 (Simplify an iterator search in borrowck diag)

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit 992aa1e into rust-lang:master Mar 24, 2024
11 checks passed
@rustbot rustbot added this to the 1.79.0 milestone Mar 24, 2024
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Mar 24, 2024
Rollup merge of rust-lang#122879 - maurer:callsite-instances, r=workingjubilee

CFI: Strip auto traits off Virtual calls

We already use `Instance` at declaration sites when available to glean additional information about possible abstractions of the type in use. This does the same when possible at callsites as well.

The primary purpose of this change is to allow CFI to alter how it generates type information for indirect calls through `Virtual` instances.

This is needed for the "separate machinery" version of my approach to the vtable issues (rust-lang#122573), because we need to respond differently to a `Virtual` call to the same type as a non-virtual call, specifically [stripping auto traits off the receiver's `Self`](rust-lang@54b15b0) because there isn't a separate vtable for `Foo` vs `Foo + Send`.

This would also make a more general underlying mechanism that could be used by rcvalle's [proposed drop detection / encoding](rust-lang@edcd1e2) if we end up using his approach, as we could condition out on the `def_id` in the CFI code rather than requiring the generating code to explicitly note whether it was calling drop.
RenjiSann pushed a commit to RenjiSann/rust that referenced this pull request Mar 25, 2024
…ngjubilee

CFI: Strip auto traits off Virtual calls

We already use `Instance` at declaration sites when available to glean additional information about possible abstractions of the type in use. This does the same when possible at callsites as well.

The primary purpose of this change is to allow CFI to alter how it generates type information for indirect calls through `Virtual` instances.

This is needed for the "separate machinery" version of my approach to the vtable issues (rust-lang#122573), because we need to respond differently to a `Virtual` call to the same type as a non-virtual call, specifically [stripping auto traits off the receiver's `Self`](rust-lang@54b15b0) because there isn't a separate vtable for `Foo` vs `Foo + Send`.

This would also make a more general underlying mechanism that could be used by rcvalle's [proposed drop detection / encoding](rust-lang@edcd1e2) if we end up using his approach, as we could condition out on the `def_id` in the CFI code rather than requiring the generating code to explicitly note whether it was calling drop.
RenjiSann pushed a commit to RenjiSann/rust that referenced this pull request Mar 25, 2024
…kingjubilee

Rollup of 7 pull requests

Successful merges:

 - rust-lang#120419 (Expand sys/os for UEFI)
 - rust-lang#121940 (Mention Register Size in `#[warn(asm_sub_register)]`)
 - rust-lang#122762 (fix typo of endianness)
 - rust-lang#122797 (Fix compile of wasm64-unknown-unknown target)
 - rust-lang#122875 (CFI: Support self_cell-like recursion)
 - rust-lang#122879 (CFI: Strip auto traits off Virtual calls)
 - rust-lang#122969 (Simplify an iterator search in borrowck diag)

r? `@ghost`
`@rustbot` modify labels: rollup
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
PG-exploit-mitigations Project group: Exploit mitigations S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants