Rust guarantees no segfaults with only safe code but it segfaults (stack overflow)


#21

We never have, and that’s not what I’m suggesting. In the segmented stack era when we hit the end of the stack we called abort!. A runtime abort does not trigger a segfault, but an illegal instruction. Apparently, the current stack overflow behavior causes the process to exit with a segfault, not an abort. This is incorrect because it is leaking an implementation detail of our stack overflow detection. We should rather trap the segfault and abort like any other fatal error.

Edit: issue


#22

In case anyone finds this issue today, this PR is relevant:


#23

I’m not sure I understand what all this means. Is a remote code execution exploit possible with this kind of stack overflow?


#24

No, if the overflow happens, the application will just be aborted because of Rust’s stack probing.
This was and is Not a bug. Rust was just exposing internal details(again, by “exposing” I don’t mean in a security way, just that it was passing the stack overflow further to the system when it didn’t have to) before but it still had the protection.


#25

IIRC, rust doesn’t yet do stack probing (it’s wanted but not implemented).


#26

It is implemented on Windows, but due to lack of LLVM support on other platforms, isn’t on some other very major ones. It’s blocked on upstream, basically.


#27

Except if you overflow the guard page you might ACTUALLY access an illegal memory location AFAIK.


#28

That can only happen when you have guard pages without stack probes. With stack probes, whenever you perform a read more than a page down the stack from the last read, you read a byte out of every page in-between to guarantee you never skip over the guard page.


#29

I think Linux doesn’t have stack probes, only Windows does. I’m a little bit uneasy with a potential memory unsafety concern on stack overflow.


#30

In theory, yes. There are no partially initialized on-stack arrays in the safe Rust subset (as far as I know), but there are some LLVM stack slot reuse optimizations which appear to have a similar effect. As a result, it is theoretically possible that the stack pointer is decremented past the guard page, and execution continues with a stack that overlaps with other (writable) memory.


#31

There can be safe interfaces on top of uninitialized stack data though, like ArrayVec. But since that’s still statically sized, maybe it’s not much of an exploitation concern. My intuition is that a huge ArrayVec will always fail, whereas you need VLAs to get something that usually works but may overflow when under attack.


#32

For those interested, there is an update on that: https://github.com/rust-lang/rust/pull/42816

In short:
Stack probing support for x86/x86_64 landed in LLVM and @alexcrichton implemented stack probes for Rust(merged in nightly).


#33

I later observed that the Stack Probing support got finished-up and landed in LLVM thanks to @pcwalton :slight_smile:
https://reviews.llvm.org/D34386
https://reviews.llvm.org/D34387