-
Notifications
You must be signed in to change notification settings - Fork 13.5k
Map the stack guard page with max protection on NetBSD #50331
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
Conversation
On NetBSD the initial mmap() protection of a mapping can not be made less restrictive with mprotect(). So when mapping a stack guard page, use the maximum protection we ever want to use, then mprotect() it to the permission we want it to have initially.
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @Kimundi (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this affect only NetBSD?
src/libstd/sys/unix/thread.rs
Outdated
@@ -326,11 +326,23 @@ pub mod guard { | |||
// Reallocate the last page of the stack. | |||
// This ensures SIGBUS will be raised on | |||
// stack overflow. | |||
let result = mmap(stackaddr, PAGE_SIZE, PROT_NONE, | |||
MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0); | |||
if cfg!(target_os = "netbsd") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a comment with an abridged version of the PR description, mentioning the Issue #? That way people can track the reason for this without having to use git blame
to fish out why netbsd is being singled out here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It affects anyone who is enforcing PaX MPROTECT in strict mode. Strict mode means not only you are enforcing W^X (i.e. you can't map a segment both writable and executable at the same time), but also that you can't use mprotect(2) to augment (add) permissions on an already mapped page (that did not have those permissions during mapping time). I.e. can't toggle between R-X<->RW- using mprotect(2). I am not aware of other OS's doing this at this time, but the change to do the mmap(PROT_READ|PROT_WRITE)+mprotect(PROT_NONE) for the guard page should work on every OS, so it doesn't really need to be conditionalized. I would put a comment why this is the case though (why we are going doing this).
While currently only NetBSD seems to be affected, all systems implementing PAX MPROTECT in strict mode need this treatment, and it does not hurt others.
Ping from triage! This PR needs a review, can @Kimundi or someone else from @rust-lang/libs review this? |
@bors r+ |
📌 Commit 244e24a has been approved by |
Map the stack guard page with max protection on NetBSD On NetBSD the initial mmap() protection of a mapping can not be made less restrictive with mprotect(). So when mapping a stack guard page, use the maximum protection we ever want to use, then mprotect() it to the permission we want it to have initially. Fixes #50313
☀️ Test successful - status-appveyor, status-travis |
On NetBSD the initial mmap() protection of a mapping can not be made
less restrictive with mprotect().
So when mapping a stack guard page, use the maximum protection
we ever want to use, then mprotect() it to the permission we
want it to have initially.
Fixes #50313