Skip to content

glibc 2.27 stack guard pages are moving #47863

Closed
@cuviper

Description

@cuviper
Member

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 using rtabort!)

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.)

Activity

added
A-runtimeArea: std's runtime and "pre-main" init for handling backtraces, unwinds, stack overflows
O-linuxOperating system: Linux
T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.
C-bugCategory: This is a bug.
on Jan 30, 2018
nagisa

nagisa commented on Jan 30, 2018

@nagisa
Member

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 guard::current is used for IIRC).

If it is possible to adjust the guard::current logic to return a correct value – great. Alternatively, we should just live with the notion that this check may be false-negative.

cuviper

cuviper commented on Jan 30, 2018

@cuviper
MemberAuthor

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 pthread_attr_setguardsize(attr, 0), leaving libpthread to allocate the stack, and then alter the last page with mprotect(PROT_NONE) ourselves. But that too may be fragile, if libpthread tries to do anything more than munmap with that area on cleanup, when it doesn't know it's protected there.

I'll take another look at guard::current. One thought is to have this return an address range, rather than just an edge, and then for Linux targets we can cover both within and just past the end of stack. Worst case is that this would misdiagnose an unrelated segv that just happened to be right below the thread stack.

cuviper

cuviper commented on Jan 30, 2018

@cuviper
MemberAuthor

BTW, android is ignored in this test due to #20004. #41618 tried to enable it again, and the log has the same assertion failed: `(left == right)` (left: `Some(11)`, right: `Some(6)`), which is SIGSEGV vs. SIGABRT. Android probably puts the guard below the stack, as that's really the proper way to do it.

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.)

alexcrichton

alexcrichton commented on Jan 31, 2018

@alexcrichton
Member

@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

cuviper

cuviper commented on Jan 31, 2018

@cuviper
MemberAuthor

Great, I have a patch that does just that. 😀

I'll clean it up and send a PR tomorrow.

added a commit that references this issue on Jan 31, 2018
55b54a9
added 3 commits that reference this issue on Feb 3, 2018

Rollup merge of rust-lang#47912 - cuviper:glibc-stack-guard, r=alexcr…

eb3b870

Rollup merge of rust-lang#47912 - cuviper:glibc-stack-guard, r=alexcr…

e19c1f1

Rollup merge of rust-lang#47912 - cuviper:glibc-stack-guard, r=alexcr…

8b8c6ee

2 remaining items

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-runtimeArea: std's runtime and "pre-main" init for handling backtraces, unwinds, stack overflowsC-bugCategory: This is a bug.O-linuxOperating system: LinuxT-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      Participants

      @cuviper@alexcrichton@nagisa

      Issue actions

        glibc 2.27 stack guard pages are moving · Issue #47863 · rust-lang/rust