musl: pick stacksize-related improvements, increase default size

Also supports setting default thread stack size via linker,
making it possible to fix programs without modifying source.
This commit is contained in:
Will Dietz 2018-09-24 23:40:08 -05:00
parent dcd5e4558f
commit f38218a756
5 changed files with 264 additions and 0 deletions

View File

@ -72,6 +72,11 @@ stdenv.mkDerivation rec {
# name_to_handle_at
./name-to-handle-at.patch
./max-handle-sz-for-name-to-handle-at.patch
# Upstream improvements regarding stack size, incl size increase
./stacksize-0001.patch
./stacksize-0002.patch
./stacksize-0003.patch
./stacksize-0004.patch
];
preConfigure = ''
configureFlagsArray+=("--syslibdir=$out/lib")

View File

@ -0,0 +1,56 @@
From c7ed3e909a69d34a7821f7db644c2fa590a1a690 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Tue, 18 Sep 2018 19:43:52 -0400
Subject: [PATCH 1/4] remove redundant declarations of __default_stacksize,
__default_guardsize
these are now declared in pthread_impl.h.
---
src/thread/pthread_attr_init.c | 3 ---
src/thread/pthread_create.c | 2 --
src/thread/pthread_setattr_default_np.c | 3 ---
3 files changed, 8 deletions(-)
diff --git a/src/thread/pthread_attr_init.c b/src/thread/pthread_attr_init.c
index 398990d1..463a8d20 100644
--- a/src/thread/pthread_attr_init.c
+++ b/src/thread/pthread_attr_init.c
@@ -1,8 +1,5 @@
#include "pthread_impl.h"
-extern size_t __default_stacksize;
-extern size_t __default_guardsize;
-
int pthread_attr_init(pthread_attr_t *a)
{
*a = (pthread_attr_t){0};
diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c
index 3293dcd5..3da7db14 100644
--- a/src/thread/pthread_create.c
+++ b/src/thread/pthread_create.c
@@ -162,8 +162,6 @@ static void *dummy_tsd[1] = { 0 };
weak_alias(dummy_tsd, __pthread_tsd_main);
volatile int __block_new_threads = 0;
-extern size_t __default_stacksize;
-extern size_t __default_guardsize;
static FILE *volatile dummy_file = 0;
weak_alias(dummy_file, __stdin_used);
diff --git a/src/thread/pthread_setattr_default_np.c b/src/thread/pthread_setattr_default_np.c
index 88503e34..256f0685 100644
--- a/src/thread/pthread_setattr_default_np.c
+++ b/src/thread/pthread_setattr_default_np.c
@@ -2,9 +2,6 @@
#include "pthread_impl.h"
#include <string.h>
-extern size_t __default_stacksize;
-extern size_t __default_guardsize;
-
int pthread_setattr_default_np(const pthread_attr_t *attrp)
{
/* Reject anything in the attr object other than stack/guard size. */
--
2.19.0

View File

@ -0,0 +1,86 @@
From 792f32772e64a32527cd455ebfa087ef434a6f4f Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Tue, 18 Sep 2018 23:06:50 -0400
Subject: [PATCH 2/4] limit the configurable default stack/guard size for
threads
limit to 8MB/1MB, repectively. since the defaults cannot be reduced
once increased, excessively large settings would lead to an
unrecoverably broken state. this change is in preparation to allow
defaults to be increased via program headers at the linker level.
creation of threads that really need larger sizes needs to be done
with an explicit attribute.
---
src/internal/pthread_impl.h | 7 +++++--
src/thread/default_attr.c | 4 ++--
src/thread/pthread_setattr_default_np.c | 12 ++++++++----
3 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h
index 26e6e1df..e73a251f 100644
--- a/src/internal/pthread_impl.h
+++ b/src/internal/pthread_impl.h
@@ -182,12 +182,15 @@ hidden void __acquire_ptc(void);
hidden void __release_ptc(void);
hidden void __inhibit_ptc(void);
-extern hidden size_t __default_stacksize;
-extern hidden size_t __default_guardsize;
+extern hidden unsigned __default_stacksize;
+extern hidden unsigned __default_guardsize;
#define DEFAULT_STACK_SIZE 81920
#define DEFAULT_GUARD_SIZE 4096
+#define DEFAULT_STACK_MAX (8<<20)
+#define DEFAULT_GUARD_MAX (1<<20)
+
#define __ATTRP_C11_THREAD ((void*)(uintptr_t)-1)
#endif
diff --git a/src/thread/default_attr.c b/src/thread/default_attr.c
index 46fe98ee..dce96409 100644
--- a/src/thread/default_attr.c
+++ b/src/thread/default_attr.c
@@ -1,4 +1,4 @@
#include "pthread_impl.h"
-size_t __default_stacksize = DEFAULT_STACK_SIZE;
-size_t __default_guardsize = DEFAULT_GUARD_SIZE;
+unsigned __default_stacksize = DEFAULT_STACK_SIZE;
+unsigned __default_guardsize = DEFAULT_GUARD_SIZE;
diff --git a/src/thread/pthread_setattr_default_np.c b/src/thread/pthread_setattr_default_np.c
index 256f0685..58486220 100644
--- a/src/thread/pthread_setattr_default_np.c
+++ b/src/thread/pthread_setattr_default_np.c
@@ -2,6 +2,9 @@
#include "pthread_impl.h"
#include <string.h>
+#define MIN(a,b) ((a)<(b) ? (a) : (b))
+#define MAX(a,b) ((a)>(b) ? (a) : (b))
+
int pthread_setattr_default_np(const pthread_attr_t *attrp)
{
/* Reject anything in the attr object other than stack/guard size. */
@@ -11,11 +14,12 @@ int pthread_setattr_default_np(const pthread_attr_t *attrp)
if (memcmp(&tmp, &zero, sizeof tmp))
return EINVAL;
+ unsigned stack = MIN(attrp->_a_stacksize, DEFAULT_STACK_MAX);
+ unsigned guard = MIN(attrp->_a_guardsize, DEFAULT_GUARD_MAX);
+
__inhibit_ptc();
- if (attrp->_a_stacksize >= __default_stacksize)
- __default_stacksize = attrp->_a_stacksize;
- if (attrp->_a_guardsize >= __default_guardsize)
- __default_guardsize = attrp->_a_guardsize;
+ __default_stacksize = MAX(__default_stacksize, stack);
+ __default_guardsize = MAX(__default_guardsize, guard);
__release_ptc();
return 0;
--
2.19.0

View File

@ -0,0 +1,36 @@
From c0058ab465e950c2c3302d2b62e21cc0b494224b Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Tue, 18 Sep 2018 23:11:49 -0400
Subject: [PATCH 3/4] increase default thread stack/guard size
stack size default is increased from 80k to 128k. this coincides with
Linux's hard-coded default stack for the main thread (128k is
initially committed; growth beyond that up to ulimit is contingent on
additional allocation succeeding) and GNU ld's default PT_GNU_STACK
size for FDPIC, at least on sh.
guard size default is increased from 4k to 8k to reduce the risk of
guard page jumping on overflow, since use of just over 4k of stack is
common (PATH_MAX buffers, etc.).
---
src/internal/pthread_impl.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h
index e73a251f..d491f975 100644
--- a/src/internal/pthread_impl.h
+++ b/src/internal/pthread_impl.h
@@ -185,8 +185,8 @@ hidden void __inhibit_ptc(void);
extern hidden unsigned __default_stacksize;
extern hidden unsigned __default_guardsize;
-#define DEFAULT_STACK_SIZE 81920
-#define DEFAULT_GUARD_SIZE 4096
+#define DEFAULT_STACK_SIZE 131072
+#define DEFAULT_GUARD_SIZE 8192
#define DEFAULT_STACK_MAX (8<<20)
#define DEFAULT_GUARD_MAX (1<<20)
--
2.19.0

View File

@ -0,0 +1,81 @@
From 7b3348a98c139b4b4238384e52d4b0eb237e4833 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Tue, 18 Sep 2018 23:54:18 -0400
Subject: [PATCH 4/4] support setting of default thread stack size via
PT_GNU_STACK header
this facilitates building software that assumes a large default stack
size without any patching to call pthread_setattr_default_np or
pthread_attr_setstacksize at each thread creation site, using just
LDFLAGS.
normally the PT_GNU_STACK header is used only to reflect whether
executable stack is desired, but with GNU ld at least, passing
-Wl,-z,stack-size=N will set a size on the program header. with this
patch, that size will be incorporated into the default stack size
(subject to increase-only rule and DEFAULT_STACK_MAX limit).
both static and dynamic linking honor the program header. for dynamic
linking, all libraries loaded at program start, including preloaded
ones, are considered. dlopened libraries are not considered, for
several reasons. extra logic would be needed to defer processing until
the load of the new library is commited, synchronization woud be
needed since other threads may be running concurrently, and the
effectiveness woud be limited since the larger size would not apply to
threads that already existed at the time of dlopen. programs that will
dlopen code expecting a large stack need to declare the requirement
themselves, or pthread_setattr_default_np can be used.
---
ldso/dynlink.c | 12 ++++++++++++
src/env/__init_tls.c | 5 +++++
2 files changed, 17 insertions(+)
diff --git a/ldso/dynlink.c b/ldso/dynlink.c
index e4829c3a..3ecbddfa 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -609,6 +609,12 @@ static void *map_library(int fd, struct dso *dso)
} else if (ph->p_type == PT_GNU_RELRO) {
dso->relro_start = ph->p_vaddr & -PAGE_SIZE;
dso->relro_end = (ph->p_vaddr + ph->p_memsz) & -PAGE_SIZE;
+ } else if (ph->p_type == PT_GNU_STACK) {
+ if (!runtime && ph->p_memsz > __default_stacksize) {
+ __default_stacksize =
+ ph->p_memsz < DEFAULT_STACK_MAX ?
+ ph->p_memsz : DEFAULT_STACK_MAX;
+ }
}
if (ph->p_type != PT_LOAD) continue;
nsegs++;
@@ -1238,6 +1244,12 @@ static void kernel_mapped_dso(struct dso *p)
} else if (ph->p_type == PT_GNU_RELRO) {
p->relro_start = ph->p_vaddr & -PAGE_SIZE;
p->relro_end = (ph->p_vaddr + ph->p_memsz) & -PAGE_SIZE;
+ } else if (ph->p_type == PT_GNU_STACK) {
+ if (!runtime && ph->p_memsz > __default_stacksize) {
+ __default_stacksize =
+ ph->p_memsz < DEFAULT_STACK_MAX ?
+ ph->p_memsz : DEFAULT_STACK_MAX;
+ }
}
if (ph->p_type != PT_LOAD) continue;
if (ph->p_vaddr < min_addr)
diff --git a/src/env/__init_tls.c b/src/env/__init_tls.c
index e0224243..96d0e284 100644
--- a/src/env/__init_tls.c
+++ b/src/env/__init_tls.c
@@ -90,6 +90,11 @@ static void static_init_tls(size_t *aux)
base = (size_t)_DYNAMIC - phdr->p_vaddr;
if (phdr->p_type == PT_TLS)
tls_phdr = phdr;
+ if (phdr->p_type == PT_GNU_STACK &&
+ phdr->p_memsz > __default_stacksize)
+ __default_stacksize =
+ phdr->p_memsz < DEFAULT_STACK_MAX ?
+ phdr->p_memsz : DEFAULT_STACK_MAX;
}
if (tls_phdr) {
--
2.19.0