1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) 2016 Richard Palethorpe <richiejp@f-m.fm> 4f08c3bdfSopenharmony_ci */ 5f08c3bdfSopenharmony_ci 6f08c3bdfSopenharmony_ci/* 7f08c3bdfSopenharmony_ci * Check that accessing a page marked with MADV_HWPOISON results in SIGBUS. 8f08c3bdfSopenharmony_ci * 9f08c3bdfSopenharmony_ci * Test flow: create child process, 10f08c3bdfSopenharmony_ci * map and write to memory, 11f08c3bdfSopenharmony_ci * mark memory with MADV_HWPOISON, 12f08c3bdfSopenharmony_ci * access memory, 13f08c3bdfSopenharmony_ci * if SIGBUS is delivered to child the test passes else it fails 14f08c3bdfSopenharmony_ci * 15f08c3bdfSopenharmony_ci * If the underlying page type of the memory we have mapped does not support 16f08c3bdfSopenharmony_ci * poisoning then the test will fail. We try to map and write to the memory in 17f08c3bdfSopenharmony_ci * such a way that by the time madvise is called the virtual memory address 18f08c3bdfSopenharmony_ci * points to a supported page. However there may be some rare circumstances 19f08c3bdfSopenharmony_ci * where the test produces the wrong result because we have somehow obtained 20f08c3bdfSopenharmony_ci * an unsupported page. In such cases madvise will probably return success, 21f08c3bdfSopenharmony_ci * but no SIGBUS will be produced. 22f08c3bdfSopenharmony_ci * 23f08c3bdfSopenharmony_ci * For more information see <linux source>/Documentation/vm/hwpoison.txt. 24f08c3bdfSopenharmony_ci */ 25f08c3bdfSopenharmony_ci 26f08c3bdfSopenharmony_ci#include <stdlib.h> 27f08c3bdfSopenharmony_ci#include <stdio.h> 28f08c3bdfSopenharmony_ci#include <sys/wait.h> 29f08c3bdfSopenharmony_ci#include <fcntl.h> 30f08c3bdfSopenharmony_ci#include <unistd.h> 31f08c3bdfSopenharmony_ci#include <signal.h> 32f08c3bdfSopenharmony_ci#include <errno.h> 33f08c3bdfSopenharmony_ci#include <string.h> 34f08c3bdfSopenharmony_ci 35f08c3bdfSopenharmony_ci#include "tst_test.h" 36f08c3bdfSopenharmony_ci#include "lapi/mmap.h" 37f08c3bdfSopenharmony_ci 38f08c3bdfSopenharmony_cistatic void run_child(void) 39f08c3bdfSopenharmony_ci{ 40f08c3bdfSopenharmony_ci const size_t msize = getpagesize(); 41f08c3bdfSopenharmony_ci void *mem = NULL; 42f08c3bdfSopenharmony_ci 43f08c3bdfSopenharmony_ci tst_res(TINFO, 44f08c3bdfSopenharmony_ci "mmap(0, %zu, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)", 45f08c3bdfSopenharmony_ci msize); 46f08c3bdfSopenharmony_ci mem = SAFE_MMAP(NULL, 47f08c3bdfSopenharmony_ci msize, 48f08c3bdfSopenharmony_ci PROT_READ | PROT_WRITE, 49f08c3bdfSopenharmony_ci MAP_ANONYMOUS | MAP_PRIVATE, 50f08c3bdfSopenharmony_ci -1, 51f08c3bdfSopenharmony_ci 0); 52f08c3bdfSopenharmony_ci memset(mem, 'L', msize); 53f08c3bdfSopenharmony_ci 54f08c3bdfSopenharmony_ci tst_res(TINFO, "madvise(%p, %zu, MADV_HWPOISON)", mem, msize); 55f08c3bdfSopenharmony_ci if (madvise(mem, msize, MADV_HWPOISON) == -1) { 56f08c3bdfSopenharmony_ci if (errno == EINVAL) { 57f08c3bdfSopenharmony_ci tst_res(TCONF | TERRNO, 58f08c3bdfSopenharmony_ci "CONFIG_MEMORY_FAILURE probably not set in kconfig"); 59f08c3bdfSopenharmony_ci } else { 60f08c3bdfSopenharmony_ci tst_res(TFAIL | TERRNO, "Could not poison memory"); 61f08c3bdfSopenharmony_ci } 62f08c3bdfSopenharmony_ci exit(0); 63f08c3bdfSopenharmony_ci } 64f08c3bdfSopenharmony_ci 65f08c3bdfSopenharmony_ci *((char *)mem) = 'd'; 66f08c3bdfSopenharmony_ci 67f08c3bdfSopenharmony_ci tst_res(TFAIL, "Did not receive SIGBUS on accessing poisoned page"); 68f08c3bdfSopenharmony_ci} 69f08c3bdfSopenharmony_ci 70f08c3bdfSopenharmony_cistatic void run(void) 71f08c3bdfSopenharmony_ci{ 72f08c3bdfSopenharmony_ci int status; 73f08c3bdfSopenharmony_ci pid_t pid; 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_ci pid = SAFE_FORK(); 76f08c3bdfSopenharmony_ci if (pid == 0) { 77f08c3bdfSopenharmony_ci run_child(); 78f08c3bdfSopenharmony_ci exit(0); 79f08c3bdfSopenharmony_ci } 80f08c3bdfSopenharmony_ci 81f08c3bdfSopenharmony_ci SAFE_WAITPID(pid, &status, 0); 82f08c3bdfSopenharmony_ci if (WIFSIGNALED(status) && WTERMSIG(status) == SIGBUS) { 83f08c3bdfSopenharmony_ci tst_res(TPASS, "Received SIGBUS after accessing poisoned page"); 84f08c3bdfSopenharmony_ci return; 85f08c3bdfSopenharmony_ci } 86f08c3bdfSopenharmony_ci 87f08c3bdfSopenharmony_ci if (WIFEXITED(status) && WEXITSTATUS(status) == 0) 88f08c3bdfSopenharmony_ci return; 89f08c3bdfSopenharmony_ci 90f08c3bdfSopenharmony_ci tst_res(TFAIL, "Child %s", tst_strstatus(status)); 91f08c3bdfSopenharmony_ci} 92f08c3bdfSopenharmony_ci 93f08c3bdfSopenharmony_cistatic struct tst_test test = { 94f08c3bdfSopenharmony_ci .test_all = run, 95f08c3bdfSopenharmony_ci .needs_root = 1, 96f08c3bdfSopenharmony_ci .forks_child = 1 97f08c3bdfSopenharmony_ci}; 98f08c3bdfSopenharmony_ci 99