In multiple decades I can think of a handful of engine bugs that would have been prevented by rust - and those were largely preventable (and now are) in c++ as well.
It is possible for rust to be a safer language than c++ and to also not meaningfully change the security profile of the language.
It’s not just the jit, the interpreter and GCs are also subject largely - necessarily - no more protected by rust than c++.
In other words, even if you write a JS engine in Rust you could benefit greatly from this technique.
>why not work on isolating it behind it’s own process (there must be ways to do this securely while not giving up too much performance)?
Well, you make it sound like the easy answer. A good exercise would be to try implementing what you're proposing in a comment. Not necessarily going all the way, but enough to know why it might not be as straightforward as you think.
The people working on V8 are not completely clueless, the concept of moving things out of process or using a memory safe language is not going to be a novel idea that they'll just start working on now that someone clever thought of it.
> However, assuming these numbers are simply stored as integers somewhere in the JSObject, an attacker could corrupt one of them to break this invariant. Subsequently, the access into the (out-of-sandbox) std::vector would go out of bounds. Adding an explicit bounds check, for example with an SBXCHECK, would fix this.
Or use Rust
> Encouragingly, nearly all "sandbox violations" discovered so far are like this: trivial (1st order) memory corruption bugs such as use-after-frees or out-of-bounds accesses due to lack of a bounds check
Or use Rust
> Contrary to the 2nd order vulnerabilities typically found in V8, these sandbox bugs could actually be prevented or mitigated by the approaches discussed earlier. In fact, the particular bug above would already be mitigated today due to Chrome's libc++ hardening
Or use Rust
I'm not saying rewrite the entire thing in Rust, too expensive & would introduce new bugs in the JIT for questionable benefit. But at least mention that & also discuss the technical challenges why the sandbox mechanism isn't written in Rust & what it would take to address those.
Look, I'm not saying the V8 team is making the wrong decisions. My questions are an indication of the shallowness of the blog write-up - why not explain some obvious questions that come up for someone who reads it?
1) jitted javascript code with subtle bugs due to logic errors in the compiler (Rust's memory safety can't really help here)
2) Bugs in surrounding utility code and the interpreter (Rust can help, but running without a JIT entirely is too slow. Still, it's part of the attack surface either way)
3) Bugs in the sandbox implementation which helps mitigate bugs of the first kind (Rust can help)
AFAIK the main objection raised here is the article dismisses moving to a memory safe language because it doesn't help with 1, but then discusses 2 and 3 where in fact the issues are exactly where memory safety can help.
Take the fizzbuzz example with a missing bounds check. Rust can't prevent you from generating JIT code that omits a bounds check on an array and reads/writes out-of-bounds. The sandbox doesn't prevent out-of-bounds reads/writes, but it guarantees that they will only be able to access data inside the sandbox.
This means that logic bugs in the JIT compiler are no longer immediately exploitable. They must be combined with bugs in the sandbox implementation. The article's claim is that, unlike compiler bugs, sandbox bugs tend to be amenable to standard mitigation techniques.
This article isn't dismissing the value of memory-safe languages. It's identifying a problem space where current memory-safe languages can't help, and providing an alternative solution. Currently, every browser JS engine is written in C++, in part because Rust doesn't solve the big correctness problems. If the sandbox approach works, then using Rust for other parts of the engine becomes more appealing.
What hardening technique discussed in this article would be helped by Rust, and what specific feature of Rust would help?
> Encouragingly, nearly all "sandbox violations" discovered so far are like this: trivial (1st order) memory corruption bugs such as use-after-frees or out-of-bounds accesses due to lack of a bounds check. Contrary to the 2nd order vulnerabilities typically found in V8, these sandbox bugs could actually be prevented or mitigated by the approaches discussed earlier. In fact, the particular bug above would already be mitigated today due to Chrome's libc++ hardening. As such, the hope is that in the long run, the sandbox becomes a more defensible security boundary than V8 itself
You're making it sound like these are the same, the difference is the defaults
Unsafely accessing an element in C++
vec[i]
Unsafely accessing an element in Rust unsafe { vec.get_unchecked(i) }
One of these is screamingly obvious that something potentially unsafe is happening and should be audited more closely, that's the real difference. The cause of potential memory issues is isolated and searchable in `unsafe` blocks rather than being potentially anywhereWhy not just use grep?
Keep in mind that failed bounds checks are only 1 memory safety possibility for C++. Another common one is UB behavior which abounds all over the place in C++.
The only language security issue you have to worry about with safe Rust is that integers overflow by default in release mode which means you need to explicitly annotate summations that could cause a security exploit with `saturating_X`, `checked_add`, or `wrapping_add` depending on what behavior you want when you exceed the integer range bounds. In cases where security by default is more important, setting `overflow-checks` to `true` in the Cargo profile is better - that way you have to explicitly opt-in to wrapping behavior if you want more performance in the hot path.
vec[i]
Is safe in v8, blink, jsc, webkit, etc. Rust has a huge number of benefits over c++, but it hurts your argument if you refuse to acknowledge the actual environment the C++ is being used in and make objectively incorrect statements. It implies a lack of understanding of C++ and sounds like all you're doing is parroting other people's critiques without understanding the core issues, which undermines your message.That said it's still not particularly relevant here, because the issues being presented are bugs in the runtime. e.g. the runtime logic and state results in erroneous behavior. The bugs being discussed are not "you did not use a safe vec" or "you did not use Rc", it's "the size or bounds check in vec is incorrect" or "the ref counting in Rc is incorrect". Rust does not inherently stop those the runtime from having bugs, it simply statically limits where the exposure to unsafe operations can occur.
That's super relevant to program safety, but it's not relevant to safety in the JS VM runtime, where they're performing the operations that would be unsafe{} in rust as well.