Skip to content

Conversation

folkertdev
Copy link
Contributor

@folkertdev folkertdev commented Oct 14, 2025

tracking issue: #81391
tracking issue: #75835

When a union passes from secure to non-secure (so, passed as an argument to a non-secure call, or returned by a non-secure entry), warn that there may be secure information lingering in the unused or uninitialized parts of a union value.

This lint matches the behavior of clang (see https://godbolt.org/z/vq9xnrnEs). Like clang we warn at the use site, so that individual uses could be annotated with #[allow(cmse_uninitialized_leak)].

Ideally we'd warn on any type that may have uninitialized parts, but I haven't figured out a good way to do that yet.

It is still unclear whether a union value where all fields are equally large and allow the same bit patterns can be considered initialized (see rust-lang/unsafe-code-guidelines#438), so for now we just warn on any union.

r? @ghost

@folkertdev folkertdev added F-cmse_nonsecure_entry `#![feature(cmse_nonsecure_entry)]` F-abi_c_cmse_nonsecure_call `#![feature(abi_c_cmse_nonsecure_call)]` labels Oct 14, 2025
@rustbot rustbot added A-test-infra-minicore Area: `minicore` test auxiliary and `//@ add-core-stubs` S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Oct 14, 2025
@rust-log-analyzer

This comment has been minimized.

@folkertdev folkertdev force-pushed the cmse-lint-on-uninitialized branch from a344d30 to 514010e Compare October 15, 2025 09:09
@rust-log-analyzer

This comment has been minimized.

@folkertdev folkertdev force-pushed the cmse-lint-on-uninitialized branch from 514010e to 9d276b5 Compare October 15, 2025 11:03
@rust-log-analyzer

This comment has been minimized.

@folkertdev folkertdev force-pushed the cmse-lint-on-uninitialized branch from 9d276b5 to 4a269f5 Compare October 15, 2025 11:55
@rust-log-analyzer

This comment has been minimized.

@folkertdev folkertdev force-pushed the cmse-lint-on-uninitialized branch from 4a269f5 to 0b424f6 Compare October 15, 2025 16:49
@folkertdev
Copy link
Contributor Author

r? @davidtwco

This seems useful just for parity with clang. The code is built to be extended to cover more cases of types possibly containing uninitialized memory, but by the looks of things there isn't currently a straightforward way to detect such types (cc #t-compiler/help > check whether a type can be (partially) uninitialized)

@folkertdev folkertdev marked this pull request as ready for review October 15, 2025 19:29
@rustbot
Copy link
Collaborator

rustbot commented Oct 15, 2025

HIR ty lowering was modified

cc @fmease

This PR modifies tests/auxiliary/minicore.rs.

cc @jieyouxu

@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 Oct 15, 2025
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.

Implementation LGTM, two nits, but will need t-lang approval for a new lint

View changes since this review

#[no_mangle]
#[allow(improper_ctypes_definitions)]
pub extern "cmse-nonsecure-entry" fn f5(_: [u32; 5]) {} //~ ERROR [E0798]
//
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
//

nit

use minicore::*;

#[repr(Rust)]
pub union ReprRustUnionU64 {
Copy link
Member

Choose a reason for hiding this comment

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

Can you add cases where the unions are contained within other types to these tests?

@davidtwco davidtwco added the I-lang-nominated Nominated for discussion during a lang team meeting. label Oct 16, 2025
When a union passes from secure to non-secure (so, passed as an argument to an nonsecure call, or returned by a nonsecure entry), warn that there may be secure information lingering in the unused or uninitialized parts of a union value. https://godbolt.org/z/vq9xnrnEs
@folkertdev folkertdev force-pushed the cmse-lint-on-uninitialized branch from 0b424f6 to 4586300 Compare October 16, 2025 20:05
Copy link
Contributor Author

@folkertdev folkertdev left a comment

Choose a reason for hiding this comment

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

The lint will only fire when the cmse ABIs are enabled, but I suppose the name does sort of "leak".

the OP here provides some context. The bigger picture is in this draft RFC that I plan to formally submit soon.

View changes since this review

Comment on lines +49 to +58
warning: passing a union across the security boundary may leak information
--> $DIR/return-uninitialized.rs:46:5
|
LL | / match 0 {
LL | |
LL | | 0 => Wrapper(ReprRustUnionU64 { _unused: 1 }),
LL | | _ => Wrapper(ReprRustUnionU64 { _unused: 2 }),
LL | | }
| |_____^
|
Copy link
Contributor Author

Choose a reason for hiding this comment

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

would it make sense to warn in the individual arms of the match instead? I think as a user that would be better in this simple case, though I don't know that we can make that robust (e.g. thinking about labeled blocks).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-test-infra-minicore Area: `minicore` test auxiliary and `//@ add-core-stubs` F-abi_c_cmse_nonsecure_call `#![feature(abi_c_cmse_nonsecure_call)]` F-cmse_nonsecure_entry `#![feature(cmse_nonsecure_entry)]` I-lang-nominated Nominated for discussion during a lang team meeting. 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.

4 participants