3 ms·
Ok. What is your solution then? If it is 'use rust' wasm actively downgrades the memory safety that rust gives you because many of the security issues that was
by eyberg 3y ago
Ok. What is your solution then?
If it is 'use rust' wasm actively downgrades the memory safety that rust gives you because many of the security issues that wasm has is a function of both the compiler and the operating system working together. The compiler merely tells the operating system what should be done - it can't really enforce it.
In this case the various wasm runtimes are acting as that piece and they aren't enforcing the expected behavior.
If the compiler says - hey stick this in .rodata and the wasm interpreter says I don't know what that is then that memory safety feature/contract gets broken.
- josephg 3y ago> If it is 'use rust' wasm actively downgrades the memory safety that rust gives you because many of the security issues that wasm has is a function of both the compiler and the operating system working together. Can you say more about this? I’m using rust through wasm and I hadn’t heard of any security disadvantages of doing so. What kind of security problems are mitigated in a native binary that are problems in wasm?
- eyberg 3y agoAgain, it's not really 'native binary' vs wasm. The binary can only really tell the os what it expects it to do. It is more of 'operating system' vs wasm. By no means an authoritative list and I've not brought up the sandbox at all - that's completely out of scope for this argument but: * wasm has no aslr - making it incredibly easy to figure out where something lives - you can run the same wasm payload again and again again and get the same result, for instance on linux: me@box:~/w/zz/aslr$ ./aslr Library functions: 00007faebfc9f3f0, Heap: 0000562a103c12a0, Stack: 00007ffeea5d8fec, Binary: 0000562a0f1cf179 me@box:~/w/zz/aslr$ ./aslr Library functions: 00007ff2eda9f3f0, Heap: 000056509ae012a0, Stack: 00007fff849209bc, Binary: 000056509a92d179 ~/w/wasi-sdk-20.0+threads/bin/clang --sysroot ~/w/wasi-sdk-20.0+threads/share/wasi-sysroot/ aslr.c -o aslr.wasm and on wasm... Nothing changes: me@box:~/w/zz/aslr$ wasmer aslr.wasm Library functions: 0000000000000002, Heap: 0000000000011500, Stack: 00000000000114b4, Binary: 0000000000000001 me@box:~/w/zz/aslr$ wasmer aslr.wasm Library functions: 0000000000000002, Heap: 0000000000011500, Stack: 00000000000114b4, Binary: 0000000000000001 (btw - all of this works on all wasm runtimes) * wasm can write directly to 0x0 - meaning I can just initialize variables to all sorts of random bad values (eg: overriding functions that might return an expected value or perhaps I have a user_id from a database or worse an 'admin' flag or something, these are just a few examples - it gets way worse in other languages that depend on this) * wasm can easily overflow buffers (despite claims to the contrary) - that claim really should be taken down from the website - it is totally false * doesn't have the concept of read-only memory These are all issues that linux hasn't really had to deal with for 20? years now.
- junon 3y ago> wasm has no aslr Many systems don't employ ASLR. There's a long history of very smart people questioning if ASLR is even a good deterrent. This dissent even extends to KASLR. ASLR is also not unbreakable, don't fool yourself about this. Also, ASLR only works if your code is compiled as position-independent, which isn't always the case. There's also (sometimes) a performance hit with it. Finally, I don't see how the ASLR argument here is anything but moving the goalposts away from your original argument. > wasm can write directly to 0x0 Again, this is not a guarantee, either. Nothing is stopping an OS from mapping in something at virtual page 0 either. It's just a specification from C (perhaps before) that's been adopted by a lot of other languages, so much so that OS developers tend not to map anything there as a rule. On many Microcontrollers for example, 0x0 is usually a perfectly valid memory address, and not allowing something there means you lose at least <required alignment> bytes of usable memory. > wasm can easily overflow buffers Not sure what you mean by this. > that claim really should be taken down from the website Can you quote the claim? Bonus points for linking to it so we have some context. > doesn't have the concept of read-only memory So? Again, as many others have pointed out, neither do OSes unless you can somehow guarantee they're mapping memory in with an MMU or MPU with flags lacking X/W. You're still trusting the OS to do it right, the linker to do it right, and the language to place symbols in the right sections. > These are all issues that linux hasn't really had to deal with for 20? years now. Of course it has, what are you talking about?
- eyberg 3y ago> So? Again, as many others have pointed out, neither do OSes unless you can somehow guarantee they're mapping memory in with an MMU or MPU with flags lacking X/W. You're still trusting the OS to do it right, the linker to do it right, and the language to place symbols in the right sections. If you don't care/understand about the concept of read-only memory I'm not going to be able to convince you of anything. I'll just state that there's a few tens of thousands of people descending on Vegas next week and the longer the wasm community doesn't deal with these issues the louder those people are going to get.
- 3y ago
- junon 3y ago> The compiler merely tells the operating system what should be done - it can't really enforce it. I really don't know how to parse this statement. `.rodata` is not a guarantee, you can almost always change the memory protection of pages your program owns, on almost all OSes (including Windows). Rust also doesn't make guarantees about this stuff, either. `.rodata` is more borne out of the need to put certain data in certain areas of flash memory depending on the platform. It's also a feature of ELF, not Rust. It's also not even required. The flags specify how the memory is used by the application, not how it's meant to be mapped (though usually the ELF loader will map it exactly how it's specified to be used). I'm writing an OS. One of the stage 1 bootloader tasks is to load the main kernel as a module. It's in ELF format. I can choose how the ELF segments are mapped into memory, and as long as they're mapped 1) in the right places and 2) with at least the access flags they're specified to use, the program will work correctly. Further, with Rust in particular, unless a safety contract has been violated within an `unsafe{}` block, I am guaranteed as a contract of the compiler (barring compiler bugs) that anything marked as `const` and thus most likely put into a RO segment will not be written to by the application. That is not a guarantee C can make, and thus not anything an OS can rely on, anyway. Again, I don't really see your point. I think you're conflating why operating systems have memory protection flags. They're there to help, not to guarantee. You can only guarantee so much, and if you're writing code like what you have in your C example, then the guarantees fly out the window. I don't see how it's WASMs job to check memory read/write correctness for you. The _whole point_ is to make it as fast as possible whilst being as much of a sandbox as possible - "sandbox" here meaning your application should operate exactly how the language (not WASM) specifies it to work, whereas the environment is locked down to allow for only certain operations and accesses to resources (which has nothing to do about language specifications). Thus, unless I'm completely missing your point, I disagree with your suggestion that WASM is doing something inherently wrong here. --- To answer your question directly, barring using something like Rust (which I would recommend people do anyway as it's just a good language regardless of its safety guarantees, but that's a personal and subjective opinion), don't incur undefined behavior in C, and don't rely on the underlying system, if any, to protect you against UB.
- skitter 3y agoRust's (and other languages) memory safety doesn't come from hardware features. Implementing memory safety at the language level means that you don't care about whether the data sits in a paged mapped as read-only, because the language already makes sure you're not writing to said data. Besides, that's the safety of the code running inside the VM. Wasm is about the safety of the host.
- duped 3y ago> If the compiler says - hey stick this in .rodata and the wasm interpreter says I don't know what that is then that memory safety feature/contract gets broken. In WASM terms this is called "multiple memories" and it's up to compilers to generate code that works as you'd expect (eg have a "read only data" memory segment and compile the code that references it correctly).