1 // test prctl per process setting
2 #define _GNU_SOURCE 1
3 #include <stdlib.h>
4 #include <sys/mman.h>
5 #include <stdio.h>
6 #include <unistd.h>
7 #include <sys/prctl.h>
8 #include <setjmp.h>
9 #include <signal.h>
10
11 #define err(x) perror("FAILURE: " x), exit(1)
12 #define fail(x) printf("FAILURE: " x "\n"), exit(1)
13 #define mb() asm volatile("" ::: "memory")
14
15 #define MADV_POISON 100
16
17 /*
18 * Set early/late kill mode for hwpoison memory corruption.
19 * This influences when the process gets killed on a memory corruption.
20 */
21 #define PR_MCE_KILL 33
22 # define PR_MCE_KILL_CLEAR 0
23 # define PR_MCE_KILL_SET 1
24
25 # define PR_MCE_KILL_LATE 0
26 # define PR_MCE_KILL_EARLY 1
27 # define PR_MCE_KILL_DEFAULT 2
28
29 #define PR_MCE_KILL_GET 34
30
31 sigjmp_buf recover_ctx;
32 volatile int seq;
33
handler(int sig)34 void handler(int sig)
35 {
36 siglongjmp(recover_ctx, 1);
37 }
38
test(int early)39 void test(int early)
40 {
41 int PS = getpagesize();
42 char *ptr = mmap(NULL, PS, PROT_READ|PROT_WRITE,
43 MAP_PRIVATE|MAP_ANONYMOUS|MAP_POPULATE, 0,0);
44 if (ptr == (char *)-1L)
45 err("mmap");
46 signal(SIGBUS, handler);
47 printf("ptr = %p\n", ptr);
48 if (sigsetjmp(recover_ctx, 1) == 0) {
49 seq = 0;
50 printf("injection\n");
51 if (madvise(ptr, PS, MADV_POISON) < 0)
52 err("MADV_POISON");
53 /* early kill should kill here */
54 seq++;
55 mb();
56 printf("faulting\n");
57 /* late kill should kill here */
58 *ptr = 1;
59 printf("finished\n");
60 } else {
61 printf("recovered\n");
62 if (seq == 1 && early)
63 fail("early mode set, but no early kill");
64 if (seq == 0 && !early)
65 fail("late mode set, but early kill");
66 }
67 }
68
main(void)69 int main(void)
70 {
71 int err;
72 err = prctl(PR_MCE_KILL_GET, 0, 0, 0, 0, 0);
73 if (err < 0)
74 err("PR_MCE_KILL_GET");
75 if (err != PR_MCE_KILL_DEFAULT)
76 fail("starting policy not default");
77 if (prctl(PR_MCE_KILL, PR_MCE_KILL_SET, PR_MCE_KILL_LATE, 0, 0, 0) < 0)
78 err("PR_MCE_KILL_SET late");
79 test(0);
80 if (prctl(PR_MCE_KILL, PR_MCE_KILL_SET, PR_MCE_KILL_EARLY, 0, 0, 0) < 0)
81 err("PR_MCE_KILL_SET early");
82 test(1);
83 err = prctl(PR_MCE_KILL_GET, 0, 0, 0,0,0);
84 if (err < 0)
85 err("PR_MCE_KILL_GET");
86 if (err != PR_MCE_KILL_EARLY)
87 fail("get mode not early after setting");
88 if (prctl(PR_MCE_KILL, PR_MCE_KILL_CLEAR, 0, 0,0,0) < 0)
89 err("PR_MCE_KILL_CLEAR");
90 err = prctl(PR_MCE_KILL_GET, 0, 0, 0, 0, 0);
91 if (err < 0)
92 err("PR_MCE_KILL_GET");
93 if (err != PR_MCE_KILL_DEFAULT)
94 fail("ending policy not default");
95 return 0;
96 }
97