From f20d7d8ea3840487c8caf458226a98380749f89d Mon Sep 17 00:00:00 2001 From: Michael Kerrisk Date: Fri, 25 May 2007 18:57:30 +0000 Subject: [PATCH] A much improved eample program. --- man2/mprotect.2 | 85 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 61 insertions(+), 24 deletions(-) diff --git a/man2/mprotect.2 b/man2/mprotect.2 index 69cf11589..572b789e7 100644 --- a/man2/mprotect.2 +++ b/man2/mprotect.2 @@ -121,46 +121,83 @@ has any effect different from .B PROT_READ is architecture and kernel version dependent. .SH EXAMPLE +.PP +The program below allocates 4 pages of memory, makes the third +of these pages read-only, and then executes a loop that walks upwards +through the allocated region modifying bytes. + +An example of what we might see when running the program is the +following: + +.in +0.5i .nf +$ ./a.out +Start of region: 0x804c000 +Got SIGSEGV at address: 0x804e000 +.fi +.in +.nf + +#include +#include #include +#include #include #include #include -#include /* for PAGESIZE */ -#ifndef PAGESIZE -#define PAGESIZE 4096 -#endif +char *buffer; + +static void +handler(int sig, siginfo_t *si, void *unused) +{ + printf("Got SIGSEGV at address: 0x%lx\\n", + (long) si->si_addr); + exit(EXIT_FAILURE); +} int -main(void) +main(int argc, char *argv[]) { char *p; - char c; + int pagesize; + struct sigaction sa; - /* Allocate a buffer; it will have the default - protection of PROT_READ|PROT_WRITE. */ - p = malloc(1024+PAGESIZE-1); - if (!p) { - perror("Couldn't malloc(1024)"); - exit(errno); + sa.sa_flags = SA_SIGINFO; + sigemptyset(&sa.sa_mask); + sa.sa_sigaction = handler; + if (sigaction(SIGSEGV, &sa, NULL) == -1) { + perror("sigaction"); + exit(EXIT_FAILURE); } - /* Align to a multiple of PAGESIZE, assumed to be a power of two */ - p = (char *)(((int) p + PAGESIZE-1) & ~(PAGESIZE-1)); - - c = p[666]; /* Read; ok */ - p[666] = 42; /* Write; ok */ - - /* Mark the buffer read-only. */ - if (mprotect(p, 1024, PROT_READ)) { - perror("Couldn't mprotect"); - exit(errno); + pagesize = sysconf(_SC_PAGE_SIZE); + if (pagesize == -1) { + perror("sysconf"); + exit(EXIT_FAILURE); } - c = p[666]; /* Read; ok */ - p[666] = 42; /* Write; program dies on SIGSEGV */ + /* Allocate a buffer aligned on a page boundary; + initial protection is PROT_READ | PROT_WRITE */ + buffer = memalign(pagesize, 4 * pagesize); + if (buffer == NULL) { + perror("memalign"); + exit(EXIT_FAILURE); + } + + printf("Start of region: 0x%lx\\n", (long) buffer); + + if (mprotect(buffer + pagesize * 2, pagesize, + PROT_NONE) == -1) { + perror("mprotect"); + exit(EXIT_FAILURE); + } + + for (p = buffer ; ; ) + *(p++) = 'a'; + + printf("Loop completed\\n"); /* Should never happen */ exit(EXIT_SUCCESS); } .fi