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
|
|
|
.\"
|
2011-09-08 16:49:44 +00:00
|
|
|
.TH MPROTECT 2 2011-09-08 "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
|
2008-05-26 11:12:19 +00:00
|
|
|
.BI "int mprotect(const void *" addr ", size_t " len ", int " prot );
|
2004-11-03 13:51:07 +00:00
|
|
|
.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 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.
|
2008-08-06 19:41:51 +00:00
|
|
|
.TP
|
|
|
|
.B ENOMEM
|
|
|
|
Addresses in the range
|
2005-09-21 15:47:18 +00:00
|
|
|
.RI [ addr ,
|
2011-09-08 14:58:27 +00:00
|
|
|
.IR addr + len \-1]
|
2005-09-21 15:47:18 +00:00
|
|
|
are invalid for the address space of the process,
|
|
|
|
or specify one or more pages that are not mapped.
|
2008-08-06 19:41:51 +00:00
|
|
|
(Before kernel 2.4.19, the error
|
|
|
|
.BR EFAULT
|
|
|
|
was incorrectly produced for these cases.)
|
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
|
2008-03-10 10:04:03 +00:00
|
|
|
On Linux it is always permissible to call
|
2007-05-19 04:30:20 +00:00
|
|
|
.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
|
2007-12-26 11:17:23 +00:00
|
|
|
is architecture- and kernel version-dependent.
|
2007-12-24 17:31:35 +00:00
|
|
|
On some hardware architectures (e.g., i386),
|
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
|
Changes.old, clone.2, execve.2, fcntl.2, futex.2, getitimer.2, getpriority.2, mmap.2, mount.2, mprotect.2, sched_setscheduler.2, select_tut.2, setuid.2, sigaltstack.2, vfork.2, div.3, fenv.3, fmod.3, memchr.3, pthread_attr_setstackaddr.3, pthread_attr_setstacksize.3, pthread_getattr_np.3, queue.3, scanf.3, trunc.3, st.4, proc.5, services.5, utmp.5, bootparam.7, capabilities.7, feature_test_macros.7, futex.7, glob.7, man.7, netlink.7, unicode.7: Switch to American usage: "-wards" ==> "-ward"
American English uses "afterward" in preference to "afterwards",
and so on
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
2010-09-26 05:34:47 +00:00
|
|
|
of these pages read-only, and then executes a loop that walks upward
|
2007-05-25 18:57:30 +00:00
|
|
|
through the allocated region modifying bytes.
|
|
|
|
|
|
|
|
An example of what we might see when running the program is the
|
|
|
|
following:
|
|
|
|
|
2007-12-19 06:57:44 +00:00
|
|
|
.in +4n
|
2004-11-03 13:51:07 +00:00
|
|
|
.nf
|
eventfd.2, execve.2, getdents.2, ioprio_set.2, mprotect.2, signalfd.2, timerfd_create.2, wait.2, backtrace.3, clock_getcpuclockid.3, end.3, fmemopen.3, fopencookie.3, frexp.3, getdate.3, getgrouplist.3, getprotoent_r.3, getservent_r.3, gnu_get_libc_version.3, inet.3, inet_pton.3, makecontext.3, malloc.3, matherr.3, offsetof.3, pthread_attr_init.3, pthread_create.3, pthread_getattr_np.3, sem_wait.3, strftime.3, strtok.3, strtol.3, core.5, proc.5, cpuset.7, mq_overview.7: Global fix: Format user input in shell sessions in boldface
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
2008-10-28 15:37:22 +00:00
|
|
|
.RB "$" " ./a.out"
|
2007-05-25 18:57:30 +00:00
|
|
|
Start of region: 0x804c000
|
|
|
|
Got SIGSEGV at address: 0x804e000
|
|
|
|
.fi
|
2008-11-04 14:03:49 +00:00
|
|
|
.in
|
eventfd.2, getdents.2, mprotect.2, signalfd.2, timerfd_create.2, wait.2, backtrace.3, clock_getcpuclockid.3, end.3, fmemopen.3, fopencookie.3, getdate.3, getgrouplist.3, getprotoent_r.3, getservent_r.3, gnu_get_libc_version.3, inet.3, inet_pton.3, makecontext.3, matherr.3, offsetof.3, pthread_attr_init.3, pthread_create.3, pthread_getattr_np.3, sem_wait.3, strtol.3, core.5: global fix: Add ".SS Program source" to EXAMPLE
Add ".SS Program source" to clearly distinguish shell session and
descriptive text from actual program code.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
2008-10-28 15:51:05 +00:00
|
|
|
.SS Program source
|
eventfd.2, getdents.2, mprotect.2, signalfd.2, timerfd_create.2, wait.2, backtrace.3, clock_getcpuclockid.3, end.3, fmemopen.3, fopencookie.3, frexp.3, getaddrinfo.3, getdate.3, getgrouplist.3, getprotoent_r.3, getservent_r.3, gnu_get_libc_version.3, inet.3, inet_pton.3, makecontext.3, matherr.3, offsetof.3, pthread_attr_init.3, pthread_create.3, pthread_getattr_np.3, sem_wait.3, strftime.3, strtok.3, strtol.3, core.5: srcfix
s/\.R " "/\\\&/ as a way of getting a blank line after a .SS heading.
(Suggested by Sam Varshavchik <mrsam@courier-mta.com>)
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
2008-11-05 01:42:45 +00:00
|
|
|
\&
|
2007-05-25 18:57:30 +00:00
|
|
|
.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,
|
2011-09-08 15:27:59 +00:00
|
|
|
PROT_READ) == \-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 ; ; )
|
2008-06-09 15:49:35 +00:00
|
|
|
*(p++) = \(aqa\(aq;
|
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)
|