1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Test that signal delivery is able to expand the stack segment without 4 * triggering a SEGV. 5 * 6 * Based on test code by Tom Lane. 7 */ 8 9 #include <err.h> 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <signal.h> 13 #include <sys/types.h> 14 #include <unistd.h> 15 16 #include "../pmu/lib.h" 17 #include "utils.h" 18 19 #define _KB (1024) 20 #define _MB (1024 * 1024) 21 22 static char *stack_base_ptr; 23 static char *stack_top_ptr; 24 25 static volatile sig_atomic_t sig_occurred = 0; 26 27 static void sigusr1_handler(int signal_arg) 28 { 29 sig_occurred = 1; 30 } 31 32 static int consume_stack(unsigned int stack_size, union pipe write_pipe) 33 { 34 char stack_cur; 35 36 if ((stack_base_ptr - &stack_cur) < stack_size) 37 return consume_stack(stack_size, write_pipe); 38 else { 39 stack_top_ptr = &stack_cur; 40 41 FAIL_IF(notify_parent(write_pipe)); 42 43 while (!sig_occurred) 44 barrier(); 45 } 46 47 return 0; 48 } 49 50 static int child(unsigned int stack_size, union pipe write_pipe) 51 { 52 struct sigaction act; 53 char stack_base; 54 55 act.sa_handler = sigusr1_handler; 56 sigemptyset(&act.sa_mask); 57 act.sa_flags = 0; 58 if (sigaction(SIGUSR1, &act, NULL) < 0) 59 err(1, "sigaction"); 60 61 stack_base_ptr = (char *) (((size_t) &stack_base + 65535) & ~65535UL); 62 63 FAIL_IF(consume_stack(stack_size, write_pipe)); 64 65 printf("size 0x%06x: OK, stack base %p top %p (%zx used)\n", 66 stack_size, stack_base_ptr, stack_top_ptr, 67 stack_base_ptr - stack_top_ptr); 68 69 return 0; 70 } 71 72 static int test_one_size(unsigned int stack_size) 73 { 74 union pipe read_pipe, write_pipe; 75 pid_t pid; 76 77 FAIL_IF(pipe(read_pipe.fds) == -1); 78 FAIL_IF(pipe(write_pipe.fds) == -1); 79 80 pid = fork(); 81 if (pid == 0) { 82 close(read_pipe.read_fd); 83 close(write_pipe.write_fd); 84 exit(child(stack_size, read_pipe)); 85 } 86 87 close(read_pipe.write_fd); 88 close(write_pipe.read_fd); 89 FAIL_IF(sync_with_child(read_pipe, write_pipe)); 90 91 kill(pid, SIGUSR1); 92 93 FAIL_IF(wait_for_child(pid)); 94 95 close(read_pipe.read_fd); 96 close(write_pipe.write_fd); 97 98 return 0; 99 } 100 101 int test(void) 102 { 103 unsigned int i, size; 104 105 // Test with used stack from 1MB - 64K to 1MB + 64K 106 // Increment by 64 to get more coverage of odd sizes 107 for (i = 0; i < (128 * _KB); i += 64) { 108 size = i + (1 * _MB) - (64 * _KB); 109 FAIL_IF(test_one_size(size)); 110 } 111 112 return 0; 113 } 114 115 int main(void) 116 { 117 return test_harness(test, "stack_expansion_signal"); 118 } 119