linux/tools/testing/selftests/powerpc/mm/stack_expansion_signal.c
<<
>>
Prefs
   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
  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 + 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
 115int main(void)
 116{
 117        return test_harness(test, "stack_expansion_signal");
 118}
 119