diff --git a/stress-ng-0.12.03-sigstksz.patch b/stress-ng-0.12.03-sigstksz.patch new file mode 100644 index 0000000..b05c935 --- /dev/null +++ b/stress-ng-0.12.03-sigstksz.patch @@ -0,0 +1,661 @@ +From 7c4f74761089177127c2cfe6685b7886aa231885 Mon Sep 17 00:00:00 2001 +From: Colin Ian King +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 +--- + 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; + } + diff --git a/stress-ng.spec b/stress-ng.spec index 8e2868b..a5a24cc 100644 --- a/stress-ng.spec +++ b/stress-ng.spec @@ -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}"