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

Extend stack probe support to non-tier-1 platforms, and clarify policy for mitigating LLVM-dependent unsafety #43241

Open
bstrie opened this issue Jul 14, 2017 · 10 comments

Comments

@bstrie
Copy link
Contributor

@bstrie bstrie commented Jul 14, 2017

As of #42816 , all tier-1 platforms are protected against the potential memory unsafety demonstrated in #16012 . However, this protection is dependent upon platform-dependent LLVM support, so AFAIK most of our supported tier-2 and tier-3 platforms ( https://forge.rust-lang.org/platform-support.html ) are still theoretically unprotected.

Proper resolution of this issue will depend on extending LLVM's stack probe support for various platforms, (which should be done regardless of the discussion in the next paragraph). See https://reviews.llvm.org/D34387 for pcwalton's original x86 implementation, https://reviews.llvm.org/D34386 for the implementation of the attribute itself, and #42816 for the work needed on rustc's side.

But here's the more important concern: the list of potential platforms is unbounded, and we need to decide where to draw the line. As minor as the safety hole may be, is it an abrogation of Rust's claim to guarantee memory safety if that safety is only enforced on "popular" platforms? If so, is it worth considering some sort of blanket check that can be implemented in the frontend for use only on platforms where stack probes are unimplemented? For instance, given that we statically know the stack size of all types, could we perhaps enforce an upper bound on the size of a type (perhaps only in debug mode)? I think this discussion may be relevant to #10184 as well.

@whitequark

This comment has been minimized.

Copy link
Member

@whitequark whitequark commented Jul 14, 2017

so AFAIK most of our supported tier-2 and tier-3 platforms

All of them. LLVM only currently has support for x86.

@cuviper

This comment has been minimized.

Copy link
Member

@cuviper cuviper commented Jul 14, 2017

For instance, given that we statically know the stack size of all types, could we perhaps enforce an upper bound on the size of a type (perhaps only in debug mode)?

GCC has -Wframe-larger-than=len, so I could see rustc having something similar. That can't count alloca/VLAs/etc. though. It's also hard to say what a reasonable limit is generally, so I think it would have to be user configurable. e.g. a 1MB stack item might be fine in isolation, but will blow up in mild recursion, or if a few such functions are nested. A kernel probably wants more like ~1KB max.

@bstrie

This comment has been minimized.

Copy link
Contributor Author

@bstrie bstrie commented Jul 14, 2017

@cuviper Would it suffice to give the user the ability to enforce that no given function ever exceeds the size of the guard page? Maybe I'm naive, but I'm assuming that our guard page support is platform-independent, and that we can calculate the maximum size of any given monomorphized function (I can't think of a reason why we couldn't given that we don't support alloca).

@cuviper

This comment has been minimized.

Copy link
Member

@cuviper cuviper commented Jul 14, 2017

Page size is not a static value on some arches, although for this purpose you could probably get away with just assuming a minimum 4KB. Stack probing on those arches will probably have to use 4KB strides as a worst case, even when the real page size is 64KB/etc., unless we want those to query sysconf at runtime.

Also, as we learned in #43052, the Linux kernel now implements a much larger effective guard size, but we have no way to detect that at runtime, unless you tried to probe a fault on purpose.

Anyway, 4KB seems to me like a pretty low stack-frame threshold for userspace programs. I guess some users might be happy with that, but I think a tunable threshold would be more useful.

@cuviper

This comment has been minimized.

Copy link
Member

@cuviper cuviper commented Jul 14, 2017

There's also different behavior between the main thread's growable stack and the fixed stack space of other threads. See pthread_attr_setguardsize -- defaults to one page, which Rust doesn't change.

@bstrie

This comment has been minimized.

Copy link
Contributor Author

@bstrie bstrie commented Jul 14, 2017

I suppose another difficulty is that LLVM can inline functions as it pleases, which would poke a hole in any attempt to statically lint against large functions in the frontend.

@whitequark

This comment has been minimized.

Copy link
Member

@whitequark whitequark commented Jul 15, 2017

Would it suffice to give the user the ability to enforce that no given function ever exceeds the size of the guard page?

This is not realistic given the way LLVM is designed. You'd have to plug your pass very late into the MI pipeline, which by itself will need target-specific LLVM patches (that are quite a bit more complex than stack probes themselves).

@nikomatsakis

This comment has been minimized.

Copy link
Contributor

@nikomatsakis nikomatsakis commented Aug 24, 2017

triage: P-medium

@GreenReaper

This comment has been minimized.

Copy link

@GreenReaper GreenReaper commented Apr 15, 2019

so AFAIK most of our supported tier-2 and tier-3 platforms

All of them. LLVM only currently has support for x86.

Well, gnux32 (Tier 2) is x86_64, with 32-bit pointers, and theory has support.
But in practice, LLVM is shaky here, too; see #59674.

@whitequark

This comment has been minimized.

Copy link
Member

@whitequark whitequark commented Jan 16, 2020

This is not realistic given the way LLVM is designed.

Revisiting: this statement is wrong. There is a way to ask LLVM to emit this information because it gained exactly such a pass plugged very late into MC pipeline. See this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
7 participants
You can’t perform that action at this time.