2017-06-04 00:04:56 +02:00
|
|
|
From df29db0bec24211cfc917db52024bf8deecac2c9 Mon Sep 17 00:00:00 2001
|
|
|
|
From: Mike Frysinger <vapier@gentoo.org>
|
|
|
|
Date: Wed, 15 Mar 2017 23:59:31 -0700
|
2017-06-20 13:46:17 +02:00
|
|
|
Subject: posix_spawn: use a larger min stack for -fstack-check [BZ #21253]
|
2017-06-04 00:04:56 +02:00
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
diff --git a/ChangeLog b/ChangeLog
|
2017-06-20 13:46:17 +02:00
|
|
|
index 321bf53191..b37a054bae 100644
|
2017-06-04 00:04:56 +02:00
|
|
|
--- a/ChangeLog
|
|
|
|
+++ b/ChangeLog
|
|
|
|
@@ -1,3 +1,9 @@
|
|
|
|
+2017-04-03 Mike Frysinger <vapier@gentoo.org>
|
|
|
|
+
|
|
|
|
+ [BZ #21253]
|
|
|
|
+ * sysdeps/unix/sysv/linux/spawni.c (__spawnix): Increase argv_size
|
|
|
|
+ slack space by 32KiB.
|
|
|
|
+
|
|
|
|
2017-04-03 Wladimir van der Laan <laanwj@gmail.com>
|
|
|
|
|
|
|
|
[BZ# 21338]
|
|
|
|
diff --git a/sysdeps/unix/sysv/linux/spawni.c b/sysdeps/unix/sysv/linux/spawni.c
|
2017-06-20 13:46:17 +02:00
|
|
|
index c96aac889d..29d8f25ab5 100644
|
2017-06-04 00:04:56 +02:00
|
|
|
--- a/sysdeps/unix/sysv/linux/spawni.c
|
|
|
|
+++ b/sysdeps/unix/sysv/linux/spawni.c
|
|
|
|
@@ -319,6 +319,11 @@ __spawnix (pid_t * pid, const char *file,
|
|
|
|
|
|
|
|
/* Add a slack area for child's stack. */
|
|
|
|
size_t argv_size = (argc * sizeof (void *)) + 512;
|
|
|
|
+ /* We need at least a few pages in case the compiler's stack checking is
|
|
|
|
+ enabled. In some configs, it is known to use at least 24KiB. We use
|
|
|
|
+ 32KiB to be "safe" from anything the compiler might do. Besides, the
|
|
|
|
+ extra pages won't actually be allocated unless they get used. */
|
|
|
|
+ argv_size += (32 * 1024);
|
|
|
|
size_t stack_size = ALIGN_UP (argv_size, GLRO(dl_pagesize));
|
|
|
|
void *stack = __mmap (NULL, stack_size, prot,
|
|
|
|
MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
|
|
|
|
--
|
2017-06-20 13:46:17 +02:00
|
|
|
2.13.1
|
2017-06-04 00:04:56 +02:00
|
|
|
|