fn_cast!
macro
#140803
Labels
A-control-flow-integrity
Area: Control Flow Integrity (CFI) security mitigation
A-rust-for-linux
Relevant for the Rust-for-Linux project
A-sanitizers
Area: Sanitizers for correctness and code quality
C-discussion
Category: Discussion or questions that doesn't represent real issues.
I-lang-nominated
Nominated for discussion during a lang team meeting.
needs-triage
This issue may need triage. Remove it if it has been sufficiently triaged.
PG-exploit-mitigations
Project group: Exploit mitigations
T-lang
Relevant to the language team, which will review and decide on the PR/issue.
Since Rust 1.76 we document that it's valid to transmute function pointers from one signature to another as long as their signatures are ABI-compatible. However, we have since learned that these rules may be too broad and allow some transmutes that it is undesirable to permit. Specifically, transmutes that change the pointee type or constness of a pointer argument are considered ABI-compatible, but they are rejected by the CFI sanitizer as incompatible. See rust-lang/unsafe-code-guidelines#489 for additional details and #128728 for a concrete issue.
This issue tracks a proposed solution to the above: Introduce a new macro called
fn_cast!
that allows you to change the signature of a function pointer. Under most circumstances, this is equivalent to simply transmuting the function pointer, but in some cases it will generate a new "trampoline" function that transmutes all arguments and calls the original function. This allows you to perform such function casts safely without paying the cost of a trampoline when it's not needed.The argument to
fn_cast!()
must be an expression that evaluates to a function item or a non-capturing closure. This ensures that the compiler knows which function is being called at monomorphization time.As a sketch, you can implement a simple version of the macro like this:
This implementation should get the point across, but it is incomplete for a few reasons:
fn_cast!
should be improved to work with functions of any arity.fn(&T)
tofn(*const T)
is allowed because&T
and*const T
is treated the same by KCFI. The compiler could detect such cases and emit a transmute instead of a trampoline.By adding this macro, it becomes feasible to make the following breaking change to the spec:
Here, the change is that ABI-compatible calls are considered EB. However, even without the spec change the macro is useful because it would allow for a more efficient implementation of #139632 than what is possible today.
This proposal was originally made as a comment. I'm filing a new issue because T-lang requested that I do so during the RfL meeting 2025-05-07.
The text was updated successfully, but these errors were encountered: