A much improved eample program.

This commit is contained in:
Michael Kerrisk 2007-05-25 18:57:30 +00:00
parent af5267b2f4
commit f20d7d8ea3
1 changed files with 61 additions and 24 deletions

View File

@ -121,46 +121,83 @@ has any effect different from
.B PROT_READ .B PROT_READ
is architecture and kernel version dependent. is architecture and kernel version dependent.
.SH EXAMPLE .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 .nf
$ ./a.out
Start of region: 0x804c000
Got SIGSEGV at address: 0x804e000
.fi
.in
.nf
#include <unistd.h>
#include <signal.h>
#include <stdio.h> #include <stdio.h>
#include <malloc.h>
#include <stdlib.h> #include <stdlib.h>
#include <errno.h> #include <errno.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <limits.h> /* for PAGESIZE */ char *buffer;
#ifndef PAGESIZE
#define PAGESIZE 4096 static void
#endif handler(int sig, siginfo_t *si, void *unused)
{
printf("Got SIGSEGV at address: 0x%lx\\n",
(long) si->si_addr);
exit(EXIT_FAILURE);
}
int int
main(void) main(int argc, char *argv[])
{ {
char *p; char *p;
char c; int pagesize;
struct sigaction sa;
/* Allocate a buffer; it will have the default sa.sa_flags = SA_SIGINFO;
protection of PROT_READ|PROT_WRITE. */ sigemptyset(&sa.sa_mask);
p = malloc(1024+PAGESIZE-1); sa.sa_sigaction = handler;
if (!p) { if (sigaction(SIGSEGV, &sa, NULL) == -1) {
perror("Couldn't malloc(1024)"); perror("sigaction");
exit(errno); exit(EXIT_FAILURE);
} }
/* Align to a multiple of PAGESIZE, assumed to be a power of two */ pagesize = sysconf(_SC_PAGE_SIZE);
p = (char *)(((int) p + PAGESIZE-1) & ~(PAGESIZE-1)); if (pagesize == -1) {
perror("sysconf");
c = p[666]; /* Read; ok */ exit(EXIT_FAILURE);
p[666] = 42; /* Write; ok */
/* Mark the buffer read-only. */
if (mprotect(p, 1024, PROT_READ)) {
perror("Couldn't mprotect");
exit(errno);
} }
c = p[666]; /* Read; ok */ /* Allocate a buffer aligned on a page boundary;
p[666] = 42; /* Write; program dies on SIGSEGV */ 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); exit(EXIT_SUCCESS);
} }
.fi .fi