mirror of https://github.com/mkerrisk/man-pages
A much improved eample program.
This commit is contained in:
parent
af5267b2f4
commit
f20d7d8ea3
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue