Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove morestack support #27338

Merged
merged 1 commit into from Aug 11, 2015
Merged

Conversation

alexcrichton
Copy link
Member

This commit removes all morestack support from the compiler which entails:

  • Segmented stacks are no longer emitted in codegen.
  • We no longer build or distribute libmorestack.a
  • The stack_exhausted lang item is no longer required

The only current use of the segmented stack support in LLVM is to detect stack
overflow. This is no longer really required, however, because we already have
guard pages for all threads and registered signal handlers watching for a
segfault on those pages (to print out a stack overflow message). Additionally,
major platforms (aka Windows) already don't use morestack.

This means that Rust is by default less likely to catch stack overflows because
if a function takes up more than one page of stack space it won't hit the guard
page. This is what the purpose of morestack was (to catch this case), but it's
better served with stack probes which have more cross platform support and no
runtime support necessary. Until LLVM supports this for all platform it looks
like morestack isn't really buying us much.

cc #16012 (still need stack probes)
Closes #26458 (a drive-by fix to help diagnostics on stack overflow)

r? @brson

@alexcrichton
Copy link
Member Author

cc @Zoxc, @geofft

@steveklabnik
Copy link
Member

🎊 amaze!

@brson
Copy link
Contributor

brson commented Jul 27, 2015

Since this will open a fairly big hole in Rust's memory safety until stack probes work (which could be a long time) I'd like this to have some visibility before pulling the trigger. cc @nrc @pnkfelix @eddyb.

@brson
Copy link
Contributor

brson commented Jul 27, 2015

I'm also a bit wary that this makes it much harder for anybody to add true split stacks back to a custom build of Rust (since it removes everything), but maybe it's time to let that dream die.

@alexcrichton
Copy link
Member Author

Since this will open a fairly big hole in Rust's memory safety until stack probes work

I feel like our story has been worn down here quite a bit over time, so I don't personally feel that our usage of morestack is really gaining us much memory safety today. One of our tier 1 platforms, Windows, hasn't been using morestack for months now, but I also wouldn't consider ourselves memory unsafe on Windows.

@eefriedman
Copy link
Contributor

One of our tier 1 platforms, Windows, hasn't been using morestack for months now, but I also wouldn't consider ourselves memory unsafe on Windows.

morestack is irrelevant on Windows because stack probes are already implemented there. That isn't a very strong argument for allowing arbitrary wild memory accesses on Linux.

@eddyb
Copy link
Member

eddyb commented Jul 28, 2015

I'm also a bit wary that this makes it much harder for anybody to add true split stacks back to a custom build of Rust (since it removes everything), but maybe it's time to let that dream die.

Amen to that 👍.

@Aatch
Copy link
Contributor

Aatch commented Jul 28, 2015

Eh, the danger on Linux is fairly small, you need the following conditions for it to actually cause problems:

  • A frame using more than page of stack space
  • The frame starting at a location where it completely covers the guard page
  • The function not actually interacting with the >4Kb data it allocated on the stack before making a function call
  • The space after the end of the stack being mapped

That's quite a significant amount of requirements, to the point that hitting all of them almost certainly requires doing so deliberately. Obviously having stack probes is better than not, but I'm not going to be kept awake by the removal of morestack.

@oli-obk
Copy link
Contributor

oli-obk commented Jul 28, 2015

how about also adding a lint that checks the stack size of functions? It would create some false positives since optimizations might lower the stack usage, but I don't think that's too important.

let guard = thread_info::stack_guard().unwrap_or(0);
let addr = (*info).si_addr as usize;

let _ = ::sys::stdio::Stderr::new().and_then(|mut s| {
use io::Write;
s.write_fmt(format_args!("{:?} {:?} {:?}", guard, addr, PAGE_SIZE))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

left-over debug print?

@nagisa
Copy link
Member

nagisa commented Jul 28, 2015

Given morestack doesn’t work on non-linux/non-apple anyway, and all of the platforms have ASLR I’m not convinced “hole” is that much bigger than it was before. Sure, it exists, but to exploit it you pretty much have to be doing it maliciously, and for malicious purposes there’s many much much easier ways to do that via unsafe.

So overall 👍 from me.

_data: *mut libc::c_void) {

// We can not return from a SIGSEGV or SIGBUS signal.
// See: https://www.gnu.org/software/libc/manual/html_node/Handler-Returns.html
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't remove this comment. Add one stating why we can return on linux, macos, bitrig, netbsd and openbsd. (Should probably be tested on all those platforms as well)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And FreeBSD. I think we're good on all the UNIXes that Rust currently supports; if not, the re-raise code needs to be kept. (I ran out of motivation to go categorize this and send in a PR for #26458 but I could go do that now I guess.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah sorry, I forgot that I meant to reword this, and I've now done so.

@pythonesque
Copy link
Contributor

I'm also a bit wary that this makes it much harder for anybody to add true split stacks back to a custom build of Rust (since it removes everything), but maybe it's time to let that dream die.

I think that's okay, given that other languages (Go) that used segmented stacks have had to move away from them anyway.

@alexcrichton
Copy link
Member Author

@nagisa, @Zoxc ah I forgot to go through and do a final cleanup, but I've added comments and addressed issues now, thanks for taking a look!

@geofft
Copy link
Contributor

geofft commented Jul 28, 2015

Big 👍 to both the idea and the code. The continued existence of __morestack confused me a lot, and it was never clear how to implement the stack_exhausted lang-item.

That said, I do agree with the wariness about removing this from Linux while stack probes aren't present. (I'm still not totally sure what's the blocker, as in why MIPS can't use generic stack probing, but let's have that conversation on #16012.) I am concerned about whether this makes it easy to write "safe" code (that is, code that doesn't use unsafe) that messes with memory: see my writeup of doing this in well-defined C, and in particular CVE-2010-2240, which uses attacker-controlled recursion in the X server, plus MIT-SHM, to gain local root on Linux. (It did rely on coaxing the kernel into not generating a guard page, since each function happened to use less than a page of stack space.) If there's no current protection on Windows, meh, but if stack probes are present on Windows but not Linux, then I think removing explicit stack checks on Linux would be unfortunate. If we can quickly get generic stack probes in on all architectures, that sounds like the right approach.

That said, if there's already a way for malicious code to deliberately violate memory safety without unsafe in pure Rust, which I think @nagisa said there is, I don't think I can complain about there being another way to do it.

I don't think custom split stacks are a compelling reason to keep this code around; I agree this is the right long-term thing to do.

@@ -94,7 +94,6 @@ pub fn opts(arch: Arch) -> TargetOptions {
//
// SS might be also enabled on Arm64 as it has builtin support in LLVM
// but I haven't tested it through yet
morestack: false,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comments above this line are now irrelevant.

@nagisa
Copy link
Member

nagisa commented Jul 28, 2015

That said, if there's already a way for malicious code to deliberately violate memory safety without unsafe in pure Rust, which I think @nagisa said there is, I don't think I can complain about there being another way to do it.

Sorry, I didn’t mean to imply there’s already a way to access arbitrary memory using only safe code. What I’m trying to say that you have to be deliberately trying to write malicious safe code to reasonably expect to exploit lack of __morestack/stack probing and it won’t work most of the time anyway because of memory layout randomisation.

Sure, that is not good enough for safety Rust-without-unsafe tries to guarantee, but since we expect to implement stack probes for all platforms sometime in the future anyway…

@alexcrichton alexcrichton force-pushed the remove-morestack branch 5 times, most recently from cae8577 to ce2b8d1 Compare July 28, 2015 20:07
@alexcrichton
Copy link
Member Author

And to clarify, we don't currently use stack probes anywhere today. From what I understand it sounds like LLVM has support for stack probes on Windows but not on other platforms just yet. That being said I believe there's more detailed discussion over at #16012

@bors
Copy link
Contributor

bors commented Aug 5, 2015

⌛ Testing commit 143ca53 with merge b18b3bf...

@alexcrichton
Copy link
Member Author

@bors: r- force

Travis failed in what looks like a pretty legit fashion.

@bors
Copy link
Contributor

bors commented Aug 5, 2015

⛄ The build was interrupted to prioritize another pull request.

term(signum);
// If the faulting address is within the guard page, then we print a
// message saying so.
if guard != 0 && guard - PAGE_SIZE <= addr && addr <= guard {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be addr < guard.

@alexcrichton
Copy link
Member Author

@bors: r+ acbdf0a1bded880011cfff5f487066a8d16f2e0b

@bors
Copy link
Contributor

bors commented Aug 10, 2015

⌛ Testing commit acbdf0a with merge aa3d701...

@bors
Copy link
Contributor

bors commented Aug 10, 2015

💔 Test failed - auto-win-gnu-32-opt

This commit removes all morestack support from the compiler which entails:

* Segmented stacks are no longer emitted in codegen.
* We no longer build or distribute libmorestack.a
* The `stack_exhausted` lang item is no longer required

The only current use of the segmented stack support in LLVM is to detect stack
overflow. This is no longer really required, however, because we already have
guard pages for all threads and registered signal handlers watching for a
segfault on those pages (to print out a stack overflow message). Additionally,
major platforms (aka Windows) already don't use morestack.

This means that Rust is by default less likely to catch stack overflows because
if a function takes up more than one page of stack space it won't hit the guard
page. This is what the purpose of morestack was (to catch this case), but it's
better served with stack probes which have more cross platform support and no
runtime support necessary. Until LLVM supports this for all platform it looks
like morestack isn't really buying us much.

cc rust-lang#16012 (still need stack probes)
Closes rust-lang#26458 (a drive-by fix to help diagnostics on stack overflow)
@alexcrichton
Copy link
Member Author

@bors: r=brson 7a3fdfb

bors added a commit that referenced this pull request Aug 10, 2015
This commit removes all morestack support from the compiler which entails:

* Segmented stacks are no longer emitted in codegen.
* We no longer build or distribute libmorestack.a
* The `stack_exhausted` lang item is no longer required

The only current use of the segmented stack support in LLVM is to detect stack
overflow. This is no longer really required, however, because we already have
guard pages for all threads and registered signal handlers watching for a
segfault on those pages (to print out a stack overflow message). Additionally,
major platforms (aka Windows) already don't use morestack.

This means that Rust is by default less likely to catch stack overflows because
if a function takes up more than one page of stack space it won't hit the guard
page. This is what the purpose of morestack was (to catch this case), but it's
better served with stack probes which have more cross platform support and no
runtime support necessary. Until LLVM supports this for all platform it looks
like morestack isn't really buying us much.

cc #16012 (still need stack probes)
Closes #26458 (a drive-by fix to help diagnostics on stack overflow)

r? @brson
@bors
Copy link
Contributor

bors commented Aug 10, 2015

⌛ Testing commit 7a3fdfb with merge 5aca49c...

@bors bors merged commit 7a3fdfb into rust-lang:master Aug 11, 2015
@alexcrichton alexcrichton deleted the remove-morestack branch August 11, 2015 06:11
geofft added a commit to geofft/std-with-cargo that referenced this pull request Aug 31, 2015
On the functionality side, morestack is gone (rust-lang/rust#27338), and
rustrt_native is gone (rust-lang/rust#27176).

On the implementation side, connect has been renamed to join
(rust-lang/rust#26957).
@ranma42 ranma42 mentioned this pull request Oct 28, 2015
hannobraun added a commit to hannobraun/embedded that referenced this pull request Mar 24, 2016
The Rust version is now at:
```
rustc 1.9.0-nightly (0dcc413e4 2016-03-22)
```

This includes a fix for the following build error that the new version
produced:
```
src/rust_base.rs:17:1: 19:2 error: definition of an unknown language
item: `stack_exhausted`. [E0522]
src/rust_base.rs:17 pub extern fn stack_exhausted() {
src/rust_base.rs:18     panic!("Stack exhausted");
src/rust_base.rs:19 }
src/rust_base.rs:17:1: 19:2 help: run `rustc --explain E0522` to see a
detailed explanation
```

It looks like the `stack_exhausted item was removed last year:
rust-lang/rust#27338

This didn't cause an error so far, because the compiler didn't complain
about defining lang items that don't exist. This seems to have changed
in this pull request:
rust-lang/rust#32264
hawkw added a commit to sos-os/kernel that referenced this pull request Apr 2, 2016
The `stack_exhausted` lang item was removed in rust-lang/rust#27338.
Therefore, our (empty) implementation of `stack_exhausted` can be
removed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
relnotes Marks issues that should be documented in the release notes of the next release.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

SIGSEGV and SIGBUS cause an exit signal of SIGILL