Skip to content

KCFI: Add KCFI arity indicator support #138368

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

Merged
merged 1 commit into from
Apr 5, 2025
Merged

Conversation

rcvalle
Copy link
Member

@rcvalle rcvalle commented Mar 11, 2025

@rustbot
Copy link
Collaborator

rustbot commented Mar 11, 2025

r? @cjgillot

rustbot has assigned @cjgillot.
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 PG-exploit-mitigations Project group: Exploit mitigations 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 11, 2025
@rustbot
Copy link
Collaborator

rustbot commented Mar 11, 2025

Some changes occurred in tests/ui/sanitizer

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

Some changes occurred in tests/codegen/sanitizer

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

@rcvalle rcvalle force-pushed the rust-kcfi-arity branch 2 times, most recently from 9df55b1 to 3cf7741 Compare March 11, 2025 19:12
@ojeda
Copy link
Contributor

ojeda commented Mar 11, 2025

Thanks Ramon for the very quick PR!

I think the matching LLVM PR is llvm/llvm-project#121070, not the other one, right?

Also, would it make sense to add a quick check for the instructions generated, so that we are sure LLVM is actually doing something? e.g. one of the ones from https://github.com/llvm/llvm-project/blob/main/llvm/test/CodeGen/X86/kcfi-arity.ll

@rust-log-analyzer

This comment has been minimized.

@rcvalle rcvalle force-pushed the rust-kcfi-arity branch 2 times, most recently from e84b08f to 60df964 Compare March 11, 2025 20:17
@rcvalle
Copy link
Member Author

rcvalle commented Mar 11, 2025

I think the matching LLVM PR is llvm/llvm-project#121070, not the other one, right?

Thanks for pointing that out! Sorry, I confused them. Fixed.

Also, would it make sense to add a quick check for the instructions generated, so that we are sure LLVM is actually doing something? e.g. one of the ones from https://github.com/llvm/llvm-project/blob/main/llvm/test/CodeGen/X86/kcfi-arity.ll

For module flags, we usually add tests up to to verifying that flags are added only because the side effects of adding them are not implemented in the Rust compiler (so we don't need to keep track of changes and update tests when changes are made in LLVM). Would that be okay for you?

@maurer
Copy link
Contributor

maurer commented Mar 11, 2025

Do we want to add a check when this flag is set that the LLVM is new enough? I think LLVM will silently ignore unknown module tags, so as is, this could result in someone setting -Zsanitizer-kcfi-arity with a rustc that can't actually produce the new-style tags, and being confused by tags that are incompatible with a clang that has that features enabled.

@rust-log-analyzer

This comment has been minimized.

@ojeda
Copy link
Contributor

ojeda commented Mar 11, 2025

For module flags, we usually add tests up to to verifying that flags are added only because the side effects of adding them are not implemented in the Rust compiler (so we don't need to keep track of changes and update tests when changes are made in LLVM). Would that be okay for you?

Up to the Rust compiler team, of course -- I am not sure what their policy is.

In any case, to be clear, I only meant it as a smoke test, rather than testing everything that LLVM does. In other words, just to be sure that LLVM actually did something with the module flag, rather than replicating every test in LLVM.

From a quick test, it seems LLVM (well, at least llc in Compiler Explorer) does not say anything if there is a typo in the module flag in the IR.

So what I thought is to check e.g. that we get, say, a mov edx, ... with the flag instead of a mov eax, ... without the flag.

@davidtwco
Copy link
Member

r? @davidtwco

@rustbot rustbot assigned davidtwco and unassigned cjgillot Mar 12, 2025
@rcvalle
Copy link
Member Author

rcvalle commented Mar 12, 2025

Do we want to add a check when this flag is set that the LLVM is new enough? I think LLVM will silently ignore unknown module tags, so as is, this could result in someone setting -Zsanitizer-kcfi-arity with a rustc that can't actually produce the new-style tags, and being confused by tags that are incompatible with a clang that has that features enabled.

Yes, I think it's a good idea. Done. It seems it's the first time such a check is added for an LLVM-related option so I hope I did it right.

P.S. the implementation chosen for the KCFI arity indicator was to use different registers in the mov instruction as the arity indicator instead of augmenting the KCFI tag with this information. This is entirely implemented in LLVM and visible only in the target architecture assembly (and that is why it's tricky and probably not the right place to test it in the Rust compiler tests).

@rcvalle
Copy link
Member Author

rcvalle commented Mar 13, 2025

From a quick test, it seems LLVM (well, at least llc in Compiler Explorer) does not say anything if there is a typo in the module flag in the IR.

So what I thought is to check e.g. that we get, say, a mov edx, ... with the flag instead of a mov eax, ... without the flag.

For non module flags, we test option's side effects (which are actually implemented in the Rust compiler, such as CFI/KCFI checks) in the LLVM assembly, not the target architecture assembly, and since the implementation for the KCFI arity indicator uses different registers in a mov operation in the target architecture assembly as the arity indicator, we'd have to go even further out from what we usually do module flags (which is just test that the module flag was emitted and emitted correctly, see #129373 as an example), and test the target architecture assembly after the KCFI pass is applied and the target architecture assembly is emitted. I'll see if there is a good way to do a smoke test for this, but I still think this a contract and that it's LLVM's responsibility to test the actual side effects of the module flag-- we'd still caught with out test if we didn't pass or if there was a typo in the module flag.

@rust-log-analyzer

This comment has been minimized.

@ojeda
Copy link
Contributor

ojeda commented Mar 13, 2025

This is entirely implemented in LLVM and visible only in the target architecture assembly (and that is why it's tricky and probably not the right place to test it in the Rust compiler tests).

For non module flags, we test option's side effects (which are actually implemented in the Rust compiler, such as CFI/KCFI checks) in the LLVM assembly, not the target architecture assembly,

Hmm... I am not sure what you mean. Perhaps there is a different policy for LLVM module flags vs. other things like LLVM attributes, but the Rust compiler has assembly tests in tests/assembly/.

For instance, when I added -Zno-jump-tables and -Zfunction-return, I added both an LLVM IR level test as well as an asm level test: 2d47622 ("Add -Zfunction-return={keep,thunk-extern} option"), a65ec44 ("Add -Zno-jump-tables").

Not doing anything is not the end of the world, but it means it is fairly easy for LLVM to e.g. rename the module flags and we wouldn't notice until someone builds the kernel with that compiler and KCFI etc. enabled, as far as I understand, and then it is a mess on the kernel side to add Kconfigs to workaround it.

If adding the test is complex, then sure, we can avoid it. But I don't understand what the issue is adding it. I may be missing a policy thing here, but if it is just the technical side, what is the issue?

In fact, for similar reasons, I would suggest adding one to the feature the PR you linked adds.

@rust-log-analyzer

This comment has been minimized.

@rcvalle
Copy link
Member Author

rcvalle commented Mar 13, 2025

Hmm... I am not sure what you mean. Perhaps there is a different policy for LLVM module flags vs. other things like LLVM attributes, but the Rust compiler has assembly tests in tests/assembly/.

At least that is my understanding (i.e., to not duplicate LLVM tests and perform tests in LLVM assembly as much as possible). (Notice there are no sanitizer tests in there.)

For instance, when I added -Zno-jump-tables and -Zfunction-return, I added both an LLVM IR level test as well as an asm level test: 2d47622 ("Add -Zfunction-return={keep,thunk-extern} option"), a65ec44 ("Add -Zno-jump-tables").

Not doing anything is not the end of the world, but it means it is fairly easy for LLVM to e.g. rename the module flags and we wouldn't notice until someone builds the kernel with that compiler and KCFI etc. enabled, as far as I understand, and then it is a mess on the kernel side to add Kconfigs to workaround it.

Adding it is not the end the world either--I'll just add it :) (But if LLVM starts to arbitrarily changing module flags and like this, I'd argue we'd have much more serious problems.)

In fact, for similar reasons, I would suggest adding one to the feature the PR you linked adds.

Since I'll create the sanitizer/ directory structure there and add a test for this module flag, I'll revisit the other module flags and add similar tests for them accordingly.

Comment on lines 334 to 335
// KCFI arity requires LLVM 20.1.0 or later.
if llvm_version < (20, 1, 0) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This is not the case -- there is no tag yet in upstream LLVM that contains the feature, sadly.

Copy link
Member

@davidtwco davidtwco left a comment

Choose a reason for hiding this comment

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

r=me with the LLVM version check fixed as per #138368 (comment)

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rcvalle
Copy link
Member Author

rcvalle commented Apr 5, 2025

@bors r=davidtwco

@bors
Copy link
Collaborator

bors commented Apr 5, 2025

📌 Commit a98546b has been approved by davidtwco

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 Apr 5, 2025
bors added a commit to rust-lang-ci/rust that referenced this pull request Apr 5, 2025
…iaskrgr

Rollup of 4 pull requests

Successful merges:

 - rust-lang#138368 (KCFI: Add KCFI arity indicator support)
 - rust-lang#138381 (Implement `SliceIndex` for `ByteStr`)
 - rust-lang#139092 (Move `fd` into `std::sys`)
 - rust-lang#139398 (Change notifications for Exploit Mitigations PG)

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit 543160d into rust-lang:master Apr 5, 2025
6 checks passed
@rustbot rustbot added this to the 1.88.0 milestone Apr 5, 2025
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Apr 5, 2025
Rollup merge of rust-lang#138368 - rcvalle:rust-kcfi-arity, r=davidtwco

KCFI: Add KCFI arity indicator support

Adds KCFI arity indicator support to the Rust compiler (see rust-lang#138311, llvm/llvm-project#121070, and https://lore.kernel.org/lkml/CANiq72=3ghFxy8E=AU9p+0imFxKr5iU3sd0hVUXed5BA+KjdNQ@mail.gmail.com/).
@rcvalle rcvalle deleted the rust-kcfi-arity branch April 7, 2025 18:32
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.

8 participants