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
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 <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/mman.h>
#include <limits.h> /* 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