1f08c3bdfSopenharmony_ci/* 2f08c3bdfSopenharmony_ci * Test program for Linux memory error recovery. 3f08c3bdfSopenharmony_ci * Requires special injection support. 4f08c3bdfSopenharmony_ci * 5f08c3bdfSopenharmony_ci * This is a early primitive version of tinjpage.c, 6f08c3bdfSopenharmony_ci * but simpler to debug in some cases. 7f08c3bdfSopenharmony_ci */ 8f08c3bdfSopenharmony_ci#define _GNU_SOURCE 1 9f08c3bdfSopenharmony_ci#include <sys/mman.h> 10f08c3bdfSopenharmony_ci#include <stdio.h> 11f08c3bdfSopenharmony_ci#include <signal.h> 12f08c3bdfSopenharmony_ci#include <unistd.h> 13f08c3bdfSopenharmony_ci#include <sys/fcntl.h> 14f08c3bdfSopenharmony_ci#include <stdlib.h> 15f08c3bdfSopenharmony_ci#include <setjmp.h> 16f08c3bdfSopenharmony_ci#include <errno.h> 17f08c3bdfSopenharmony_ci#include <string.h> 18f08c3bdfSopenharmony_ci 19f08c3bdfSopenharmony_ci#define MADV_POISON 100 20f08c3bdfSopenharmony_ci 21f08c3bdfSopenharmony_ci#define err(x) perror(x),exit(1) 22f08c3bdfSopenharmony_ci 23f08c3bdfSopenharmony_ciint count = 20; 24f08c3bdfSopenharmony_ciint failure = 0; 25f08c3bdfSopenharmony_ciint total_cases = 0; 26f08c3bdfSopenharmony_cisigjmp_buf recover; 27f08c3bdfSopenharmony_ciint PS; 28f08c3bdfSopenharmony_ci 29f08c3bdfSopenharmony_civoid sighandler(int sig, siginfo_t *si, void *arg) 30f08c3bdfSopenharmony_ci{ 31f08c3bdfSopenharmony_ci printf("signal %d code %d addr %p\n", sig, si->si_code, si->si_addr); 32f08c3bdfSopenharmony_ci 33f08c3bdfSopenharmony_ci if (--count == 0) 34f08c3bdfSopenharmony_ci exit(1); 35f08c3bdfSopenharmony_ci 36f08c3bdfSopenharmony_ci siglongjmp(recover, 1); 37f08c3bdfSopenharmony_ci} 38f08c3bdfSopenharmony_ci 39f08c3bdfSopenharmony_civoid testmem(char *msg, char *page, int write) 40f08c3bdfSopenharmony_ci{ 41f08c3bdfSopenharmony_ci printf("%s page %p\n", msg, page); 42f08c3bdfSopenharmony_ci total_cases++; 43f08c3bdfSopenharmony_ci if (sigsetjmp(recover,1) == 0) { 44f08c3bdfSopenharmony_ci if (madvise(page, PS, MADV_POISON) != 0) { 45f08c3bdfSopenharmony_ci failure++; 46f08c3bdfSopenharmony_ci perror("madvise"); 47f08c3bdfSopenharmony_ci } 48f08c3bdfSopenharmony_ci if (write) 49f08c3bdfSopenharmony_ci *page = 2; 50f08c3bdfSopenharmony_ci else 51f08c3bdfSopenharmony_ci printf("%x\n", *(unsigned char *)page); 52f08c3bdfSopenharmony_ci } 53f08c3bdfSopenharmony_ci printf("recovered\n"); 54f08c3bdfSopenharmony_ci} 55f08c3bdfSopenharmony_ci 56f08c3bdfSopenharmony_civoid expecterr(char *msg, int res) 57f08c3bdfSopenharmony_ci{ 58f08c3bdfSopenharmony_ci if (res == 0) 59f08c3bdfSopenharmony_ci printf("no error on %s\n", msg); 60f08c3bdfSopenharmony_ci else 61f08c3bdfSopenharmony_ci perror(msg); 62f08c3bdfSopenharmony_ci} 63f08c3bdfSopenharmony_ci 64f08c3bdfSopenharmony_ciint tempfd(void) 65f08c3bdfSopenharmony_ci{ 66f08c3bdfSopenharmony_ci static int tmpcount; 67f08c3bdfSopenharmony_ci int fd; 68f08c3bdfSopenharmony_ci char buf[30]; 69f08c3bdfSopenharmony_ci snprintf(buf,30,"/tmp/test%d.XXXXXXXX",tmpcount++); 70f08c3bdfSopenharmony_ci fd = mkstemp(buf); 71f08c3bdfSopenharmony_ci if (fd >= 0) 72f08c3bdfSopenharmony_ci unlink(buf); 73f08c3bdfSopenharmony_ci return fd; 74f08c3bdfSopenharmony_ci} 75f08c3bdfSopenharmony_ci 76f08c3bdfSopenharmony_ci#define RANDOM_FILE "/etc/profile" 77f08c3bdfSopenharmony_ci 78f08c3bdfSopenharmony_ciint main(void) 79f08c3bdfSopenharmony_ci{ 80f08c3bdfSopenharmony_ci PS = getpagesize(); 81f08c3bdfSopenharmony_ci char *page; 82f08c3bdfSopenharmony_ci 83f08c3bdfSopenharmony_ci struct sigaction sa = { 84f08c3bdfSopenharmony_ci .sa_sigaction = sighandler, 85f08c3bdfSopenharmony_ci .sa_flags = SA_SIGINFO 86f08c3bdfSopenharmony_ci }; 87f08c3bdfSopenharmony_ci sigaction(SIGBUS, &sa, NULL); 88f08c3bdfSopenharmony_ci// sigaction(SIGSEGV, &sa, NULL); 89f08c3bdfSopenharmony_ci 90f08c3bdfSopenharmony_ci page = mmap(NULL, PS, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_POPULATE, 0, 0); 91f08c3bdfSopenharmony_ci testmem("dirty", page, 1); 92f08c3bdfSopenharmony_ci 93f08c3bdfSopenharmony_ci page = mmap(NULL, PS, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_LOCKED, 0, 0); 94f08c3bdfSopenharmony_ci testmem("mlocked", page, 1); 95f08c3bdfSopenharmony_ci 96f08c3bdfSopenharmony_ci int fd = open(RANDOM_FILE, O_RDONLY); 97f08c3bdfSopenharmony_ci if (fd < 0) err("open " RANDOM_FILE); 98f08c3bdfSopenharmony_ci page = mmap(NULL, PS, PROT_READ, MAP_SHARED|MAP_POPULATE, fd, 0); 99f08c3bdfSopenharmony_ci if (page == (char *)-1) err("mmap"); 100f08c3bdfSopenharmony_ci close(fd); 101f08c3bdfSopenharmony_ci testmem("clean file", page, 0); 102f08c3bdfSopenharmony_ci 103f08c3bdfSopenharmony_ci fd = tempfd(); 104f08c3bdfSopenharmony_ci if (fd < 0) err("open testfile"); 105f08c3bdfSopenharmony_ci char *tmp = malloc(PS); 106f08c3bdfSopenharmony_ci if (!tmp) err("no enough memory"); 107f08c3bdfSopenharmony_ci memset(tmp, 0xff, PS); 108f08c3bdfSopenharmony_ci write(fd, tmp, PS); 109f08c3bdfSopenharmony_ci free(tmp); 110f08c3bdfSopenharmony_ci page = mmap(NULL, PS, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 111f08c3bdfSopenharmony_ci if (page == (char*)-1) err("mmap"); 112f08c3bdfSopenharmony_ci *page = 1; 113f08c3bdfSopenharmony_ci testmem("file dirty", page, 0); 114f08c3bdfSopenharmony_ci expecterr("msync expect error", msync(page, PS, MS_SYNC)); 115f08c3bdfSopenharmony_ci expecterr("fsync expect error", fsync(fd)); 116f08c3bdfSopenharmony_ci close(fd); 117f08c3bdfSopenharmony_ci 118f08c3bdfSopenharmony_ci /* hole case still broken in the kernel -- doesn't report error */ 119f08c3bdfSopenharmony_ci fd = tempfd(); 120f08c3bdfSopenharmony_ci if (fd < 0) err("open testfile"); 121f08c3bdfSopenharmony_ci ftruncate(fd, PS); 122f08c3bdfSopenharmony_ci page = mmap(NULL, PS, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 123f08c3bdfSopenharmony_ci if (page == (char*)-1) err("mmap"); 124f08c3bdfSopenharmony_ci *page = 1; 125f08c3bdfSopenharmony_ci testmem("hole file dirty", page, 0); 126f08c3bdfSopenharmony_ci expecterr("hole msync expect error", msync(page, PS, MS_SYNC)); 127f08c3bdfSopenharmony_ci expecterr("hole fsync expect error", fsync(fd)); 128f08c3bdfSopenharmony_ci close(fd); 129f08c3bdfSopenharmony_ci 130f08c3bdfSopenharmony_ci#if 0 131f08c3bdfSopenharmony_ci const int NPAGES = 10; 132f08c3bdfSopenharmony_ci int i; 133f08c3bdfSopenharmony_ci fd = tempfd(); 134f08c3bdfSopenharmony_ci if (fd < 0) err("open rfp testfile"); 135f08c3bdfSopenharmony_ci tmp = malloc(PS); 136f08c3bdfSopenharmony_ci if (!tmp) exit(ENOMEM); 137f08c3bdfSopenharmony_ci for (i = 0; i < NPAGES; i++) { 138f08c3bdfSopenharmony_ci memset(tmp, i, PS); 139f08c3bdfSopenharmony_ci write(fd, tmp, PS); 140f08c3bdfSopenharmony_ci } 141f08c3bdfSopenharmony_ci free(tmp); 142f08c3bdfSopenharmony_ci page = mmap(NULL, PS*NPAGES, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 143f08c3bdfSopenharmony_ci if (page == (char*)-1) err("mmap"); 144f08c3bdfSopenharmony_ci int k = NPAGES - 1; 145f08c3bdfSopenharmony_ci for (i = 0; i < NPAGES; i++, k--) { 146f08c3bdfSopenharmony_ci if (remap_file_pages(page + i*PS, PS, 0, k, 0)) 147f08c3bdfSopenharmony_ci perror("remap_file_pages"); 148f08c3bdfSopenharmony_ci } 149f08c3bdfSopenharmony_ci *page = 1; 150f08c3bdfSopenharmony_ci testmem("rfp file dirty", page, 0); 151f08c3bdfSopenharmony_ci expecterr("rfp msync expect error", msync(page, PS, MS_SYNC)); 152f08c3bdfSopenharmony_ci expecterr("rfp fsync expect error", fsync(fd)); 153f08c3bdfSopenharmony_ci close(fd); 154f08c3bdfSopenharmony_ci#endif 155f08c3bdfSopenharmony_ci 156f08c3bdfSopenharmony_ci if (failure > 0) { 157f08c3bdfSopenharmony_ci printf("FAILURE -- %d of %d cases broken!\n", failure, total_cases); 158f08c3bdfSopenharmony_ci return 1; 159f08c3bdfSopenharmony_ci } 160f08c3bdfSopenharmony_ci printf("SUCCESS\n"); 161f08c3bdfSopenharmony_ci 162f08c3bdfSopenharmony_ci return 0; 163f08c3bdfSopenharmony_ci} 164f08c3bdfSopenharmony_ci 165f08c3bdfSopenharmony_ci 166