-
-
Notifications
You must be signed in to change notification settings - Fork 14.7k
Can CFI be made compatible with type erasure schemes? #128728
Copy link
Copy link
Open
Labels
A-control-flow-integrityArea: Control Flow Integrity (CFI) security mitigationArea: Control Flow Integrity (CFI) security mitigationA-sanitizersArea: Sanitizers for correctness and code qualityArea: Sanitizers for correctness and code qualityC-discussionCategory: Discussion or questions that doesn't represent real issues.Category: Discussion or questions that doesn't represent real issues.PG-exploit-mitigationsProject group: Exploit mitigationsProject group: Exploit mitigationsT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.T-opsemRelevant to the opsem teamRelevant to the opsem team
Metadata
Metadata
Assignees
Labels
A-control-flow-integrityArea: Control Flow Integrity (CFI) security mitigationArea: Control Flow Integrity (CFI) security mitigationA-sanitizersArea: Sanitizers for correctness and code qualityArea: Sanitizers for correctness and code qualityC-discussionCategory: Discussion or questions that doesn't represent real issues.Category: Discussion or questions that doesn't represent real issues.PG-exploit-mitigationsProject group: Exploit mitigationsProject group: Exploit mitigationsT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.T-opsemRelevant to the opsem teamRelevant to the opsem team
Type
Fields
Give feedbackNo fields configured for issues without a type.
There is a kind of common type erasure scheme used in Rust that goes something like this:
This is used, in particular, in the standard library for type-erased
fmtarguments.Unfortunately, CFI is not happy with this since the function pointer
opwas transmuted, and is not invoked at its original type. Our documented ABI compatibility rules are fine with this (and Miri also won't complain), but CFI is actually more restrictive than those rules and (at least in some configurations) rejects this call since caller and callee do not agree on the type of the argument.This is not good: ideally we could just tell people they can turn on CFI in any Rust program and expect it to work. In other words, ideally CFI would only reject programs that we consider buggy (in an official Rust lang/opsem sense), since they have either UB or erroneous behavior.
I am not sure what is the best way to fix this. I also know very little about what CFI can and cannot do (and I understand there's actually a bunch of CFI implementations that differ in their capabilities). My completely naive first idea would be to say that we have a new magic primitive type
Erasedand then declareErasedTypeAndOpas follows:Then we say that if caller and callee use different pointer types for their arguments, that is erroneous behavior unless one of them uses the special
Erasedpointee type, in which case the call is permitted. (Or maybe only the call site is allowed to useErasedlike that?)Is that something CFI can do -- basically have pointee type checking "turned off" if the call site uses
*const Erased? If yes, would this be an acceptable trade-off between still rejecting accidental type mismatches (and catching as many attacks as possible) while accepting legitimate type erasure patterns?Cc @rust-lang/opsem @maurer @rcvalle