5 ms·
The full write up shows that the exploit is based on a integer underflow that would be easily caught by Zig and any other programming language with sane runtime
by kristoff_it 5y ago
The full write up shows that the exploit is based on a integer underflow that would be easily caught by Zig and any other programming language with sane runtime checks.
Ironically enough this is the one class of bugs that Rust would not have prevented out of the box since the language defines integers to be wrapping and you need to manually opt into runtime checks.
The exploit:
https://secret.club/2021/04/20/source-engine-rce-invite.html https://secret.club/2021/04/20/source-engine-rce-invite.html
Wrapping in Rust:
https://huonw.github.io/blog/2016/04/myths-and-legends-about-integer-overflow-in-rust/ https://huonw.github.io/blog/2016/04/myths-and-legends-about...
https://scattered-thoughts.net/writing/how-safe-is-zig/ https://scattered-thoughts.net/writing/how-safe-is-zig/
I hope that explains how inappropriate is the tone of your comment.
- pjmlp 5y agoIf you want we can start counting examples if that is your point, I can pick another one that doesn't use integer overflow. What is the solution for use-after-free on Zig today, that isn't just like using Purify?
- pron 5y agoThat depends on what you mean by "just like." Zig does not make sound static guarantees about use-after-free, because those guarantees have other costs that Zig would rather not pay. This means that detecting the problem might requires some dynamic analysis. But that doesn't mean that it's "just like" such analyses in C, because Zig does make guarantees that are fundamentally different from C's. In particular, unless you resort to syntactically delineated constructs -- analogous to unsafe in Rust -- Zig does not have pointer arithmetic or arrays of unknown size. Unlike in C, in (the safe subset of) Zig every pointer is known and every object is known. This means that it's easier to build more precise and more effective mechanisms that detect such errors in Zig than in C. In other words, if you mean that use-after-free is handled in Zig in a manner that's very different from how it's handled in either Java or Rust and more similar to the general approach of how it's handled by various tools for C, then that's correct. If you mean that that general approach is just as (in)effective in Zig as it is in C, then that is incorrect. Because Zig is fundamentally more precise than C, analyses of Zig, even if they are conceptually similar to those done for C, can be more precise and effective.
- pcwalton 5y agoIt's hard to figure out exactly what you're saying, but I think you're trying to imply that bounds checks will allow for the development of some kind of novel use-after-free mitigation. Without a specific proposal I don't know why that would be the case. Zig is not meaningfully different from C++ when it comes to UAF.
- pron 5y ago> Zig is not meaningfully different from C++ when it comes to UAF. Without pointer arithmetic, unsafe casts (Zig is much easier to write without such casts than C, at least), unsafe unions, and unknown buffer sizes, the set of pointers in a Zig program can be well-defined, as pointers can come into being only in very specific ways (they have a simple provenance). Because the set of pointers is well defined, it can be precisely tracked and analysed. This means that 1. pointers can be traced even with arena allocators or perhaps even other kinds of pools (provided they cooperate with the tool) and 2. dangling pointers can be detected even without being dereferenced. This is simply not something that analysers for C or C++ can do (at least not nearly as easily). The way to think about it is that in Zig, when an object (including an allocator) is deallocated, you can invalidate the full set of pointers pointing to it, and that set it the only way of generating more pointers into it. That's not the case in C or C++. For one, pointers aren't well defined (unions); for another, a valid pointer could be used to create an invalid one.
- pcwalton 5y agoWhat you've described is a tracing garbage collector (to be pedantic, one where weak pointers are the norm, but the infrastructure and algorithm are essentially the same). In fact, I absolutely agree with you that Zig should adopt tracing garbage collection (a state-of-the-art generational concurrent one with bump allocation in the nursery), and doing so would eliminate most of my complaints about it. Unfortunately, it's unlikely that Zig will ever do this, given everything that I've seen about its design goals of being low-level with no runtime.
- 5y ago
- avgcorrection 5y ago> """Ironically""" That’s the case in production mode. Your link says that checks are added for overflow in debug mode. Presumably that also includes underflow.
- kristoff_it 5y agoExcept that what the user ends up receiving is not a debug build, but a full release, and we can safely assume that at Valve there was no test case where someone would craft a malicious invite with rcon parameters. This is why Zig maintains these checks in ReleaseSafe mode and gives you wrapping operators (+%=, etc) when that's what you want.
- avgcorrection 5y ago> Except that So you’re saying that I was correct. Good to know.
- tialaramex 5y agoIf you want these checks in "ReleaseSafe" mode of your Rust, you can choose to make such a build profile: [profile.ReleaseSafe] overflow-checks = true And of course Rust has both Wrapping types and wrapping versions of each integer operation if you want those, although I think we can be confident that the sort of person who is shipping release builds with overflow checking isn't thinking far enough ahead to have decided what should actually happen when their variabes under/overflow so giving them the option is redundant. Given that the problem here is they're Wrangling Untrusted File Formats and, unsurprisingly, they failed to do so Safely, they likely should have used WUFFS rather than Rust, or Zig, or any general purpose language.
- tialaramex 5y agoThe main thing that underflow is getting them is a pointer manipulation which lets them do a stack smash in the ZIP code. Needless to say safe Rust does not allow you to screw up pointer arithmetic and perform a stash smash, even if you can't be bothered to use checked arithmetic and so you underflow. The equivalent underflow mistake in Rust probably panics. However the RCON trick at the heart of Steam which is powering this lets you run any command as the victim if they accept your "invite" so crashing their game is almost certainly already an option without the underflow.