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