Bug 21253 - localedef randomly segfaults when using -fstack-check due to new posix_spawn implementation
Summary: localedef randomly segfaults when using -fstack-check due to new posix_spawn ...
Status: RESOLVED FIXED
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: 2.24
: P2 normal
Target Milestone: 2.26
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-03-16 06:18 UTC by Mike Frysinger
Modified: 2017-05-05 18:50 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security-


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Mike Frysinger 2017-03-16 06:18:05 UTC
looks like the new posix spawn logic creates too small of a stack in some cases.  building glibc-2.24 w/gcc-4.9 and PIE+SSP+stack-check leads to random segfaults.

example:
$ gdb --args localedef -c -i bg_BG -f UTF-8 bg_BG.UTF-8
Reading symbols from localedef...Reading symbols from /usr/lib/debug//usr/bin/localedef.debug...done.
done.
(gdb) set follow-fork-mode child
(gdb) run
Starting program: /usr/bin/localedef -c -i bg_BG -f UTF-8 bg_BG.UTF-8
[New process 1209]

Thread 2.1 "localedef" received signal SIGSEGV, Segmentation fault.
[Switching to process 1209]
0x00007ffff7b178ec in __spawni_child (arguments=0x7fffffffdb30) at ../sysdeps/unix/sysv/linux/spawni.c:120
120     {
(gdb) bt
#0  0x00007ffff7b178ec in __spawni_child (arguments=0x7fffffffdb30) at ../sysdeps/unix/sysv/linux/spawni.c:120
#1  0x00007ffff7b2676f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:105
(gdb) 

increasing the stack size in __spawnix helps, but going by the gcc internal docs, it sounds like it'd be pretty painful to try and find a good value all the time for all targets.
  https://gcc.gnu.org/onlinedocs/gcc-6.3.0/gccint/Stack-Checking.html

would be easier to just disable stack checking on this one file.
Comment 1 Mike Frysinger 2017-03-16 06:47:53 UTC
playing around, disabling -fstack-check on this one file doesn't help.  we'd have to disable it on every func __spawni_child calls too.  at which point we might as well disable it everywhere.  blah.
Comment 2 cvs-commit@gcc.gnu.org 2017-04-03 19:16:29 UTC
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, master has been updated
       via  21f042c804835d1f7a4a8e06f2c93ca35a182042 (commit)
      from  622222846a2e6ffbcd02cb46cb5f29c48fe4a466 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=21f042c804835d1f7a4a8e06f2c93ca35a182042

commit 21f042c804835d1f7a4a8e06f2c93ca35a182042
Author: Mike Frysinger <vapier@gentoo.org>
Date:   Wed Mar 15 23:59:31 2017 -0700

    posix_spawn: use a larger min stack for -fstack-check [BZ #21253]
    
    When glibc is built with -fstack-check, trying to use posix_spawn can
    lead to segfaults due to gcc internally probing stack memory too far.
    The new spawn API will allocate a minimum of 1 page, but the stack
    checking logic might probe a couple of pages.  When it tries to walk
    them, everything falls apart.
    
    The gcc internal docs [1] state the default interval checking is one
    page.  Which means we need two pages (the current one, and the next
    probed).  No target currently defines it larger.
    
    Further, it mentions that the default minimum stack size needed to
    recover from an overflow is 4/8KiB for sjlj or 8/12KiB for others.
    But some Linux targets (like mips and ppc) go up to 16KiB (and some
    non-Linux targets go up to 24KiB).
    
    Let's create each child with a minimum of 32KiB slack space to support
    them all, and give us future breathing room.
    
    No test is added as existing ones crash.  Even a simple call is
    enough to trigger the problem:
    	char *argv[] = { "/bin/ls", NULL };
    	posix_spawn(NULL, "/bin/ls", NULL, NULL, argv, NULL);
    
    [1] https://gcc.gnu.org/onlinedocs/gcc-6.3.0/gccint/Stack-Checking.html

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog                        |    6 ++++++
 sysdeps/unix/sysv/linux/spawni.c |    5 +++++
 2 files changed, 11 insertions(+), 0 deletions(-)
Comment 3 cvs-commit@gcc.gnu.org 2017-04-03 19:21:09 UTC
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, release/2.25/master has been updated
       via  df29db0bec24211cfc917db52024bf8deecac2c9 (commit)
      from  74522eeeaa4a39809a28f44171e71d36a69edb58 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=df29db0bec24211cfc917db52024bf8deecac2c9

commit df29db0bec24211cfc917db52024bf8deecac2c9
Author: Mike Frysinger <vapier@gentoo.org>
Date:   Wed Mar 15 23:59:31 2017 -0700

    posix_spawn: use a larger min stack for -fstack-check [BZ #21253]
    
    When glibc is built with -fstack-check, trying to use posix_spawn can
    lead to segfaults due to gcc internally probing stack memory too far.
    The new spawn API will allocate a minimum of 1 page, but the stack
    checking logic might probe a couple of pages.  When it tries to walk
    them, everything falls apart.
    
    The gcc internal docs [1] state the default interval checking is one
    page.  Which means we need two pages (the current one, and the next
    probed).  No target currently defines it larger.
    
    Further, it mentions that the default minimum stack size needed to
    recover from an overflow is 4/8KiB for sjlj or 8/12KiB for others.
    But some Linux targets (like mips and ppc) go up to 16KiB (and some
    non-Linux targets go up to 24KiB).
    
    Let's create each child with a minimum of 32KiB slack space to support
    them all, and give us future breathing room.
    
    No test is added as existing ones crash.  Even a simple call is
    enough to trigger the problem:
    	char *argv[] = { "/bin/ls", NULL };
    	posix_spawn(NULL, "/bin/ls", NULL, NULL, argv, NULL);
    
    [1] https://gcc.gnu.org/onlinedocs/gcc-6.3.0/gccint/Stack-Checking.html
    
    (cherry picked from commit 21f042c804835d1f7a4a8e06f2c93ca35a182042)

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog                        |    6 ++++++
 sysdeps/unix/sysv/linux/spawni.c |    5 +++++
 2 files changed, 11 insertions(+), 0 deletions(-)
Comment 4 cvs-commit@gcc.gnu.org 2017-04-03 19:21:28 UTC
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, release/2.24/master has been updated
       via  cc5dcd88039269bfaeefc0f5b2cf675904f7ee33 (commit)
      from  8cc27927431a70c361b8cdddab074878d054a306 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=cc5dcd88039269bfaeefc0f5b2cf675904f7ee33

commit cc5dcd88039269bfaeefc0f5b2cf675904f7ee33
Author: Mike Frysinger <vapier@gentoo.org>
Date:   Wed Mar 15 23:59:31 2017 -0700

    posix_spawn: use a larger min stack for -fstack-check [BZ #21253]
    
    When glibc is built with -fstack-check, trying to use posix_spawn can
    lead to segfaults due to gcc internally probing stack memory too far.
    The new spawn API will allocate a minimum of 1 page, but the stack
    checking logic might probe a couple of pages.  When it tries to walk
    them, everything falls apart.
    
    The gcc internal docs [1] state the default interval checking is one
    page.  Which means we need two pages (the current one, and the next
    probed).  No target currently defines it larger.
    
    Further, it mentions that the default minimum stack size needed to
    recover from an overflow is 4/8KiB for sjlj or 8/12KiB for others.
    But some Linux targets (like mips and ppc) go up to 16KiB (and some
    non-Linux targets go up to 24KiB).
    
    Let's create each child with a minimum of 32KiB slack space to support
    them all, and give us future breathing room.
    
    No test is added as existing ones crash.  Even a simple call is
    enough to trigger the problem:
    	char *argv[] = { "/bin/ls", NULL };
    	posix_spawn(NULL, "/bin/ls", NULL, NULL, argv, NULL);
    
    [1] https://gcc.gnu.org/onlinedocs/gcc-6.3.0/gccint/Stack-Checking.html
    
    (cherry picked from commit 21f042c804835d1f7a4a8e06f2c93ca35a182042)

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog                        |    6 ++++++
 sysdeps/unix/sysv/linux/spawni.c |    5 +++++
 2 files changed, 11 insertions(+), 0 deletions(-)
Comment 5 Carlos O'Donell 2017-05-02 12:07:09 UTC
Mike is this fixed now?
Comment 6 Adhemerval Zanella 2017-05-05 18:50:15 UTC
Fixed by 21f042c804835d1f7a4a8e06f2c93ca35a182042.