Fix build with glibc 2.34

https://github.com/ColinIanKing/stress-ng/issues/107
This commit is contained in:
Yaakov Selkowitz 2021-02-24 22:05:37 -05:00
parent 058c7ca201
commit a9bc8b5947
2 changed files with 664 additions and 0 deletions

View File

@ -0,0 +1,661 @@
From 7c4f74761089177127c2cfe6685b7886aa231885 Mon Sep 17 00:00:00 2001
From: Colin Ian King <colin.king@canonical.com>
Date: Thu, 25 Feb 2021 00:33:17 +0000
Subject: [PATCH] stack handling: use _SC_SIGSTKSZ and _SC_MINSIGSTKSZ
New versions of glibc will define SIGSTKSZ and MINSTKSZ
on the sysconf values for _SC_SIGSTKSZ and _SC_MINSIGSTKSZ
respectively. Define two helper functions to determine the
stack sizes by trying to use cached sysconf values, fetching
and caching the sysconf values or falling back to the
traditional SIGSTKSZ or MINSTKSZ defined values, or hard
coded 8K limits if all else fails.
Define STRESS_SIGSTKSZ and STRESS_MINSTKSZ that call the
helper functions and hide the details. Since these sizes
are dynamic, replace all statically allocated and stack
allocated alternative stacks with mmap'd versions and add
in allocation failure error handling.
Finally remove the MLOCKED_DATA macros now that the mlocked
alt stacks are no longer used.
Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
core-helper.c | 85 +++++++++++++++++++++++++++++++++----------
stress-bad-altstack.c | 39 ++++++++++----------
stress-context.c | 19 +++++++---
stress-ng.c | 3 --
stress-ng.h | 10 ++++-
stress-rlimit.c | 15 +++++++-
stress-stack.c | 18 ++++-----
stress-stackmmap.c | 70 ++++++++++++++++++++---------------
stress-vforkmany.c | 14 +++++--
9 files changed, 180 insertions(+), 93 deletions(-)
diff --git a/core-helper.c b/core-helper.c
index 2c009e53..bc9e4bea 100644
--- a/core-helper.c
+++ b/core-helper.c
@@ -1338,12 +1338,12 @@ int stress_sigaltstack(const void *stack, const size_t size)
#if defined(HAVE_SIGALTSTACK)
stack_t ss;
- if (size < (size_t)MINSIGSTKSZ) {
+ if (size < (size_t)STRESS_MINSIGSTKSZ) {
pr_err("sigaltstack stack size %zu must be more than %zuK\n",
- size, (size_t)MINSIGSTKSZ / 1024);
+ size, (size_t)STRESS_MINSIGSTKSZ / 1024);
return -1;
}
- ss.ss_sp = stress_align_address(stack, STACK_ALIGNMENT);
+ ss.ss_sp = (void *)stack;
ss.ss_size = size;
ss.ss_flags = 0;
if (sigaltstack(&ss, NULL) < 0) {
@@ -1370,22 +1370,23 @@ int stress_sighandler(
{
struct sigaction new_action;
#if defined(HAVE_SIGALTSTACK)
- static bool set_altstack = false;
-
- /*
- * Signal handlers should really be using an alternative
- * signal stack to be totally safe. For any new instance we
- * should set this alternative signal stack before setting
- * up any signal handler. We only need to do this once
- * per process instance, so just do it on the first
- * call to stress_sighandler.
- */
- if (!set_altstack) {
- static uint8_t MLOCKED_DATA stack[SIGSTKSZ + STACK_ALIGNMENT];
-
- if (stress_sigaltstack(stack, SIGSTKSZ) < 0)
- return -1;
- set_altstack = true;
+ {
+ static uint8_t *stack = NULL;
+
+ if (stack == NULL) {
+ /* Allocate stack, we currently leak this */
+ stack = mmap(NULL, STRESS_SIGSTKSZ, PROT_READ | PROT_WRITE,
+ MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+ if (stack == MAP_FAILED) {
+ pr_inf("%s: sigaction %s: cannot allocated signal stack, "
+ "errno = %d (%s)\n",
+ name, stress_strsignal(signum),
+ errno, strerror(errno));
+ return -1;
+ }
+ if (stress_sigaltstack(stack, STRESS_SIGSTKSZ) < 0)
+ return -1;
+ }
}
#endif
(void)memset(&new_action, 0, sizeof new_action);
@@ -2274,3 +2275,49 @@ size_t stress_hostname_length(void)
return 255 + 1; /* SUSv2 */
#endif
}
+
+/*
+ * stress_sig_stack_size()
+ * wrapper for STRESS_SIGSTKSZ
+ */
+size_t stress_sig_stack_size(void)
+{
+#if defined(_SC_SIGSTKSZ)
+ {
+ static long sz = -1;
+
+ if (sz < 0)
+ sz = sysconf(_SC_SIGSTKSZ);
+ if (sz > 0)
+ return (size_t)sz;
+ }
+#endif
+#if defined(SIGSTKSZ)
+ return SIGSTKSZ;
+#else
+ return (8192);
+#endif
+}
+
+/*
+ * stress_min_sig_stack_size()
+ * wrapper for STRESS_MINSIGSTKSZ
+ */
+size_t stress_min_sig_stack_size(void)
+{
+#if defined(_SC_MINSIGSTKSZ)
+ {
+ static long sz = -1;
+
+ if (sz < 0)
+ sz = sysconf(_SC_MINSIGSTKSZ);
+ if (sz > 0)
+ return (size_t)sz;
+ }
+#endif
+#if defined(MINSIGSTKSZ)
+ return MINSIGSTKSZ;
+#else
+ return (8192);
+#endif
+}
diff --git a/stress-bad-altstack.c b/stress-bad-altstack.c
index e6509be8..e698c3bd 100644
--- a/stress-bad-altstack.c
+++ b/stress-bad-altstack.c
@@ -41,7 +41,6 @@ static const stress_help_t help[] =
static void *stack;
static void *zero_stack;
-static const size_t stack_sz = MINSIGSTKSZ;
static sigjmp_buf jmpbuf;
static inline void stress_bad_altstack_force_fault(uint8_t *stack_start)
@@ -56,15 +55,15 @@ static inline void stress_bad_altstack_force_fault(uint8_t *stack_start)
static void MLOCKED_TEXT stress_segv_handler(int signum)
{
- uint8_t data[MINSIGSTKSZ * 2];
+ uint8_t data[STRESS_MINSIGSTKSZ * 2];
(void)signum;
- (void)munmap(stack, stack_sz);
+ (void)munmap(stack, STRESS_MINSIGSTKSZ);
(void)memset(data, 0xff, sizeof(data));
stress_uint8_put(data[0]);
if (zero_stack != MAP_FAILED)
- (void)munmap(zero_stack, stack_sz);
+ (void)munmap(zero_stack, STRESS_MINSIGSTKSZ);
/*
* If we've not got this far we've not
@@ -88,7 +87,7 @@ static int stress_bad_altstack(const stress_args_t *args)
#endif
int fd;
- stack = mmap(NULL, stack_sz, PROT_READ | PROT_WRITE,
+ stack = mmap(NULL, STRESS_MINSIGSTKSZ, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (stack == MAP_FAILED) {
pr_err("%s: cannot mmap signal handler stack, errno=%d (%s)\n",
@@ -98,7 +97,7 @@ static int stress_bad_altstack(const stress_args_t *args)
fd = open("/dev/zero", O_RDONLY);
if (fd >= 0) {
- zero_stack = mmap(NULL, stack_sz, PROT_READ,
+ zero_stack = mmap(NULL, STRESS_MINSIGSTKSZ, PROT_READ,
MAP_PRIVATE, fd, 0);
(void)close(fd);
} else {
@@ -176,13 +175,13 @@ static int stress_bad_altstack(const stress_args_t *args)
/* Exercise disable SS_DISABLE */
ss.ss_sp = stress_align_address(stack, STACK_ALIGNMENT);
- ss.ss_size = MINSIGSTKSZ;
+ ss.ss_size = STRESS_MINSIGSTKSZ;
ss.ss_flags = SS_DISABLE;
(void)sigaltstack(&ss, NULL);
/* Exercise invalid flags */
ss.ss_sp = stress_align_address(stack, STACK_ALIGNMENT);
- ss.ss_size = MINSIGSTKSZ;
+ ss.ss_size = STRESS_MINSIGSTKSZ;
ss.ss_flags = ~0;
(void)sigaltstack(&ss, NULL);
@@ -191,7 +190,7 @@ static int stress_bad_altstack(const stress_args_t *args)
/* Exercise less than minimum allowed stack size, ENOMEM */
ss.ss_sp = stress_align_address(stack, STACK_ALIGNMENT);
- ss.ss_size = MINSIGSTKSZ - 1;
+ ss.ss_size = STRESS_MINSIGSTKSZ - 1;
ss.ss_flags = 0;
(void)sigaltstack(&ss, NULL);
@@ -199,7 +198,7 @@ static int stress_bad_altstack(const stress_args_t *args)
return EXIT_FAILURE;
/* Set alternative stack for testing */
- if (stress_sigaltstack(stack, stack_sz) < 0)
+ if (stress_sigaltstack(stack, STRESS_MINSIGSTKSZ) < 0)
return EXIT_FAILURE;
/* Child */
@@ -214,7 +213,7 @@ static int stress_bad_altstack(const stress_args_t *args)
#if defined(HAVE_MPROTECT)
case 1:
/* Illegal stack with no protection */
- ret = mprotect(stack, stack_sz, PROT_NONE);
+ ret = mprotect(stack, STRESS_MINSIGSTKSZ, PROT_NONE);
if (ret == 0)
stress_bad_altstack_force_fault(stack);
if (!keep_stressing(args))
@@ -222,7 +221,7 @@ static int stress_bad_altstack(const stress_args_t *args)
CASE_FALLTHROUGH;
case 2:
/* Illegal read-only stack */
- ret = mprotect(stack, stack_sz, PROT_READ);
+ ret = mprotect(stack, STRESS_MINSIGSTKSZ, PROT_READ);
if (ret == 0)
stress_bad_altstack_force_fault(stack);
if (!keep_stressing(args))
@@ -230,7 +229,7 @@ static int stress_bad_altstack(const stress_args_t *args)
CASE_FALLTHROUGH;
case 3:
/* Illegal exec-only stack */
- ret = mprotect(stack, stack_sz, PROT_EXEC);
+ ret = mprotect(stack, STRESS_MINSIGSTKSZ, PROT_EXEC);
if (ret == 0)
stress_bad_altstack_force_fault(stack);
if (!keep_stressing(args))
@@ -239,7 +238,7 @@ static int stress_bad_altstack(const stress_args_t *args)
#endif
case 4:
/* Illegal NULL stack */
- ret = stress_sigaltstack(NULL, SIGSTKSZ);
+ ret = stress_sigaltstack(NULL, STRESS_SIGSTKSZ);
if (ret == 0)
stress_bad_altstack_force_fault(stack);
if (!keep_stressing(args))
@@ -247,7 +246,7 @@ static int stress_bad_altstack(const stress_args_t *args)
CASE_FALLTHROUGH;
case 5:
/* Illegal text segment stack */
- ret = stress_sigaltstack(stress_segv_handler, SIGSTKSZ);
+ ret = stress_sigaltstack(stress_segv_handler, STRESS_SIGSTKSZ);
if (ret == 0)
stress_bad_altstack_force_fault(stack);
if (!keep_stressing(args))
@@ -260,7 +259,7 @@ static int stress_bad_altstack(const stress_args_t *args)
case 7:
#if defined(HAVE_VDSO_VIA_GETAUXVAL)
/* Illegal stack on VDSO, otherwises NULL stack */
- ret = stress_sigaltstack(vdso, SIGSTKSZ);
+ ret = stress_sigaltstack(vdso, STRESS_SIGSTKSZ);
if (ret == 0)
stress_bad_altstack_force_fault(stack);
if (!keep_stressing(args))
@@ -270,7 +269,7 @@ static int stress_bad_altstack(const stress_args_t *args)
case 8:
/* Illegal /dev/zero mapped stack */
if (zero_stack != MAP_FAILED) {
- ret = stress_sigaltstack(zero_stack, stack_sz);
+ ret = stress_sigaltstack(zero_stack, STRESS_MINSIGSTKSZ);
if (ret == 0)
stress_bad_altstack_force_fault(zero_stack);
if (!keep_stressing(args))
@@ -280,7 +279,7 @@ static int stress_bad_altstack(const stress_args_t *args)
default:
case 0:
/* Illegal unmapped stack */
- (void)munmap(stack, stack_sz);
+ (void)munmap(stack, STRESS_MINSIGSTKSZ);
stress_bad_altstack_force_fault(NULL);
break;
}
@@ -293,9 +292,9 @@ static int stress_bad_altstack(const stress_args_t *args)
stress_set_proc_state(args->name, STRESS_STATE_DEINIT);
if (zero_stack != MAP_FAILED)
- (void)munmap(zero_stack, stack_sz);
+ (void)munmap(zero_stack, STRESS_MINSIGSTKSZ);
if (stack != MAP_FAILED)
- (void)munmap(stack, stack_sz);
+ (void)munmap(stack, STRESS_MINSIGSTKSZ);
return EXIT_SUCCESS;
}
diff --git a/stress-context.c b/stress-context.c
index fda48ba1..db4f69f3 100644
--- a/stress-context.c
+++ b/stress-context.c
@@ -33,7 +33,7 @@ static stress_help_t help[] = {
#if defined(HAVE_SWAPCONTEXT) && \
defined(HAVE_UCONTEXT_H)
-#define STACK_SIZE (16384)
+#define CONTEXT_STACK_SIZE (16384)
typedef struct {
uint32_t check0; /* memory clobbering check canary */
@@ -48,7 +48,7 @@ typedef struct {
typedef struct {
chk_ucontext_t cu; /* check ucontext */
- uint8_t stack[SIGSTKSZ + STACK_ALIGNMENT]; /* stack */
+ uint8_t stack[CONTEXT_STACK_SIZE + STACK_ALIGNMENT]; /* stack */
chk_canary_t canary; /* copy of canary */
} context_info_t;
@@ -103,7 +103,7 @@ static int stress_context_init(
context_info->cu.check1 = context_info->canary.check1;
context_info->cu.uctx.uc_stack.ss_sp =
(void *)stress_align_address(context_info->stack, STACK_ALIGNMENT);
- context_info->cu.uctx.uc_stack.ss_size = STACK_SIZE;
+ context_info->cu.uctx.uc_stack.ss_size = CONTEXT_STACK_SIZE;
context_info->cu.uctx.uc_link = uctx_link;
makecontext(&context_info->cu.uctx, func, 0);
@@ -116,10 +116,18 @@ static int stress_context_init(
*/
static int stress_context(const stress_args_t *args)
{
- static uint8_t stack_sig[SIGSTKSZ + STACK_ALIGNMENT];
+ uint8_t *stack_sig;
size_t i;
- if (stress_sigaltstack(stack_sig, SIGSTKSZ) < 0)
+ stack_sig = mmap(NULL, STRESS_SIGSTKSZ, PROT_READ | PROT_WRITE,
+ MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+ if (stack_sig == MAP_FAILED) {
+ pr_inf("%s: cannot allocate signal stack, errno=%d (%s)\n",
+ args->name, errno, strerror(errno));
+ return EXIT_NO_RESOURCE;
+ }
+
+ if (stress_sigaltstack(stack_sig, STRESS_SIGSTKSZ) < 0)
return EXIT_FAILURE;
__counter = 0;
@@ -155,6 +163,7 @@ static int stress_context(const stress_args_t *args)
}
}
stress_set_proc_state(args->name, STRESS_STATE_DEINIT);
+ (void)munmap((void *)stack_sig, STRESS_SIGSTKSZ);
return EXIT_SUCCESS;
}
diff --git a/stress-ng.c b/stress-ng.c
index 08d9bcc1..820de3c6 100644
--- a/stress-ng.c
+++ b/stress-ng.c
@@ -3108,11 +3108,8 @@ static inline void stress_mlock_executable(void)
#if defined(MLOCKED_SECTION)
extern void *__start_mlocked_text;
extern void *__stop_mlocked_text;
- extern void *__start_mlocked_data;
- extern void *__stop_mlocked_data;
stress_mlock_region(&__start_mlocked_text, &__stop_mlocked_text);
- stress_mlock_region(&__start_mlocked_data, &__stop_mlocked_data);
#endif
}
diff --git a/stress-ng.h b/stress-ng.h
index 1128750f..48f39b79 100644
--- a/stress-ng.h
+++ b/stress-ng.h
@@ -1250,11 +1250,11 @@ typedef struct { /* vmstat column */
NEED_GNUC(4,6,0) && \
!defined(__sun__) && \
!defined(BUILD_STATIC)
-#define MLOCKED_DATA __attribute__((__section__("mlocked_data")))
+//#define MLOCKED_DATA __attribute__((__section__("mlocked_data")))
#define MLOCKED_TEXT __attribute__((__section__("mlocked_text")))
#define MLOCKED_SECTION 1
#else
-#define MLOCKED_DATA
+//#define MLOCKED_DATA
#define MLOCKED_TEXT
#endif
@@ -3927,6 +3927,12 @@ extern WARN_UNUSED int32_t stress_get_opt_sched(const char *const str);
extern WARN_UNUSED int32_t stress_get_opt_ionice_class(const char *const str);
/* Misc helper funcs */
+extern WARN_UNUSED size_t stress_sig_stack_size(void);
+extern WARN_UNUSED size_t stress_min_sig_stack_size(void);
+
+#define STRESS_SIGSTKSZ (stress_sig_stack_size())
+#define STRESS_MINSIGSTKSZ (stress_min_sig_stack_size())
+
extern void stress_unmap_shared(void);
extern void stress_log_system_mem_info(void);
extern WARN_UNUSED char *stress_munge_underscore(const char *str);
diff --git a/stress-rlimit.c b/stress-rlimit.c
index 4fb4d09a..c6c674a8 100644
--- a/stress-rlimit.c
+++ b/stress-rlimit.c
@@ -147,10 +147,20 @@ static void MLOCKED_TEXT stress_rlimit_handler(int signum)
static int stress_rlimit_child(const stress_args_t *args, void *ctxt)
{
stress_rlimit_context_t *context = (stress_rlimit_context_t *)ctxt;
- static unsigned char stack[MINSIGSTKSZ];
+ uint8_t *stack;
- if (stress_sigaltstack(stack, MINSIGSTKSZ) < 0)
+ stack = mmap(NULL, STRESS_MINSIGSTKSZ, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (stack == MAP_FAILED) {
+ pr_inf("%s: cannot allocate signal stack: %d (%s)\n",
+ args->name, errno, strerror(errno));
return EXIT_NO_RESOURCE;
+ }
+
+ if (stress_sigaltstack(stack, STRESS_MINSIGSTKSZ) < 0) {
+ (void)munmap((void *)stack, STRESS_MINSIGSTKSZ);
+ return EXIT_NO_RESOURCE;
+ }
stress_set_proc_state(args->name, STRESS_STATE_RUN);
@@ -261,6 +271,7 @@ static int stress_rlimit_child(const stress_args_t *args, void *ctxt)
stress_set_proc_state(args->name, STRESS_STATE_DEINIT);
(void)close(context->fd);
+ (void)munmap((void *)stack, STRESS_MINSIGSTKSZ);
return EXIT_SUCCESS;
}
diff --git a/stress-stack.c b/stress-stack.c
index 644af726..06d12670 100644
--- a/stress-stack.c
+++ b/stress-stack.c
@@ -132,9 +132,6 @@ static int stress_stack_child(const stress_args_t *args, void *context)
{
char *start_ptr = shim_sbrk(0);
void *altstack;
- ssize_t altstack_size = (SIGSTKSZ +
- STACK_ALIGNMENT +
- args->page_size) & ~(args->page_size -1);
bool stack_fill = false;
bool stack_mlock = false;
@@ -149,11 +146,14 @@ static int stress_stack_child(const stress_args_t *args, void *context)
* if there is no memory to back it later. Stack
* must be privately mapped.
*/
- altstack = mmap(NULL, altstack_size, PROT_READ | PROT_WRITE,
+ altstack = mmap(NULL, STRESS_SIGSTKSZ, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if (altstack == MAP_FAILED)
+ if (altstack == MAP_FAILED) {
+ pr_inf("%s: cannot allocate signal stack: errno = %d (%s)\n",
+ args->name, errno, strerror(errno));
return EXIT_NO_RESOURCE;
- (void)stress_mincore_touch_pages(altstack, altstack_size);
+ }
+ (void)stress_mincore_touch_pages(altstack, STRESS_SIGSTKSZ);
/*
* We need to create an alternative signal
@@ -162,8 +162,8 @@ static int stress_stack_child(const stress_args_t *args, void *context)
* than try to push onto an already overflowed
* stack
*/
- if (stress_sigaltstack(altstack, SIGSTKSZ) < 0) {
- (void)munmap(altstack, altstack_size);
+ if (stress_sigaltstack(altstack, STRESS_SIGSTKSZ) < 0) {
+ (void)munmap(altstack, STRESS_SIGSTKSZ);
return EXIT_NO_RESOURCE;
}
@@ -221,7 +221,7 @@ static int stress_stack_child(const stress_args_t *args, void *context)
}
stress_set_proc_state(args->name, STRESS_STATE_DEINIT);
- (void)munmap(altstack, altstack_size);
+ (void)munmap((void *)altstack, STRESS_SIGSTKSZ);
return EXIT_SUCCESS;
}
diff --git a/stress-stackmmap.c b/stress-stackmmap.c
index 2f90aaae..0cdc2019 100644
--- a/stress-stackmmap.c
+++ b/stress-stackmmap.c
@@ -86,32 +86,6 @@ static void stress_stackmmap_push_msync(void)
*/
static void stress_stackmmap_push_start(void)
{
- /* stack for SEGV handler must not be on the stack */
- static uint8_t stack_sig[SIGSTKSZ + STACK_ALIGNMENT];
- struct sigaction new_action;
-
- /*
- * We need to handle SEGV signals when we
- * hit the end of the mmap'd stack; however
- * an alternative signal handling stack
- * is required because we ran out of stack
- */
- (void)memset(&new_action, 0, sizeof new_action);
- new_action.sa_handler = stress_segvhandler;
- (void)sigemptyset(&new_action.sa_mask);
- new_action.sa_flags = SA_ONSTACK;
- if (sigaction(SIGSEGV, &new_action, NULL) < 0)
- return;
-
- /*
- * We need an alternative signal stack
- * to handle segfaults on an overrun
- * mmap'd stack
- */
- (void)memset(stack_sig, 0, sizeof(stack_sig));
- if (stress_sigaltstack(stack_sig, SIGSTKSZ) < 0)
- return;
-
stress_stackmmap_push_msync();
}
@@ -124,6 +98,8 @@ static int stress_stackmmap(const stress_args_t *args)
int fd, ret;
volatile int rc = EXIT_FAILURE; /* could be clobbered */
char filename[PATH_MAX];
+ uint8_t *stack_sig;
+ struct sigaction new_action;
page_size = args->page_size;
page_mask = ~(page_size - 1);
@@ -148,20 +124,31 @@ static int stress_stackmmap(const stress_args_t *args)
(void)close(fd);
goto tidy_dir;
}
- stack_mmap = (uint8_t *)mmap(NULL, MMAPSTACK_SIZE, PROT_READ | PROT_WRITE,
- MAP_SHARED, fd, 0);
+ stack_sig = (uint8_t *)mmap(NULL, STRESS_SIGSTKSZ,
+ PROT_READ | PROT_WRITE, MAP_SHARED, -1, 0);
+ if (stack_sig == MAP_FAILED) {
+ pr_inf("%s: skipping stressor, cannot mmap signal stack, "
+ "errno=%d (%s)\n",
+ args->name, errno, strerror(errno));
+ rc = EXIT_NO_RESOURCE;
+ (void)close(fd);
+ goto tidy_dir;
+ }
+
+ stack_mmap = (uint8_t *)mmap(NULL, MMAPSTACK_SIZE,
+ PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (stack_mmap == MAP_FAILED) {
if (errno == ENXIO) {
pr_inf("%s: skipping stressor, mmap not possible on file %s\n",
args->name, filename);
rc = EXIT_NO_RESOURCE;
(void)close(fd);
- goto tidy_dir;
+ goto tidy_stack_sig;
}
pr_fail("%s: mmap failed, errno=%d (%s)\n",
args->name, errno, strerror(errno));
(void)close(fd);
- goto tidy_dir;
+ goto tidy_stack_sig;
}
(void)close(fd);
@@ -231,6 +218,27 @@ static int stress_stackmmap(const stress_args_t *args)
/* Make sure this is killable by OOM killer */
stress_set_oom_adjustment(args->name, true);
+ /*
+ * We need to handle SEGV signals when we
+ * hit the end of the mmap'd stack; however
+ * an alternative signal handling stack
+ * is required because we ran out of stack
+ */
+ (void)memset(&new_action, 0, sizeof new_action);
+ new_action.sa_handler = stress_segvhandler;
+ (void)sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_ONSTACK;
+ if (sigaction(SIGSEGV, &new_action, NULL) < 0)
+ _exit(EXIT_FAILURE);
+
+ /*
+ * We need an alternative signal stack
+ * to handle segfaults on an overrun
+ * mmap'd stack
+ */
+ if (stress_sigaltstack(stack_sig, STRESS_SIGSTKSZ) < 0)
+ _exit(EXIT_FAILURE);
+
(void)makecontext(&c_test, stress_stackmmap_push_start, 0);
(void)swapcontext(&c_main, &c_test);
@@ -244,6 +252,8 @@ static int stress_stackmmap(const stress_args_t *args)
tidy_mmap:
stress_set_proc_state(args->name, STRESS_STATE_DEINIT);
(void)munmap((void *)stack_mmap, MMAPSTACK_SIZE);
+tidy_stack_sig:
+ (void)munmap((void *)stack_sig, STRESS_SIGSTKSZ);
tidy_dir:
stress_set_proc_state(args->name, STRESS_STATE_DEINIT);
(void)stress_temp_dir_rm_args(args);
diff --git a/stress-vforkmany.c b/stress-vforkmany.c
index 852bde2e..6d7f7807 100644
--- a/stress-vforkmany.c
+++ b/stress-vforkmany.c
@@ -79,13 +79,20 @@ static int stress_vforkmany(const stress_args_t *args)
{
static pid_t chpid;
static volatile int instance = 0;
- static uint8_t stack_sig[SIGSTKSZ + SIGSTKSZ];
+ static uint8_t *stack_sig;
static volatile bool *terminate;
static bool *terminate_mmap;
/* We should use an alternative signal stack */
- (void)memset(stack_sig, 0, sizeof(stack_sig));
- if (stress_sigaltstack(stack_sig, SIGSTKSZ) < 0)
+ stack_sig = mmap(NULL, STRESS_SIGSTKSZ, PROT_READ | PROT_WRITE,
+ MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+ if (stack_sig == MAP_FAILED) {
+ pr_inf("%s: skipping stressor, cannot allocate signal stack,"
+ " errno=%d (%s)\n",
+ args->name, errno, strerror(errno));
+ return EXIT_NO_RESOURCE;
+ }
+ if (stress_sigaltstack(stack_sig, STRESS_SIGSTKSZ) < 0)
return EXIT_FAILURE;
terminate = terminate_mmap =
@@ -219,6 +226,7 @@ static int stress_vforkmany(const stress_args_t *args)
stress_set_proc_state(args->name, STRESS_STATE_DEINIT);
(void)munmap((void *)terminate_mmap, args->page_size);
+ (void)munmap((void *)stack_sig, STRESS_SIGSTKSZ);
return EXIT_SUCCESS;
}

View File

@ -6,6 +6,8 @@ Summary: Stress test a computer system in various ways
License: GPLv2+
URL: https://kernel.ubuntu.com/~cking/%{name}
Source0: https://kernel.ubuntu.com/~cking/tarballs/%{name}/%{name}-%{version}.tar.xz
# https://github.com/ColinIanKing/stress-ng/issues/107
Patch0: stress-ng-0.12.03-sigstksz.patch
BuildRequires: make
BuildRequires: gcc
@ -29,6 +31,7 @@ system kernel interfaces.
%prep
%setup -q
%patch0 -p1
%build
export CFLAGS="%{optflags}"