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
31sigjmp_buf recover_ctx;
32volatile int seq;
33
34void handler(int sig)
35{
36	siglongjmp(recover_ctx, 1);
37}
38
39void 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
69int 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