662 lines
21 KiB
Diff
662 lines
21 KiB
Diff
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;
|
|
}
|
|
|