2007-04-12 22:42:49 +00:00
|
|
|
.\" -*- nroff -*-
|
2007-09-20 06:52:22 +00:00
|
|
|
.\" Copyright (C) 2007 Michael Kerrisk <mtk.manpages@gmail.com>
|
2007-05-25 19:54:08 +00:00
|
|
|
.\" and Copyright (C) 1995 Michael Shields <shields@tembel.org>.
|
2004-11-03 13:51:07 +00:00
|
|
|
.\"
|
|
|
|
.\" Permission is granted to make and distribute verbatim copies of this
|
|
|
|
.\" manual provided the copyright notice and this permission notice are
|
|
|
|
.\" preserved on all copies.
|
|
|
|
.\"
|
|
|
|
.\" Permission is granted to copy and distribute modified versions of this
|
|
|
|
.\" manual under the conditions for verbatim copying, provided that the
|
|
|
|
.\" entire resulting derived work is distributed under the terms of a
|
|
|
|
.\" permission notice identical to this one.
|
2007-04-12 22:42:49 +00:00
|
|
|
.\"
|
2004-11-03 13:51:07 +00:00
|
|
|
.\" Since the Linux kernel and libraries are constantly changing, this
|
|
|
|
.\" manual page may be incorrect or out-of-date. The author(s) assume no
|
|
|
|
.\" responsibility for errors or omissions, or for damages resulting from
|
|
|
|
.\" the use of the information contained herein. The author(s) may not
|
|
|
|
.\" have taken the same level of care in the production of this manual,
|
|
|
|
.\" which is licensed free of charge, as they might when working
|
|
|
|
.\" professionally.
|
2007-04-12 22:42:49 +00:00
|
|
|
.\"
|
2004-11-03 13:51:07 +00:00
|
|
|
.\" Formatted or processed versions of this manual, if unaccompanied by
|
|
|
|
.\" the source, must acknowledge the copyright and author of this work.
|
|
|
|
.\"
|
|
|
|
.\" Modified 1996-10-22 by Eric S. Raymond <esr@thyrsus.com>
|
|
|
|
.\" Modified 1997-05-31 by Andries Brouwer <aeb@cwi.nl>
|
|
|
|
.\" Modified 2003-08-24 by Andries Brouwer <aeb@cwi.nl>
|
|
|
|
.\" Modified 2004-08-16 by Andi Kleen <ak@muc.de>
|
2007-05-25 19:54:08 +00:00
|
|
|
.\" 2007-06-02, mtk: Fairly substantial rewrites and additions, and
|
|
|
|
.\" a much improved example program.
|
2004-11-03 13:51:07 +00:00
|
|
|
.\"
|
2007-05-25 19:54:08 +00:00
|
|
|
.TH MPROTECT 2 2007-06-02 "Linux" "Linux Programmer's Manual"
|
2004-11-03 13:51:07 +00:00
|
|
|
.SH NAME
|
2007-05-25 19:54:08 +00:00
|
|
|
mprotect \- set protection on a region of memory
|
2004-11-03 13:51:07 +00:00
|
|
|
.SH SYNOPSIS
|
|
|
|
.nf
|
|
|
|
.B #include <sys/mman.h>
|
|
|
|
.sp
|
|
|
|
\fBint mprotect(const void *\fIaddr\fB, size_t \fIlen\fB, int \fIprot\fB);
|
|
|
|
.fi
|
|
|
|
.SH DESCRIPTION
|
2005-10-19 06:54:38 +00:00
|
|
|
.BR mprotect ()
|
2007-05-25 19:54:08 +00:00
|
|
|
changes protection for the calling process's memory page(s)
|
2007-06-21 22:55:04 +00:00
|
|
|
containing any part of the address range in the
|
2007-07-18 20:11:21 +00:00
|
|
|
interval [\fIaddr\fP,\ \fIaddr\fP+\fIlen\fP\-1].
|
2007-05-25 19:54:08 +00:00
|
|
|
.I addr
|
|
|
|
must be aligned to a page boundary.
|
|
|
|
|
|
|
|
If the calling process tries to access memory in a manner
|
2007-06-21 22:55:04 +00:00
|
|
|
that violates the protection, then the kernel generates a
|
2007-05-25 19:54:08 +00:00
|
|
|
.B SIGSEGV
|
|
|
|
signal for the process.
|
2004-11-03 13:51:07 +00:00
|
|
|
.PP
|
|
|
|
.I prot
|
2007-05-25 19:54:08 +00:00
|
|
|
is either
|
|
|
|
.B PROT_NONE
|
|
|
|
or a bitwise-or of the other values in the following list:
|
2004-11-03 13:51:07 +00:00
|
|
|
.TP 1.1i
|
|
|
|
.B PROT_NONE
|
|
|
|
The memory cannot be accessed at all.
|
|
|
|
.TP
|
|
|
|
.B PROT_READ
|
|
|
|
The memory can be read.
|
|
|
|
.TP
|
|
|
|
.B PROT_WRITE
|
2007-05-25 19:54:08 +00:00
|
|
|
The memory can be modified.
|
2004-11-03 13:51:07 +00:00
|
|
|
.TP
|
|
|
|
.B PROT_EXEC
|
2007-07-10 03:57:50 +00:00
|
|
|
The memory can be executed.
|
2006-09-05 08:03:37 +00:00
|
|
|
.\" FIXME
|
2007-06-16 11:43:44 +00:00
|
|
|
.\" Document PROT_GROWSUP and PROT_GROWSDOWN
|
2004-11-03 13:51:07 +00:00
|
|
|
.SH "RETURN VALUE"
|
|
|
|
On success,
|
2005-10-19 06:54:38 +00:00
|
|
|
.BR mprotect ()
|
2007-04-12 22:42:49 +00:00
|
|
|
returns zero.
|
|
|
|
On error, \-1 is returned, and
|
2004-11-03 13:51:07 +00:00
|
|
|
.I errno
|
|
|
|
is set appropriately.
|
|
|
|
.SH ERRORS
|
|
|
|
.TP
|
|
|
|
.B EACCES
|
2007-04-12 22:42:49 +00:00
|
|
|
The memory cannot be given the specified access.
|
|
|
|
This can happen, for example, if you
|
2004-11-03 13:51:07 +00:00
|
|
|
.BR mmap (2)
|
|
|
|
a file to which you have read-only access, then ask
|
2005-10-19 06:54:38 +00:00
|
|
|
.BR mprotect ()
|
2004-11-03 13:51:07 +00:00
|
|
|
to mark it
|
|
|
|
.BR PROT_WRITE .
|
|
|
|
.TP
|
|
|
|
.B EFAULT
|
|
|
|
The memory cannot be accessed.
|
|
|
|
.TP
|
|
|
|
.B EINVAL
|
2007-07-18 20:24:30 +00:00
|
|
|
\fIaddr\fP is not a valid pointer,
|
2007-05-25 19:54:08 +00:00
|
|
|
or not a multiple of the system page size.
|
2007-06-16 11:45:57 +00:00
|
|
|
.\" Or: both PROT_GROWSUP and PROT_GROWSDOWN were specified in 'prot'.
|
2004-11-03 13:51:07 +00:00
|
|
|
.TP
|
|
|
|
.B ENOMEM
|
2007-04-12 22:42:49 +00:00
|
|
|
Internal kernel structures could not be allocated.
|
2006-03-20 00:19:11 +00:00
|
|
|
Or: addresses in the range
|
2005-09-21 15:47:18 +00:00
|
|
|
.RI [ addr ,
|
|
|
|
.IR addr + len ]
|
|
|
|
are invalid for the address space of the process,
|
|
|
|
or specify one or more pages that are not mapped.
|
2007-05-19 04:30:20 +00:00
|
|
|
.SH "CONFORMING TO"
|
|
|
|
SVr4, POSIX.1-2001.
|
|
|
|
.\" SVr4 defines an additional error
|
|
|
|
.\" code EAGAIN. The SVr4 error conditions don't map neatly onto Linux's.
|
2007-06-08 09:56:56 +00:00
|
|
|
POSIX says that the behavior of
|
2007-05-19 04:30:20 +00:00
|
|
|
.BR mprotect ()
|
2007-05-25 19:54:08 +00:00
|
|
|
is unspecified if it is applied to a region of memory that
|
|
|
|
was not obtained via
|
2007-05-19 04:30:20 +00:00
|
|
|
.BR mmap (2).
|
|
|
|
.SH NOTES
|
|
|
|
On Linux it is always legal to call
|
|
|
|
.BR mprotect ()
|
2007-06-11 19:20:30 +00:00
|
|
|
on any address in a process's address space (except for the
|
2007-05-19 04:30:20 +00:00
|
|
|
kernel vsyscall area).
|
|
|
|
In particular it can be used
|
|
|
|
to change existing code mappings to be writable.
|
|
|
|
|
|
|
|
Whether
|
|
|
|
.B PROT_EXEC
|
|
|
|
has any effect different from
|
|
|
|
.B PROT_READ
|
|
|
|
is architecture and kernel version dependent.
|
2007-09-10 04:10:36 +00:00
|
|
|
On some hardware architectures (e.g., x86),
|
2007-09-20 16:26:31 +00:00
|
|
|
.B PROT_WRITE
|
2007-09-10 04:10:36 +00:00
|
|
|
implies
|
|
|
|
.BR PROT_READ .
|
2007-05-25 19:54:08 +00:00
|
|
|
|
|
|
|
POSIX.1-2001 says that an implementation may permit access
|
|
|
|
other than that specified in
|
|
|
|
.IR prot ,
|
|
|
|
but at a minimum can only allow write access if
|
|
|
|
.B PROT_WRITE
|
|
|
|
has been set, and must not allow any access if
|
|
|
|
.B PROT_NONE
|
|
|
|
has been set.
|
2004-11-03 13:51:07 +00:00
|
|
|
.SH EXAMPLE
|
2007-05-27 17:04:53 +00:00
|
|
|
.\" sigaction.2 refers to this example
|
2007-05-25 18:57:30 +00:00
|
|
|
.PP
|
2007-05-25 19:54:08 +00:00
|
|
|
The program below allocates four pages of memory, makes the third
|
2007-05-25 18:57:30 +00:00
|
|
|
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
|
2004-11-03 13:51:07 +00:00
|
|
|
.nf
|
2007-05-25 18:57:30 +00:00
|
|
|
$ ./a.out
|
|
|
|
Start of region: 0x804c000
|
|
|
|
Got SIGSEGV at address: 0x804e000
|
|
|
|
.fi
|
|
|
|
.in
|
|
|
|
.nf
|
|
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <signal.h>
|
2004-11-03 13:51:07 +00:00
|
|
|
#include <stdio.h>
|
2007-05-25 18:57:30 +00:00
|
|
|
#include <malloc.h>
|
2004-11-03 13:51:07 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <sys/mman.h>
|
|
|
|
|
2007-11-19 03:25:26 +00:00
|
|
|
#define handle_error(msg) \\
|
|
|
|
do { perror(msg); exit(EXIT_FAILURE); } while (0)
|
2007-06-02 08:31:25 +00:00
|
|
|
|
2007-05-25 18:57:30 +00:00
|
|
|
char *buffer;
|
|
|
|
|
|
|
|
static void
|
|
|
|
handler(int sig, siginfo_t *si, void *unused)
|
|
|
|
{
|
2007-06-21 22:55:04 +00:00
|
|
|
printf("Got SIGSEGV at address: 0x%lx\\n",
|
2007-06-20 21:39:45 +00:00
|
|
|
(long) si\->si_addr);
|
2007-05-25 18:57:30 +00:00
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2004-11-03 13:51:07 +00:00
|
|
|
|
|
|
|
int
|
2007-05-25 18:57:30 +00:00
|
|
|
main(int argc, char *argv[])
|
2004-11-03 13:51:07 +00:00
|
|
|
{
|
|
|
|
char *p;
|
2007-05-25 18:57:30 +00:00
|
|
|
int pagesize;
|
|
|
|
struct sigaction sa;
|
|
|
|
|
|
|
|
sa.sa_flags = SA_SIGINFO;
|
|
|
|
sigemptyset(&sa.sa_mask);
|
|
|
|
sa.sa_sigaction = handler;
|
2007-06-20 21:39:45 +00:00
|
|
|
if (sigaction(SIGSEGV, &sa, NULL) == \-1)
|
2007-11-19 03:25:26 +00:00
|
|
|
handle_error("sigaction");
|
2004-11-03 13:51:07 +00:00
|
|
|
|
2007-05-25 18:57:30 +00:00
|
|
|
pagesize = sysconf(_SC_PAGE_SIZE);
|
2007-06-20 21:39:45 +00:00
|
|
|
if (pagesize == \-1)
|
2007-11-19 03:25:26 +00:00
|
|
|
handle_error("sysconf");
|
2004-11-03 13:51:07 +00:00
|
|
|
|
2007-06-21 22:55:04 +00:00
|
|
|
/* Allocate a buffer aligned on a page boundary;
|
2007-05-25 18:57:30 +00:00
|
|
|
initial protection is PROT_READ | PROT_WRITE */
|
|
|
|
|
|
|
|
buffer = memalign(pagesize, 4 * pagesize);
|
2007-06-02 08:31:25 +00:00
|
|
|
if (buffer == NULL)
|
2007-11-19 03:25:26 +00:00
|
|
|
handle_error("memalign");
|
2004-11-03 13:51:07 +00:00
|
|
|
|
2007-05-25 18:57:30 +00:00
|
|
|
printf("Start of region: 0x%lx\\n", (long) buffer);
|
2004-11-03 13:51:07 +00:00
|
|
|
|
2007-06-21 22:55:04 +00:00
|
|
|
if (mprotect(buffer + pagesize * 2, pagesize,
|
2007-06-20 21:39:45 +00:00
|
|
|
PROT_NONE) == \-1)
|
2007-11-19 03:25:26 +00:00
|
|
|
handle_error("mprotect");
|
2004-11-03 13:51:07 +00:00
|
|
|
|
2007-05-25 18:57:30 +00:00
|
|
|
for (p = buffer ; ; )
|
|
|
|
*(p++) = 'a';
|
2004-11-03 13:51:07 +00:00
|
|
|
|
2007-05-25 18:57:30 +00:00
|
|
|
printf("Loop completed\\n"); /* Should never happen */
|
2007-05-14 21:06:00 +00:00
|
|
|
exit(EXIT_SUCCESS);
|
2004-11-03 13:51:07 +00:00
|
|
|
}
|
|
|
|
.fi
|
|
|
|
.SH "SEE ALSO"
|
2007-05-25 19:54:08 +00:00
|
|
|
.BR mmap (2),
|
|
|
|
.BR sysconf (3)
|