4 ms·
I think you could argue there is already some effort to do type safety at the ISA register level, with e.g. shadow stack or control flow integrity. Isn't that v
by btdmaster 9mo ago
I think you could argue there is already some effort to do type safety at the ISA register level, with e.g. shadow stack or control flow integrity. Isn't that very similar to this, except targeting program state rather than external memory?
- Joker_vD 9mo agoI mean, if the stacks grew upwards, that alone would nip 90% of buffer overflow attacks in the bud. Moving the return address from the activation frame into a separate stack would help as well, but I understand that having an activation frame to be a single piece of data (a current continuation's closure, essentially) can be quite convenient.
- musicale 9mo agoThe PL/I stack growing up rather than down reduced potential impact of stack overflows in Multics (and PL/I already had better memory safety, with bounded strings, etc.) TFA's author would probably have appreciated the segmented memory architecture as well. There is no reason why the C/C++ stack can't grow up rather than down. On paged hardware, both the stack and heap could (and probably should) grow up. "C's stack should grow up", one might say.
- Joker_vD 9mo ago> There is no reason why the C/C++ stack can't grow up rather than down. Historical accident. Imagine if PDP-7/PDP-11 easily allowed for the following memory layout: FFFF +---------------+ | text | X +---------------+ | rodata | R +---------------+ | data + bss | RW +---------------+ | heap | | || | RW | \/ | +---------------+ | empty space | unmapped +---------------+ | /\ | | || | RW | stack | 0000 +---------------+ Things could have turned out very differently than they have. Oh well.
- deleted 9mo ago[deleted]
- musicale 9mo agoNice diagram. I might put read-only pages on both sides of 0 though to mitigate null pointer effects.
- josephg 9mo agoIs there anything stopping us from doing this today on modern hardware? Why do we grow the stack down?
- Veserv 9mo agox86-64 call instruction decrements the stack pointer to push the return address. x86-64 push instructions decrement the stack pointer. The push instructions are easy to work around because most compilers already just push the entire stack frame at once and then do offset accesses, but the call instruction would be kind of annoying. ARM does not suffer from that problem due to the usage of link registers and generic pre/post-modify. RISC-V is probably also safe, but I have not looked specifically.
- musicale 9mo ago> [x86] call instruction would be kind of annoying I wonder what the best way to do it (on current x86) would be. The stupid simple way might be to adjust SP before the call instruction, and that seems to me like something that would be relatively efficient (simple addition instruction, issued very early).
- Joker_vD 9mo agoSome architectures had CALL that was just "STR [SP], IP" without anything else, and it was up to the called procedure to adjust the stack pointer further to allocate for its local variables and the return slot for further calls. The RET instruction would still normally take an immediate (just as e.g. x86/x64's RET does) and additionally adjust the stack pointer by its value (either before or after loading the return address from the tip of the stack).
- sph 9mo agoNothing stops you from having upward growing stacks in RISC-V, for example, as there are no dedicated stack instructions. Instead of addi sp, sp, -16 sd a0, 0(sp) sd a1, 8(sp) Do: addi sp, sp, 16 sd a0, -8(sp) sd a1, -16(sp)
- axoltl 9mo agoFor modern systems, stack buffer overflow bugs haven't been great to exploit for a while. You need at least a stack cookie leak and on Apple Silicon the return addresses are MACed so overwriting them is a fools errand (2^-16 chance of success). Most exploitable memory corruption bugs are heap buffer overflows.
- ch_123 9mo agoHP-UX on PA-RISC had an upward-growing stack. In practice, various exploits were developed which adapted to the changed direction of the stack. One source from a few mins of searching: https://phrack.org/issues/58/11 https://phrack.org/issues/58/11
- LukeShu 9mo agoLinux on PA-RISC also has an upward-growing stack (AFAIK, it's the only architecture Linux has ever had an upward-growing stack on; it's certainly the only currently-supported one).
- musicale 9mo agoBoth this and parent comment about PA-RISC are very interesting. As noted, stack growing up doesn't prevent all stack overflows, but it makes it less trivially easy to overwrite a return address. Bounded strings also made it less trivially easy to create string buffer overflows.
- ch_123 9mo agoYeah, my assumption is that all the PA-RISC operating systems did, but I only know about HP-UX for certain.
- saagarjha 9mo agoIt’s still fairly easy to attack buffer overflows if the stack grows upward
- dmitrygr 9mo agoIn ARMv4/v5 (non-thumb-mode) stack is purely a convention that hardware does not enforce. Nobody forces you to use r13 as the stack pointer or to make the stack descending. You can prototype your approach trivially with small changes to gcc and linux kernel. As this is a standard architectural feature, qemu and the like will support emulating this. And it would run fine on real hardware too. I'd read the paper you publish based on this.
- nine_k 9mo agoTagged memory was a thing, and is a thing again on some ARM machines. Check out Google Pixel 9.