1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright 2015, Michael Neuling, IBM Corp. |
4 | * |
5 | * Test the kernel's signal delievery code to ensure that we don't |
6 | * trelaim twice in the kernel signal delivery code. This can happen |
7 | * if we trigger a signal when in a transaction and the stack pointer |
8 | * is bogus. |
9 | * |
10 | * This test case registers a SEGV handler, sets the stack pointer |
11 | * (r1) to NULL, starts a transaction and then generates a SEGV. The |
12 | * SEGV should be handled but we exit here as the stack pointer is |
13 | * invalid and hance we can't sigreturn. We only need to check that |
14 | * this flow doesn't crash the kernel. |
15 | */ |
16 | |
17 | #include <unistd.h> |
18 | #include <sys/types.h> |
19 | #include <sys/wait.h> |
20 | #include <stdlib.h> |
21 | #include <stdio.h> |
22 | #include <signal.h> |
23 | |
24 | #include "utils.h" |
25 | #include "tm.h" |
26 | |
27 | void signal_segv(int signum) |
28 | { |
29 | /* This should never actually run since stack is foobar */ |
30 | exit(1); |
31 | } |
32 | |
33 | int tm_signal_stack() |
34 | { |
35 | int pid; |
36 | |
37 | SKIP_IF(!have_htm()); |
38 | SKIP_IF(htm_is_synthetic()); |
39 | |
40 | pid = fork(); |
41 | if (pid < 0) |
42 | exit(1); |
43 | |
44 | if (pid) { /* Parent */ |
45 | /* |
46 | * It's likely the whole machine will crash here so if |
47 | * the child ever exits, we are good. |
48 | */ |
49 | wait(NULL); |
50 | return 0; |
51 | } |
52 | |
53 | /* |
54 | * The flow here is: |
55 | * 1) register a signal handler (so signal delievery occurs) |
56 | * 2) make stack pointer (r1) = NULL |
57 | * 3) start transaction |
58 | * 4) cause segv |
59 | */ |
60 | if (signal(SIGSEGV, signal_segv) == SIG_ERR) |
61 | exit(1); |
62 | asm volatile("li 1, 0 ;" /* stack ptr == NULL */ |
63 | "1:" |
64 | "tbegin.;" |
65 | "beq 1b ;" /* retry forever */ |
66 | "tsuspend.;" |
67 | "ld 2, 0(1) ;" /* trigger segv" */ |
68 | : : : "memory" ); |
69 | |
70 | /* This should never get here due to above segv */ |
71 | return 1; |
72 | } |
73 | |
74 | int main(void) |
75 | { |
76 | return test_harness(tm_signal_stack, "tm_signal_stack" ); |
77 | } |
78 | |