13 ms·
The best WebAssembly runtime may be no runtime
- sp332 3y ago"Take existing C code, compile it to WebAssembly, transpile it back to C, and you get the same code, but sandboxed." Nice!
- PaulHoule 3y agoIt helps so much that the WebAssembly "virtual machine" promises so little (compared to, say, Java.)
- Lerc 3y agoThat really epitomizes the proverb, Either make something so simple that it obviously has no flaws or make something so complex that no flaws are obvious.
- IshKebab 3y agoThis is already in Firefox: https://rlbox.dev/ https://rlbox.dev/
- chrismorgan 3y agoI strongly recommend reading through this site if this topic interests you at all (which it probably does if you’re reading this comments thread!). Lot of explanation and detail about how it works, what it does, and how to use it yourself. It’s good stuff. And yeah, it’s been in Firefox for two years now: https://hacks.mozilla.org/2021/12/webassembly-and-back-again-fine-grained-sandboxing-in-firefox-95/ https://hacks.mozilla.org/2021/12/webassembly-and-back-again....
- turbolent 3y agoJust to clarify: Compared to wasm2c, w2c2 does not (yet) have sandboxing capabilities, so assumes the translated WebAssembly module is trustworthy. The main "goal" of w2c2 so far has been allowing to port applications and libraries to as many systems as possible.
- westurner 3y agohttps://gvisor.dev/docs/architecture_guide/platforms/ https://gvisor.dev/docs/architecture_guide/platforms/ : > gVisor requires a platform to implement interception of syscalls, basic context switching, and memory mapping functionality. Internally, gVisor uses an abstraction sensibly called Platform. Chrome sandbox: https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/design/sandbox.md https://chromium.googlesource.com/chromium/src/+/refs/heads/... Firefox sandbox: https://wiki.mozilla.org/Security/Sandbox https://wiki.mozilla.org/Security/Sandbox Chromium sandbox types summary: https://github.com/chromium/chromium/blob/main/docs/linux/sandboxing.md#sandbox-types-summary https://github.com/chromium/chromium/blob/main/docs/linux/sa... Minijail: https://github.com/google/minijail https://github.com/google/minijail : > Minijail is a sandboxing and containment tool used in ChromeOS and Android. It provides an executable that can be used to launch and sandbox other programs, and a library that can be used by code to sandbox itself. Chrome vulnerability reward amounts: https://bughunters.google.com/about/rules/5745167867576320/chrome-vulnerability-reward-program-rules#reward-amounts https://bughunters.google.com/about/rules/5745167867576320/c... Systemd has SystemCallFilter= to limit processes to certain syscall: https://news.ycombinator.com/item?id=36693366 https://news.ycombinator.com/item?id=36693366 Nerdctl: https://github.com/containerd/nerdctl https://github.com/containerd/nerdctl Nerdctl, podman, and podman-remote do rootless containers.
- 10000truths 3y agoThis feels like a really roundabout way to implement something that the compiler should be responsible for. All the pain and effort of C -> WASM -> C could be avoided if GCC or clang had some option to add bounds checking instrumentation for each memory access in the compiled output.
- ithkuil 3y agoNaCl solved that long time ago
- phickey 3y agoit solved it so well that nobody outside of chrome ever implemented nacl, and chrome's nacl team became their webassembly team
- ithkuil 3y agoThat's perfectly compatible with the claim that from a technical pov pnacl solved the issue. There were other good reasons why that wasn't ultimately the road taken, but they largely were know technical reasons.
- lambda 3y agoYeah, WASM was the result of taking a look at NaCl, realizing it could never be specified and independently implemented, and writing a spec for something better that could. WASM is superior in pretty much all ways to NaCl other than being a bit more time to go through the whole specification and implementation process. NaCl was a great prototype, and WASM is a much more polished result because of it.
- jancsika 3y agoOoh, I'd love to know a few more details about both. What kept NaCl from being independently implemented? And what did WASM learn from NaCl? Edit: ah, someone already mentioned NaCl being CPU-specific.
- deleted 3y ago[deleted]
- mattsan 3y agoOh dude imagine using cosmocc on the final C code and have a single binary that runs on 6 different OS's
- IshKebab 3y agoI think it would be more interesting to compile to LLVM IR, so you don't have to deal with C. Part of the appeal of Wasm is that it's a modern system that doesn't have to deal with 70s nonsense.
- shermantanktop 3y agoC is not a large language, and a transpiler can choose to generate code that only uses a subset of the features of the language, and can choose to be consistent about safety mechanisms that the underlying language doesn't guarantee. When you say "70s nonsense" are there specific C features you are concerned about? I would think that transpilation can just avoid bad practices like passing around void * pointers and then casting them optimistically, or even the use of char * for strings in favor of a bounds-checked alternative.
- lmm 3y agoC can't represent lots of information that would be useful, e.g. while C99 has a limited "restrict" function, you can't express any more complex detail of "these things can only alias under these circumstances". If the hardware supports doing anything useful with sum types (e.g. atomic operations), there is no way to expose that in the C model. C specifies a concept of trap representations but anything you would actually do with them is undefined behaviour, so you can't write code that e.g. safely errors out when someone tries to use an uninitialized pointer. Even for arithmetic on standard hardware, the ability to fully express even quite basic things is limited - you can't write code that e.g. permits signed overflow to occur and handles it if it does. You effectively can't use any floating point rounding modes except the most broken one, at least not if your code ever uses threads. I'm sure there's more.
- turbolent 3y agoYou do not have to deal with the generated C, simply consider it the IR. The main benefit of generating C over LLVM IR is portability: C is supported by far more systems than LLVM can target. For example, it enables porting Rust applications to Mac OS 9 (https://twitter.com/turbolent/status/1617231570573873152 https://twitter.com/turbolent/status/1617231570573873152), or porting Python to all sorts of operating systems and CPUs (https://twitter.com/turbolent/status/1621992945745547264 https://twitter.com/turbolent/status/1621992945745547264). The main "goal" of w2c2 so far has been allowing to port applications and libraries to as many systems as possible. For more information, see the README of w2c2.
- legulere 3y agoThe difficulty of sandboxes is to offer a usable, useful API to the outside world that is still secure. Operating system processes would perfectly fine sandboxes except for the huge hole current syscalls and other out of process APIs rip.
- spankalee 3y agoI love the idea of AOT WASM compilers, but they will definitely be complicated by WASM GC. I wonder if compiling to another GC language, like Go, might help, or if they can just use a GC library like tgc or Oilpan.
- csjh 3y agoI'd imagine the majority won't support GC, at least not for some time
- rockwotj 3y agoI mean Kotlin already does, I believe Java will too, but you’re right that python, js, ruby, golang, rust and c/c++ don’t use Wasm GC
- csjh 3y agoThe subject of the parent comment was about AOT WASM compilers - definitely languages using WASM GC right now, and (hopefully) more to come
- slimsag 3y agoI think WASM has a problem which isn't really noticed/worked on yet (at least, that's my perspective) The WASM GC will be good, not because it's a GC, but because it would allow languages compiled to WASM to interoperate with e.g. the DOM using the same memory manager so you're not e.g. manually managing the memory of DOM objects while JS may hold references to them according to the terms of the GC. But this also means the DOM API will be tied to the GC, right? I don't know this for fact, but logically that seems correct. So languages that do NOT have good use of the GC are going to be at a disadvantage when it comes to interacting with the DOM, presumably. Meanwhile, the runtimes of languages like Go and modern Java (after Java gets goroutine-like behavior from project loom) rely on small ~8kb stacks and the ability to swap the stack to a new goroutine using setjmp/longjmp - but WASM isn't a traditional register machine like x86 ASM, instead it's more of a stack machine.. with no setjmp/longjmp. So not only do languages like Go and Java need to 'decouple' their runtimes for goroutine-like behavior from their GC and make use of the WASM GC instead (which is not tailored to the usage patterns of such languages), but they also need to emulate their own register machine 'on top of' the WASM stack machine so that their goroutine-like behavior works in WASM. Back in 2017 my coworker did this for Go, and so far as I know the implementation has not moved on from that approach since because there is no alternative. So for Go and Java, you'd be working with a GC that isn't designed for the language and presumably that has performance implications.. and you'd be working with an emulated register machine on top of a sandboxed stack machine (WASM)... that all starts to seem quite a bit far from 'low level like native code' that WASM aims to promise. I hope I'm wrong, but I fear Go/Java do not have a bright, performant, future when it comes to WASM. Zig, C++, Rust - all probably have a bright future here. But the challenges for higher level languages are stark [0] https://news.ycombinator.com/item?id=32078190 https://news.ycombinator.com/item?id=32078190
- nbittich 3y agoSo you take a language that compiles to wasm, then you take your wasm output and transpile it to c? Welcome to the frontend world I guess
- pjs_ 3y agoBack to the good old days of downloading and running .exes from the public internet :)
- theonething 3y agoThe first time I did that was at an internship when I needed a music player to listen to my music CDs on my work PC's CD-ROM drive while working. Searched for it (probably on Lycos), found one, downloaded the .exe, launched it, popped a CD in. When I pressed play and heard the music start in my headphones, I had the feeling I just performed magic. Big smile on my face as I went back to work. Viruses, etc. weren't in our reality in those naive and heady days.
- jrockway 3y agoI remember people being worried about viruses pre-Internet. You had to be careful about borrowing software from friends and things like that.
- thenickdude 3y agoIndeed, my DOS machine got infected by a Jazz Jackrabbit disk borrowed from a friend. I had a text-mode launcher menu for running programs, and that had an "anti-virus" feature built-in that checksummed programs, and alerted you if their checksum ever changed (since these viruses spread by infecting .exes), which is how I found out about it!
- afandian 3y agoBe fair, it’s .ocx files.
- pjmlp 3y agoAll the stuff trying to use WebAssembly outside the browser, without looking into all bytecode formats that have trailled the same path for decades since early 1960's is getting tiresome.
- alex_suzuki 3y agoBut… it‘s new!
- deleted 3y ago[deleted]
- mort96 3y agoDo you have any actual interesting critiques of the wasm bytecode format and what it has failed to learn from Java bytecode or CLR bytecode or whatever? Because that would be interesting, and I'm sure there are design choices to analyze and criticise. Empty references to the potential existence of problems isn't very interesting though.
- pjmlp 3y agoStart with Burroughs Large Machines from 1961, do a stop at Xerox PARC, visit ETHZ, Bell Labs, Amsterdam University, Caltech, Tao Group, UCSD, IBM and Unisys mainframes, Microsoft R&D, and already there are several bytecodes to look into. The hype around WebAssembly is also not very interesting for those of us that have read hundreds of papers on those bytecodes, but hey there is VC money to burn.
- jrockway 3y agoI think that network effects win over technical merit every time, and this time WebAssembly has the momentum. I think it's pretty neat that you can take a web server written in C++, implement some new compression algorithm in Go, and then have that web server compress pages with your Go code without having to recompile the webserver or touch any of its code. That's what WebAssembly outside of the browser offers; you can just write stuff in your language of choosing for other products. All the VC hype just means that everyone picked the same backend so there is some possibility of traction. In reality, some flaws are preventing adoption. C and Rust are pretty much the only viable languages with WebAssembly support, and since those are also the chosen implementation languages for runtime, nobody is really deriving this benefit. (Anything with a runtime seems to fail for programs beyond "hello world".) (I tried a "real program" and WebAssembly once, but it ran out of memory when compiled with either gc or tinygo. We had to write the browser side of things in Javascript, which was a shame. The code in question was: https://github.com/pachyderm/pachyderm/blob/master/src/internal/archiveserver/encode.go#L22 https://github.com/pachyderm/pachyderm/blob/master/src/inter.... Somewhat complex, but not so complex you can't do it in Javascript. So a bit of a shame that WebAssembly didn't work out.) The other thing that I think WebAssembly should fix (but people seem to want to kill me when I mention this) is that the Typescript compiler should just output WebAssembly and we can forget about node_modules and Webpack and that whole nightmare. There is AssemblyScript, but it doesn't run React, so doesn't matter for this use case. Someday I will go insane and just compile node or deno to WebAssembly and just ship the whole VM with my app embedded in it. Then you'll have a real reason to want to kill me! Muahahaha.
- prmph 3y agoThis whole webassembly thing does not seems like it will solve real problems, The more I learn about it, the more it seems like another kludge built on top of the kludges we have now. Why doesn't HTML get an overhaul, with a massive set of new and actually useful and styleable components (e.g., data table with sorting/paging/filtering capabilities built right into the browser), ability to scope CSS, and things like that? That's how the shittiness of web dev can actually be solved so that reliance of client side code can be drastically reduced
- ajross 3y agoWebassembly doesn't solve the same problems as styleable components, scoped CSS, and things like that though. Webassembly solves the problem of "how do I deploy this software that isn't written in Javascript to the browser client?". Sure, it also is sorta about performance, but JS interpreters are actually shockingly fast in the modern world. Mostly wasm is about moving your existing C++ code (or whatever) for your existing formats or algorithms or tools into a web/mobile client without having to hire someone to recode it all in TypeScript or whatever. That's not sexy, but it's valuable.
- dudus 3y agoI think webassembly actually acts as a reliable target when building software. Every platform will have a fast web assembly runtime. So you just build for it and you can deploy for any platform mobile or desktop.
- brundolf 3y agoIt's about much more than web browsers at this point, in fact I think its biggest impact will end up being outside of them
- Matheus28 3y agoIt doesn’t look like you know what webassembly is supposed to solve. It has nothing to do with styling. It’s about deploying native code in a safe sandboxed way. It’s not just about web pages. My use of wasm is web games that perform a lot better than anyone could achieve with JavaScript.
- VikingCoder 3y agoSome language -> WASM -> C -> Cosmopolitan C Compiler -> Actually Portable Executable that runs on just about anything...?
- CalChris 3y agoWhy not just Some Language -> C -> CCC -> executable? What is WASM bringing to the table? Or better yet Some Language -> MLIR.
- turbolent 3y agoVery few languages have "Some Language -> C" or "Some Language -> non-common OS / arch combo". The "just" part is a whole new backend, which is a massive amount of work for common languages. But it turns out many languages do have "Some Language -> WASM" now. WebAssembly brings portability to the table.
- turbolent 3y agoExactly!
- kllrnohj 3y agoNo more than "Some language -> its native toolchain" already is or isn't.
- VikingCoder 3y agoDid you read up on Cosmopolitan C Compiler when it was discussed here? No, it's not exactly the same amount of portability as some language and its native toolchain. If you give me source code in some language that I can transpile to C or C++, or into WASM (and then into C), then I can give you a single file which can be executed on Linux, BSD, Mac, or Windows. That's not remotely the same thing as "its native toolchain." You, a developer or tech savvy person, might not see any difference. But if I hand a non-tech-savvy person a file and they can just run it, no matter what OS they're using - with no pre-requisites - that's kind of magic.
- ncruces 3y agoI don't really buy the security argument if: “some traditional WebAssembly compilers can decorate memory accesses with bound-checking code. w2c2 currently can’t, but it totally could.” Also, in my experience, naive bounds checking will eat up a lot of cycles. But maybe the C compiler can eliminate a bunch of them.
- flohofwoe 3y agoAFAIK the (software) bounds checking isn't necessary if the WASM heap has large enough "guard bands" at the top and bottom to trap memory accesses (because the WASM bounds checking isn't fine-grained, but only against the WASM heap boundaries). E.g. see here: https://docs.google.com/document/d/17y4kxuHFrVxAiuCP_FFtFA2HP5sNPsCD10KEx17Hz6M/edit#heading=h.tbi7hpbheoai https://docs.google.com/document/d/17y4kxuHFrVxAiuCP_FFtFA2H... (I'm not 100% sure but I think that at least V8 has implemented this in the meantime)
- azakai 3y agoYes, that is exactly how production Wasm VMs optimize heap accesses. Bounds checks cause no overhead as a result. That's the case in all modern browsers, as well as in wasm2c.
- keithwinstein 3y agowasm2c (part of WABT) does this transpilation in a spec-conforming way; it passes all* the WebAssembly tests and enforces the memory-safety and determinism requirements and the rest of the spec. The memory bounds-checking itself doesn't have a runtime performance impact because it's all done with mprotect() and a segfault handler. (There are some other differences between w2c2 and wasm2c that also have to do with spec-conformance and safety; e.g., enforcing type-safety of indirect function calls. This costs <4 cycles but it's not zero.) Re: bounds checks, the thing that consumes cycles isn't the bounds check itself, it's Wasm's requirement that OOB accesses produce a deterministic trap, even if the result of an OOB load is never observed and could be optimized out. wasm2c has to prevent the compiler from optimizing out an unobserved OOB load, and that forced liveness defeats some compiler optimizations (probably more than it needs to). But even with all that, we're talking like a <30% slowdown compared with native compilation across the SPECcpu benchmarks. If you want to transpile arbitrary Wasm to native code in a spec-conforming way, you're probably better-off using wasm2c (which, disclosure, I work on). If you trust the Wasm module, or you're good with the isolation you get from your operating system and don't need Wasm's determinism, w2c2 seems great. Both of these are far less battle-hardened than V8 or wasmtime, especially when you include the fact that now you need an optimizing C compiler in the TCB. --- * The Wasm testsuite repo has recently merged in the "v4" version of the exception-handling proposal, and WABT is still on "v3". But it does pass all the core tests (including tail calls) at least until GC is merged.
- flohofwoe 3y agoFirefox actually uses this technique to harden some components: https://hacks.mozilla.org/2021/12/webassembly-and-back-again-fine-grained-sandboxing-in-firefox-95/ https://hacks.mozilla.org/2021/12/webassembly-and-back-again...
- azakai 3y agoI like the term "VMless" (or "VM-less") for this. (Inspired by "serverless" I guess)
- apatheticonion 3y agoHuuury up. I need WebAssembly in my life. My two use cases are: 1) Web UIs with DOM access from wasm/threads and all that goodness. I want to write my entire web application as a Rust wasm application without thunking through JS. 2) A native application with dynamic plugins as WASI libraries. Writing CLI tools and desktop applications in Rust with a practical method of loading plugins dynamically is .
- maxflowrn 3y agofor 1) there is https://yew.rs https://yew.rs
- triyambakam 3y agoDoes Yew provide any kind of assurances on runtime errors?
- galdosdi 3y agoNo, yew.rs does not address this problem (WASM can't directly touch the DOM or other browser APIs such as WebGPU, only JS can) It just wraps around calls to JS. Everytime you use yew.rs or some other "pure rust" or whatever framework, it's making tons of JS calls under the hood. This is OK for some purposes, but if you're trying for performance on a workload that isn't CPU-bound, it sucks. And it's another abstraction layer that's bound to leak, I imagine. This is a significant issue with WASM that a lot of us are waiting with bated breath to be fixed. We want to really be able to target the web browser with NO javascript involved.
- flohofwoe 3y ago> WASM can't directly touch the DOM or other browser APIs such as WebGPU And that's a good thing. Both APIs (DOM and to a lesser extent WebGPU) are built on top of the Javascript object model. Trying to map the JS object model to WASM inside the WASM spec would be a really bad idea. > This is a significant issue with WASM It's a non-issue really, brought up again and again by people who didn't really look into WASM in detail yet and what it is good for (hint: not to replace the HTML+CSS+JS combo). The DOM is so slow to begin with that going through a (potentially automatically generated) Javascript shim from WASM wouldn't move the performance needle. For APIs like WebGPU it would make more sense to have a WASM-friendly API, but that's really a design wart of WebGPU's Javascript API (WebGL actually did a slightly better job there). And besides, the overhead of calling from WASM into web APIs is mostly negligible compared to the overhead that happens inside the API (speaking specifically of WebGL and WebGPU here from my own experience).
- AndrewDucker 3y agoHow much does this limit the code you can write? Presumably WASM is made safe by limiting the ability of the code in some way. Otherwise the checks that occur as part of the C -> WASM -> C pipeline could be built into your standard C compiler. So what do we lose as part of this round trip? Just speed? Nothing else?
- aseipp 3y agoYou could build Software Fault Isolation into an existing compiler toolchain, and people have done it, but WebAssembly comes with an existing constraint which is why it's designed the way it is: a WASM file may be generated by an unknown or untrustworthy participant and needs to be consumed in a trustworthy context, i.e. served from a random HTTP server into a users browser. Therefore the WASM file format has stringent requirements and a strict validation algorithm placed on it before you should execute it. So, you're doing a classic thing in verification, which is just writing a "checker" that implements some (known good) algorithm in the smallest and most correct way possible, and then using that to check whether much bigger "unknown" things are safe. The goal is that the checker is much easier to implement correctly than auditing everything by hand. For example, you might have a media player with extensions (like foobar2000); traditionally extensions would be delivered as .dlls, because developers did not release the source. This would be a use case similar to the browser, where WebAssembly would be a good choice instead of random .dll files. They may not want to release the code, but you don't want to trust a random blob of binary code. If you trust your WASM implementation, you don't need to trust that the binary blob is harmless (it will just be rejected or forbidden from doing bad things.) If you're not dealing with "random binary blob from potentially untrusted source", i.e. you are running the compiler yourself on some code you downloaded, and then running that code, then you don't really need WASM for this, because you could reasonably trust the compiler to uphold the security guarantees using SFI techniques. For example, if you wanted to make sure zlib was safe from buffer overflows in your main process, to reduce blast radius, a pure SFI toolchain would be fine. You can trust it works and then just compile zlib yourself. But there's generally a lot more mindset and movement around WASM than anything else, so people use it for all of these cases, even cases where they control both the compiler generating code, and where the code is being run.
- 3cats-in-a-coat 3y agoThere's no "best" approach here. If you have RAM and enough cores, you can use JIT to achieve better performance over time for hot loops. Much better. But if you need statically compiled code, no runtime is much simpler to handle, with a lot less to go wrong. But also expect performance that's just "ok". Nothing to call home about.
- ledgerdev 3y agoThis is an amazing idea! Am I missing something or does this sound like a viable way to build cross ecosystem packages with strong sandboxing? I am thinking generating and compiling wasm to a native lib, then calling that native library from pip/npm/maven/nuget packages. I wonder if one could auto generate those binding and build a repo that pushes to all ecosystems from a single code base. My use case would be a wasm based validation lib that could be used in the browser, in edge proxies like cloudflare workers, and in a variety of backends(py/node/.net/java). This approach would negate the need to package a wasm engine like wasmtime.