119 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Test that signal delivery is able to expand the stack segment without4 * 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 22static char *stack_base_ptr;23static char *stack_top_ptr;24 25static volatile sig_atomic_t sig_occurred = 0;26 27static void sigusr1_handler(int signal_arg)28{29 sig_occurred = 1;30}31 32static 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 50static 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 72static 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 101int test(void)102{103 unsigned int i, size;104 105 // Test with used stack from 1MB - 64K to 1MB + 64K106 // Increment by 64 to get more coverage of odd sizes107 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 115int main(void)116{117 return test_harness(test, "stack_expansion_signal");118}119