]> Git Repo - J-linux.git/blob - tools/testing/selftests/powerpc/mm/stack_expansion_signal.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / tools / testing / selftests / powerpc / mm / stack_expansion_signal.c
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 }
This page took 0.034131 seconds and 4 git commands to generate.