blob: bcc1e494b23ec8a9f0154d87bd41024c3aa0f7ab [file] [log] [blame]
// test prctl per process setting
#define _GNU_SOURCE 1
#include <stdlib.h>
#include <sys/mman.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/prctl.h>
#include <setjmp.h>
#include <signal.h>
#define err(x) perror("FAILURE: " x), exit(1)
#define fail(x) printf("FAILURE: " x "\n"), exit(1)
#define mb() asm volatile("" ::: "memory")
#define MADV_POISON 100
/*
* Set early/late kill mode for hwpoison memory corruption.
* This influences when the process gets killed on a memory corruption.
*/
#define PR_MCE_KILL 33
# define PR_MCE_KILL_CLEAR 0
# define PR_MCE_KILL_SET 1
# define PR_MCE_KILL_LATE 0
# define PR_MCE_KILL_EARLY 1
# define PR_MCE_KILL_DEFAULT 2
#define PR_MCE_KILL_GET 34
sigjmp_buf recover_ctx;
volatile int seq;
void handler(int sig)
{
siglongjmp(recover_ctx, 1);
}
void test(int early)
{
int PS = getpagesize();
char *ptr = mmap(NULL, PS, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS|MAP_POPULATE, 0,0);
if (ptr == (char *)-1L)
err("mmap");
signal(SIGBUS, handler);
printf("ptr = %p\n", ptr);
if (sigsetjmp(recover_ctx, 1) == 0) {
seq = 0;
printf("injection\n");
if (madvise(ptr, PS, MADV_POISON) < 0)
err("MADV_POISON");
/* early kill should kill here */
seq++;
mb();
printf("faulting\n");
/* late kill should kill here */
*ptr = 1;
printf("finished\n");
} else {
printf("recovered\n");
if (seq == 1 && early)
fail("early mode set, but no early kill");
if (seq == 0 && !early)
fail("late mode set, but early kill");
}
}
int main(void)
{
int err;
err = prctl(PR_MCE_KILL_GET, 0, 0, 0, 0, 0);
if (err < 0)
err("PR_MCE_KILL_GET");
if (err != PR_MCE_KILL_DEFAULT)
fail("starting policy not default");
if (prctl(PR_MCE_KILL, PR_MCE_KILL_SET, PR_MCE_KILL_LATE, 0, 0, 0) < 0)
err("PR_MCE_KILL_SET late");
test(0);
if (prctl(PR_MCE_KILL, PR_MCE_KILL_SET, PR_MCE_KILL_EARLY, 0, 0, 0) < 0)
err("PR_MCE_KILL_SET early");
test(1);
err = prctl(PR_MCE_KILL_GET, 0, 0, 0,0,0);
if (err < 0)
err("PR_MCE_KILL_GET");
if (err != PR_MCE_KILL_EARLY)
fail("get mode not early after setting");
if (prctl(PR_MCE_KILL, PR_MCE_KILL_CLEAR, 0, 0,0,0) < 0)
err("PR_MCE_KILL_CLEAR");
err = prctl(PR_MCE_KILL_GET, 0, 0, 0, 0, 0);
if (err < 0)
err("PR_MCE_KILL_GET");
if (err != PR_MCE_KILL_DEFAULT)
fail("ending policy not default");
return 0;
}