-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
glibc 2.27 stack guard pages are moving #47863
Comments
We should not change how one of the core tasks are done (stack allocation) for the purpose of giving users nicer diagnostics when the stack is overflowed (what the If it is possible to adjust the |
I'm having trouble seeing how to cleanly free a manual stack allocation anyway -- when the thread may be detached from where it was spawned, no one but libpthread really knows about it anymore. I was thinking of trying something like I'll take another look at |
BTW, android is ignored in this test due to #20004. #41618 tried to enable it again, and the log has the same Actually musl is ignored too, and probably for the same reason. The glibc-focused assumption that the guard was within the stack is likely wrong for any other libc. (and now glibc is finally fixing this.) |
@cuviper it seems reasonable to me to print out a message for anything within a range of the predicted guard page, if a fault happens and it wasn't actually a stack overflow, yet we printed, it's probably not the end of the world |
Great, I have a patch that does just that. 😀 I'll clean it up and send a PR tomorrow. |
Previously, the `guard::init()` and `guard::current()` functions were returning a `usize` address representing the top of the stack guard, respectively for the main thread and for spawned threads. The `SIGSEGV` handler on `unix` targets checked if a fault was within one page below that address, if so reporting it as a stack overflow. Now `unix` targets report a `Range<usize>` representing the guard memory, so it can cover arbitrary guard sizes. Non-`unix` targets which always return `None` for guards now do so with `Option<!>`, so they don't pay any overhead. For `linux-gnu` in particular, the previous guard upper-bound was `stackaddr + guardsize`, as the protected memory was *inside* the stack. This was a glibc bug, and starting from 2.27 they are moving the guard *past* the end of the stack. However, there's no simple way for us to know where the guard page actually lies, so now we declare it as the whole range of `stackaddr ± guardsize`, and any fault therein will be called a stack overflow. This fixes rust-lang#47863.
…ichton Use a range to identify SIGSEGV in stack guards Previously, the `guard::init()` and `guard::current()` functions were returning a `usize` address representing the top of the stack guard, respectively for the main thread and for spawned threads. The `SIGSEGV` handler on `unix` targets checked if a fault was within one page below that address, if so reporting it as a stack overflow. Now `unix` targets report a `Range<usize>` representing the guard memory, so it can cover arbitrary guard sizes. Non-`unix` targets which always return `None` for guards now do so with `Option<!>`, so they don't pay any overhead. For `linux-gnu` in particular, the previous guard upper-bound was `stackaddr + guardsize`, as the protected memory was *inside* the stack. This was a glibc bug, and starting from 2.27 they are moving the guard *past* the end of the stack. However, there's no simple way for us to know where the guard page actually lies, so now we declare it as the whole range of `stackaddr ± guardsize`, and any fault therein will be called a stack overflow. This fixes rust-lang#47863.
…ichton Use a range to identify SIGSEGV in stack guards Previously, the `guard::init()` and `guard::current()` functions were returning a `usize` address representing the top of the stack guard, respectively for the main thread and for spawned threads. The `SIGSEGV` handler on `unix` targets checked if a fault was within one page below that address, if so reporting it as a stack overflow. Now `unix` targets report a `Range<usize>` representing the guard memory, so it can cover arbitrary guard sizes. Non-`unix` targets which always return `None` for guards now do so with `Option<!>`, so they don't pay any overhead. For `linux-gnu` in particular, the previous guard upper-bound was `stackaddr + guardsize`, as the protected memory was *inside* the stack. This was a glibc bug, and starting from 2.27 they are moving the guard *past* the end of the stack. However, there's no simple way for us to know where the guard page actually lies, so now we declare it as the whole range of `stackaddr ± guardsize`, and any fault therein will be called a stack overflow. This fixes rust-lang#47863.
…ichton Use a range to identify SIGSEGV in stack guards Previously, the `guard::init()` and `guard::current()` functions were returning a `usize` address representing the top of the stack guard, respectively for the main thread and for spawned threads. The `SIGSEGV` handler on `unix` targets checked if a fault was within one page below that address, if so reporting it as a stack overflow. Now `unix` targets report a `Range<usize>` representing the guard memory, so it can cover arbitrary guard sizes. Non-`unix` targets which always return `None` for guards now do so with `Option<!>`, so they don't pay any overhead. For `linux-gnu` in particular, the previous guard upper-bound was `stackaddr + guardsize`, as the protected memory was *inside* the stack. This was a glibc bug, and starting from 2.27 they are moving the guard *past* the end of the stack. However, there's no simple way for us to know where the guard page actually lies, so now we declare it as the whole range of `stackaddr ± guardsize`, and any fault therein will be called a stack overflow. This fixes rust-lang#47863.
…s will be fixed in rustc-1.25.0, rust-lang/rust#47863. git-svn-id: svn://svn.linuxfromscratch.org/BLFS/trunk@19880 af4574ff-66df-0310-9fd7-8a98e5e911e0
From bug 22637, glibc 2.27 will be allocating the stack guard page for new threads just past the end of the stack, rather than within it. This has also reached Fedora 27 from rhbz 1527887.
With these versions of glibc, the location calculated in
guard::current()
will be incorrect. This causes run-pass/out-of-stack to fail, as our SIGSEGV handler thinks the fault is something other than a guard page. (rather than identifying it as a stack overflow and usingrtabort!
)We could get out of this guessing game by allocating the thread stack and guard page ourselves. If there's no objection, I will attempt this approach. Other ideas are welcome!
(note: this doesn't affect the main thread, as that stack and guard page are managed by the kernel.)
The text was updated successfully, but these errors were encountered: