-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
CFI: core and std have explict CFI violations #115199
Comments
I'm concerned about transmuting to a more refined type being rejected by LLVM's type-directed CFI. Specifically,
Intuitively, because I realize it may be unpleasant, but the reason why Rust does this? https://www.youtube.com/watch?v=Y-Elr5K2Vuo Rust's |
Related: |
Thank you for all the information, @workingjubilee and @ChrisDenton! LLVM CFI does support those patterns (as C and C++ also use those), the casts/transmutes just have to be adjusted at the indirect call sites. You can see what I just did for (1) in the PR. This is not a characteristic of LLVM CFI itself, but many fine-grained type-based CFI implementations that perform function pointer type testing at the indirect call site. It's actually common for large code bases to have those CFI violations when CFI support is initially implemented. For example, the Linux kernel had many. I'm actually surprised I've found only three so far for core and std, and this is actually very good. |
I am slightly less concerned with "large codebases" with small armies of experts to support them. Many of those experts are well-paid for their time, and looking after those who are not is a complex task. Rather, I care about the ones maintained by some Jane Doe who makes a chat program that is a hodgepodge of miscellaneous C that is exposed to the network and eminently exploitable, and who decides to add Rust to handle the most brutally-exposed network-facing parser. I care about the volunteer maintainers of some obscure distro I've never heard of rebuilding it and trying to add compiler-driven hardening and running into complications. Not because any one such case is terribly important in security terms, but because there are millions of such cases in a very long tail. So I am attentive to when CFI violations trigger on, frankly, trivialities, ones that require intimate knowledge of C99 or LLVM to explain. They should care more for intuitively obvious violations, not for pointers being coerced to/from the "anything-pointer". And to be more precise, |
Works around rust-lang#115199 by temporarily disabling CFI for core and std CFI violations to allow the user rebuild and use both core and std with CFI enabled using the Cargo build-std feature.
I hear your concerns and I wish fine-grained type-based CFI was an enable and forget mitigation as many others because I want as many users to use it as possible, but unfortunately it does require some code care and maintenance for use. The violation in (1) is actually an uncommon case of a weakly-linked C or C++ callback/function pointer being called from Rust across the FFI boundary where the function signature it was being cast to at the call site was different from the function definition of the function linked. Let me know if you have any suggestions of how this could be improved and I'll be happy to take a look at it. |
I mean, my question is, really, "What bug or exploit, exactly, are we preventing by prohibiting an argument of type |
I should note, here: It feels intuitive and obvious to me what bugs we're preventing by prohibiting, say, But in C, the main difference between |
Besides assisting with the bugs you mentioned, for example, not allowing an attacker to redirect the control flow to functions with It's not that If the user wants to trade maintenance for a coarser-grained protection, they can use the |
Except they cannot, can they? Your code comments in that PR allude to the problem: People building the code may have to decide how they bind against other code that may have already been built with various CFI options. This makes such choices virtually irrelevant on any distros which are not fully source-based, at least, for anyone but the head maintainers. And you, of course. Meanwhile, Relying on configuration flags during the build to ameliorate this problem causes de facto ecosystem and dialect splits which we have struggled mightily in the past to prevent. If I understand correctly, one has to link and build the entire program with this option to benefit from it, and it effectively prevents anyone from benefiting unless all their dependees also comply. |
Besides, it's also eminently the case that, having done a |
Generalized pointer metadata is always included by Clang in C or C++ -compiled code regardless if the pointer generalization option is specified (as does the Rust compiler). |
??? Is LLVM going to treat the fact that some kinds of normalization must defer to other compilation units while others do not as a bug? |
Fixes (3) of rust-lang#115199 by transforming function items, closures, and Fn trait objects into function pointers.
Fixes (3) of rust-lang#115199 by transforming function items, closures, and Fn trait objects into function pointers.
Works around rust-lang#115199 by temporarily disabling CFI for core and std CFI violations to allow the user rebuild and use both core and std with CFI enabled using the Cargo build-std feature.
…ngjubilee Disable CFI for core and std CFI violations Work around rust-lang#115199 by temporarily disabling CFI for core and std CFI violations to allow the user rebuild and use both core and std with CFI enabled using the Cargo build-std feature.
Fixes (3) of rust-lang#115199 by transforming function items, closures, and Fn trait objects into function pointers.
Fixes (3) of rust-lang#115199 by transforming function items, closures, and Fn trait objects into function pointers.
Fixes (3) of rust-lang#115199 by transforming function items, closures, and Fn trait objects into function pointers.
Fixes (3) of rust-lang#115199 by transforming function items, closures, and Fn trait objects into function pointers.
Fixes (3) of rust-lang#115199 by transforming function items, closures, and Fn trait objects into function pointers.
Fixes (3) of rust-lang#115199 by transforming function items, closures, and Fn trait objects into function pointers.
Fixes (3) of rust-lang#115199 by transforming function items, closures, and Fn trait objects into function pointers.
Fixes (3) of rust-lang#115199 by transforming function items, closures, and Fn trait objects into function pointers.
I was unable to find this in the current code. Including a permalink to the relevant code would make it much easier for others to look into what is happening here. :)
Same here, what is this about? There is no |
Oh, yes there is. But I don't see any transmute of function pointers here so I don't see the CFI violation. |
Fixes (3) of rust-lang#115199 by transforming function items, closures, and Fn trait objects into function pointers.
@rustbot label A-sanitizers |
Even though the user can now rebuild both
core
andstd
with CFI enabled (see #90546) using Cargo build-std feature (which is recommended), both have explicit CFI violations that prevent the compiled program from functioning with CFI enabled.So far, I've identified three CFI violations:
std::sys::unix:thread_local_dtor::register_dtor
weakly links__cxa_thread_atexit_impl
and and the Rust compiler currently omits weakly function definitions and its metadata from LLVM IR.core::fmt::rt::Argument
transmutingformatter
innew
and indirectly branching to/calling it infmt
.std::panicking::r#try
) use ofFnOnce
explicitly violating CFI .std::sys::unix::weak::syscall
macro weakly links functions and the Rust compiler currently omits weakly function definitions and its metadata from LLVM IR.I'm not sure if those are all CFI violations, but all core and std tests pass after disabling CFI in those locations with the
no_sanitize
attribute.The text was updated successfully, but these errors were encountered: