1/* 2 * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6#include <errno.h> 7#include <limits.h> 8#include <signal.h> 9#include <stdint.h> 10#include <stdio.h> 11#include <stdlib.h> 12#include <signal.h> 13#include <string.h> 14#include <sys/mman.h> 15 16 17#ifndef PAGE_SIZE 18# define PAGE_SIZE 4096 19#endif 20 21 22static const size_t kMapChunkSize = 4 * PAGE_SIZE; 23static const size_t kTestSize = 256 * PAGE_SIZE; 24 25static int64_t sHandledSignals = 0; 26 27static uint8_t* sMappedBase; 28static size_t sMappedSize; 29static uint8_t* sTouchedAddress; 30 31 32static void 33signal_handler(int signal) 34{ 35 sHandledSignals++; 36 37 //printf("SIGSEGV at %p\n", sTouchedAddress); 38 39 // protect the last page of the current allocation writable 40 if (mprotect(sMappedBase + sMappedSize - PAGE_SIZE, PAGE_SIZE, 41 PROT_READ | PROT_WRITE) < 0) { 42 fprintf(stderr, "SIGSEGV: mprotect() failed: %s\n", strerror(errno)); 43 exit(1); 44 } 45 46 // allocate the next chunk 47 void* mappedAddress = mmap(sMappedBase + sMappedSize, kMapChunkSize, 48 PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); 49 if (mappedAddress == MAP_FAILED) { 50 fprintf(stderr, "SIGSEGV: mmap() failed: %s\n", strerror(errno)); 51 exit(1); 52 } 53 54 printf("mapped %d bytes at %p\n", (int)kMapChunkSize, mappedAddress); 55 56 sMappedSize += kMapChunkSize; 57 58 // map the last page read-only 59 if (mprotect(sMappedBase + sMappedSize - PAGE_SIZE, PAGE_SIZE, PROT_READ) 60 < 0) { 61 fprintf(stderr, "SIGSEGV: mprotect() failed: %s\n", strerror(errno)); 62 exit(1); 63 } 64} 65 66 67int 68main() 69{ 70 // install signal handler 71 if (signal(SIGSEGV, signal_handler) == SIG_ERR) { 72 fprintf(stderr, "Error: Failed to install signal handler: %s\n", 73 strerror(errno)); 74 exit(1); 75 } 76 77 // Map the complete test size plus one chunk and unmap all but the first 78 // chunk again, so no other memory gets into the way, when we mmap() the 79 // other chunks with MAP_FIXED. 80 sMappedBase = (uint8_t*)mmap(NULL, kTestSize + kMapChunkSize, 81 PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 82 if (sMappedBase == MAP_FAILED) { 83 fprintf(stderr, "mmap() failed: %s\n", strerror(errno)); 84 return 1; 85 } 86 munmap(sMappedBase + kMapChunkSize, kTestSize); 87 88 sMappedSize = kMapChunkSize; 89 90 printf("mapped %d bytes at %p\n", (int)sMappedSize, sMappedBase); 91 92 if (mprotect(sMappedBase + sMappedSize - PAGE_SIZE, PAGE_SIZE, PROT_READ) 93 < 0) { 94 fprintf(stderr, "mprotect() failed: %s\n", strerror(errno)); 95 return 1; 96 } 97 98 for (int i = 0; i < 256 * PAGE_SIZE; i++) { 99 sTouchedAddress = sMappedBase + i; 100 *sTouchedAddress = 1; 101 } 102 103 printf("test finished successfully!\n"); 104 105 return 0; 106} 107