Add lint againts invalid runtime symbol definitions#155521
Conversation
|
These commits modify the If this was unintentional then you should revert the changes before this PR is merged. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
| /// | ||
| /// ### Explanation | ||
| /// | ||
| /// Up-most care is required when defining runtime symbols assumed and |
There was a problem hiding this comment.
Nit:
| /// Up-most care is required when defining runtime symbols assumed and | |
| /// Utmost care is required when defining runtime symbols assumed and |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment was marked as duplicate.
This comment was marked as duplicate.
|
Should this also include |
|
As far as I understood the lang meeting discussion, there was no concern with this PR. But some opinion that it doesn’t fully replace the previous PR, since some warn-by-default lint more generally applicable (and to actually address the user reports, which were about |
|
My interpretation here: this lint is valuable because the wrong signature for something on the well-known list is clearly and always wrong, so deny makes sense. We should have this lint. (And I'm find expanding to more functions so long as they meet that "definitely incontrovertibly wrong signature for that name that rustc or one of your linked libraries uses" bar. I don't know if we include Another lint, for "it's very suspicious that you're defining an unmangled |
Many of the code samples in the search that I quoted https://github.com/search?q=language%3Arust+fn+memcpy&type=code are Rust-to-Rust calls as memcpy is defined in Rust.
Many of these programs also probably don't care about CFI (or only have direct function call emitted for these functions, which will be the case for LLVM-generated calls to those functions), and as this is a deny-by-default lint, I think rejecting these working code is excessive. I wouldn't be concerned if the lint is only warn-by-default. |
|
@Darksonn wrote:
AFAICT, the point of this lint is "you're defining a conflicting symbol that couldn't possibly work. If you're defining something that uses a pointer but it's a different signedness, or for that matter something that accepts an Could you elaborate on why you feel it's a problem for us to suppress the lint if the only mismatch is Is CFI an issue here? Would those types be considered incompatible, tripping a CFI fault if called? |
|
From my perspective, I would absolutely expect ABI-compatible being fine here. If we had this check on |
Yes. That's exactly the point. That's why I referenced rust-lang/unsafe-code-guidelines#489 above. The plan to make Rust CFI-compatible is to declare some calls that we currently deem ABI-compatible to instead have EB (Erroneous Behavior), together with a promise that Rust in its default configuration will not act on this EB. And among the calls that we'll have to make EB is a |
|
@RalfJung I see. That makes sense. Still not certain if we should be linting such mismatches yet, given that this is a best-effort lint, but given the CFI concern, it seems reasonable to ship this lint without the mismatch handling. |
|
This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
|
Given the discussion above, the T-lang triage notes and the Zulip thread. I've removed the type normalization/mismatch handling and gone back to exact type equality. @ojeda @nbdd0121 could I ask you to prepare a patch that allow the lint ( |
|
Thanks, I can do that. |
There's something I don't understand here. I don't think you would use With that said, I believe this is the first time we're going to lint over this new category of Erroneous Behavior to satisfy CFI, and CFI is rather strict, and deny-by-default is rather strong. If there is a convincing case where this lint would steer people away from using safer types, I'd want to discuss more with the team before this lands. I'm going to renominate so this stays on our radar, but we may be able to resolve it async if we agree there are no examples of this. @rustbot label I-lang-nominated |
Starting with Rust 1.98.0 (expected 2026-08-20), Rust is introducing
a new deny-by-default lint which checks the signature of items whose
symbol name is a runtime symbol expected by `core`:
error: invalid definition of the runtime `strlen` symbol used by the standard library
--> rust/uapi/uapi_generated.rs:13998:5
|
13998 | pub fn strlen(s: *const ffi::c_char) -> usize;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: expected `unsafe extern "C" fn(*const i8) -> usize`
found `unsafe extern "C" fn(*const u8) -> usize`
= help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "strlen")]`, or `#[link_name = "strlen"]`
= note: `#[deny(invalid_runtime_symbol_definitions)]` on by default
error: invalid definition of the runtime `strlen` symbol used by the standard library
--> rust/bindings/bindings_generated.rs:19877:5
|
19877 | pub fn strlen(s: *const ffi::c_char) -> usize;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: expected `unsafe extern "C" fn(*const i8) -> usize`
found `unsafe extern "C" fn(*const u8) -> usize`
= help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "strlen")]`, or `#[link_name = "strlen"]`
= note: `#[deny(invalid_runtime_symbol_definitions)]` on by default
Thus `allow` the lint in `bindings` and `uapi`.
Link: rust-lang/rust#155521 [1]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
|
Please cherry-pick ojeda@422215a (will conflict with #157151). I am |
The compiler is adding `invalid_runtime_symbol_definitions` [1], thus temporarily add a patch. As usual, the patch will eventually make it to the Linux kernel so that both sides are good. Link: rust-lang#155521 [1] Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
|
Thanks. I've cherry-picked the patch. Let's verify that it works as expected. |
View all comments
This PR adds a deny-by-default lint againts invalid runtime symbol definitions, those runtime symbols are assumed and used by
core1 andrustcwith a specific definition.We have had multiple reports of users tripping over
stdsymbols (addressed in a future PR):#[no_mangle] fn open() {}makecargo thang?no_mangleThis PR is a second attempt after #146505, where T-lang had some reservations about a blanket lint that does not check the signature, which is now done with this PR, and about linting of
stdruntime symbols when std is not linked, which this PR omits by not including any std runtime symbols (for now).invalid_runtime_symbol_definitions(deny-by-default)
The
invalid_runtime_symbol_definitionslint checks the signature of items whose symbol name is a runtime symbols expected bycore.Example
Explanation
Up-most care is required when defining runtime symbols assumed and used by the standard library. They must follow the C specification, not use any standard-library facility or undefined behavior may occur.
The symbols currently checked are
memcpy,memmove,memset,memcmp,bcmpandstrlen.@rustbot labels +I-lang-nominated +T-lang +needs-fcp +A-lints
cc @rust-lang/lang-ops
r? compiler
Footnotes
https://doc.rust-lang.org/core/index.html#how-to-use-the-core-library ↩