5 ms·
> All type checks are also vulnerable. For example, if some type contains an integer at offset 8 while another type contains a pointer at offset 8, then an atta
by ams6110 9y ago
> All type checks are also vulnerable. For example, if some type contains an integer at offset 8 while another type contains a pointer at offset 8, then an attacker could use Spectre to bypass the type check that is supposed to ensure that you can’t use the integer to craft an arbitrary pointer.
So, even if WebKit were entirely written in Rust, we'd still be fucked. I'm really starting to think it's about time for me to get out of this business.
- pizlonator 9y agoRight, programming-language-based security mechanisms that rely on emitting runtime checks are broken and you need something like index masking or pointer poisoning to fix them. Rust could use those fixes as well.
- iainmerrick 9y agoWhy does Rust need those? Those are things you need when running untrusted code in a sandbox. Is there a scenario where Rust is used that way? There's WASM, but in that case the extra checks need to be applied at the WASM level, not the Rust level.
- josephg 9y agoSomething I keep coming back to in all this is that maybe we should be surprised that it’s even possible to share a CPU between mutually untrusted programs, let alone do it in so many contexts. How do we stop his entire class of bugs? What is the Rust for CPU design?
- 6nf 9y agoCPUs tend to have multiple cores these days, would it be possible to assign (in software) all kernal space work to one or more dedicated cores to mitigate some of the risks?
- politician 9y agoYes, well, close. > Since the 2010 Westmere microarchitecture Intel 64 processors also support 12-bit "process-context identifiers" (PCIDs), which allow retaining TLB entries for multiple linear-address spaces, with only those that match the current PCID being used for address translation.[19][20] https://en.wikipedia.org/wiki/Translation_lookaside_buffer#PCID https://en.wikipedia.org/wiki/Translation_lookaside_buffer#P... HN discussion: https://news.ycombinator.com/item?id=16094349 https://news.ycombinator.com/item?id=16094349
- vardump 9y agoThat's just Meltdown workaround. Spectre was more relevant to context.
- megablast 9y agoWith a shared cache.
- gpderetta 9y agoSome of the newer Intel server CPUs allow statically partitioning the shared L3 cache between cores. It might (or not) work as a way to reduce side channel communications between cores.
- abecedarius 9y agoI always liked the https://en.wikipedia.org/wiki/J%E2%80%93Machine https://en.wikipedia.org/wiki/J%E2%80%93Machine idea: gobs of processors each with a small private memory (nothing shared), in a fast mesh network. It fits with physics: accessing local memory can be fast, while distant memory physically just can't. But even if it's really all that, it's just so different from the architectures we've put so much work into or on top of.
- estebank 9y agoThat sounds like a more extreme version of what the Cell[1] was supposed to be. Developers seemed to think that developing for that architecture was really painful, specially compared to other contemporary console platforms. I'd love it if the progress being made in the industry got us to actually being able to exploit the full potential of such architectures. [1]: https://en.wikipedia.org/wiki/Cell_(microprocessor) https://en.wikipedia.org/wiki/Cell_(microprocessor)
- abritinthebay 9y agoIt was painful - mostly because we don't have good tools for that sort of thing and most of our programming sort of hides the idea of multiple CPUs and pretends it's all working at once (in terms of us writing the code anyhow). It's all abstracted in a very linear way. Changing all that will take a lot of time if we do.
- gpderetta 9y agoActually multiple CPUs are not normally hidden in mainstream programming languages [1]: i.e. threads are visible. The fiction that it is maintained by the programming languages and hardware is that of a single, coherent address space, which Cell very much did not have. [1] outside of parallel iteration/folding constructs.
- abecedarius 9y agoYeah. Erlang seems to show that there is a path from here to there, but the Erlang-ish world is tiny relative to the whole industry.
- frik 9y agoYes, we need a many-core CPU. Then every program can run on a core. And we can use MPI, CILK, etc to run parallel programs. Each CPU could run its own small operating system, or using a micro kernel OS. Writing algorithms in parallel manner isn't as complicated as make to believe you, a lot can be rewritten based on cookbooks/patterns. Intel developed a many-core CPU (72 CPU cores) called Xeon Phi: https://en.wikipedia.org/wiki/Xeon_Phi https://en.wikipedia.org/wiki/Xeon_Phi Unfortunately they drifted of the target (instead of making it the successor of x86-64). For Javascript engines, it would help if the offer an optional fallback "Javascript interpreter" instead of JIT. A JIT is basically at the moment insecure, especially when running untrusted code. The same goes for WebAssembly, let the user deactivate execution/support of it. Please allow end user to enable an alternative JS interpreter for high security things like online banking.
- eecc 9y agoWell, Meltdown mitigation involves unmapping as much Kernel as possible when switching modes. It’s so much overhead that I wonder if uK messaging and process context switching is cheaper and faster.
- om2 9y agoInterpreters generally do a lot of branches, so they are also vulnerable to Spectre.
- pjmlp 9y ago> What is the Rust for CPU design? Intel iAPX 432 could have been it, but they did a lousy job implementing it. https://en.wikipedia.org/wiki/Intel_iAPX_432 https://en.wikipedia.org/wiki/Intel_iAPX_432
- lower 9y agoNote that the article talks about type checks for the JavaScript code that is being executed by WebKit, not type checks in the implementation of WebKit itself. So there are two different kinds of type checks involved here.
- pizlonator 9y agoWe are using pointer poisoning to protect type checks in WebKit itself as well as type checks in the JavaScript code we execute. We are using index masking in WTF::Vector and WTF::StringImpl, which are used both for JavaScript execution and for lots of other things in WebKit that want a vector or a string.
- rcthompson 9y agoDoesn't Rust do all its type checking at compile time, not run-time? (Not to say that a correctly-written Rust program wouldn't be vulnerable to Spectre for other reasons, of course.)
- pizlonator 9y agoRust has algebraic types, so Spectre could be used to train the branch predictor to take one type case of your match statement, and then have that case taken when the enum is actually in a different shape. That's a violation of the type system.
- FreeFull 9y agoIf I'm reading this correctly, the issue isn't with the types of the language you wrote the Javascript engine in, but with Javascript's types. All major Javascript engines are written in C++, which also does all its type checking at compile-time.
- pizlonator 9y agoNot quite. Our C++ code often does static_cast<> as a downcast based on testing some condition. That's a run-time type check. This isn't solely about those type checks that were implemented using some built-into-the-language type checking mechanism. Also, C++ does have a dynamic type check primitive (dynamic_cast). We are mitigating these branch-based type checks with pointer poisoning, and I don't think that those changes are biased in favor of C++ or JS, since both are vulnerable.
- rcthompson 9y agoAh yes, that makes sense.
- kibwen 9y agoI'm actually not sure what that passage is trying to imply at all, I've not seen any prior remarks that Spectre has that sort of implication. AIUI, Spectre lets you read arbitrary memory, not write it, so I'm not sure what they mean by "bypass the type check" and "craft arbitrary pointer". Here's another quote later on: > But Spectre could theoretically involve any branch that enforces security properties, like the branches used for type checks in JavaScriptCore. I get the impression this is all referring to JIT'd JS, not to the C++ (or Rust etc.) code powering the underlying engine (where all typechecking is done at compile-time anyway). Of course having the JS engine written in Rust would still allow the same, but it's been known for a long time that Rust's typesystem can't do squat to verify the correctness of dynamically-generated code; it's part of the reason why Mozilla only bothered to kick off a rewrite of Gecko and not SpiderMonkey.
- pizlonator 9y agoIt's common for C++ code to do type checking dynamically. In WebKit we do this by rolling the type checks ourselves. With RTTI, you can do dynamic type checks using the build-in dynamic_cast primitive. Our changes, particularly the ones having to do with pointer poisoning, are meant to protect C++ code that does dynamic type checks in addition to JIT'd JS code that does dynamic type checks. Rust's `match` statement is a dynamic type check just like C++'s `dynamic_cast`. I bet you it's implemented using branches.
- kibwen 9y ago> Rust's `match` statement is a dynamic type check just like C++'s `dynamic_cast`. I wonder if this is a case of a difference in terminology, because enum variants (the branches in `match` expressions) aren't considered types in Rust, and have no interaction with Rust's typechecker (Rust always has to assume that every instance of an enum can be any variant, even in cases where we as the programmer know that only one variant is possible). At the same time I'm still unclear on what the OP is trying to imply. To reiterate, AIUI Spectre can only read, not write, privileged memory, so it's impossible for a Spectre attack to trick the engine into believing that (to use Rust terminology) an instance of an enum is a variant that it isn't. Am I incorrect?
- vasili111 9y ago> I'm really starting to think it's about time for me to get out of this business. Maybe it is time to move to IT security business?
- roca 9y agoInterestingly you could apply these mitigations in Rust itself --- array index masking where Rust has array bounds checks, and pointer obfuscation where you check the variant tags of algebraic types. Some extra work would be required for unsafe Rust code. That would automatically protect almost all Rust code, whereas most C and C++ code would have to be handled manually.