mirror of https://github.com/mkerrisk/man-pages
249 lines
6.7 KiB
Groff
249 lines
6.7 KiB
Groff
.\" Copyright (C) 2007 Michael Kerrisk <mtk.manpages@gmail.com>
|
|
.\" and Copyright (C) 1995 Michael Shields <shields@tembel.org>.
|
|
.\"
|
|
.\" %%%LICENSE_START(VERBATIM)
|
|
.\" 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.
|
|
.\"
|
|
.\" 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.
|
|
.\"
|
|
.\" Formatted or processed versions of this manual, if unaccompanied by
|
|
.\" the source, must acknowledge the copyright and author of this work.
|
|
.\" %%%LICENSE_END
|
|
.\"
|
|
.\" 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-06-02, mtk: Fairly substantial rewrites and additions, and
|
|
.\" a much improved example program.
|
|
.\"
|
|
.\" FIXME The following protection flags need documenting:
|
|
.\" PROT_SEM
|
|
.\" PROT_GROWSDOWN
|
|
.\" PROT_GROWSUP
|
|
.\" PROT_SAO (PowerPC)
|
|
.\"
|
|
.TH MPROTECT 2 2015-07-23 "Linux" "Linux Programmer's Manual"
|
|
.SH NAME
|
|
mprotect \- set protection on a region of memory
|
|
.SH SYNOPSIS
|
|
.nf
|
|
.B #include <sys/mman.h>
|
|
.sp
|
|
.BI "int mprotect(void *" addr ", size_t " len ", int " prot );
|
|
.fi
|
|
.SH DESCRIPTION
|
|
.BR mprotect ()
|
|
changes protection for the calling process's memory page(s)
|
|
containing any part of the address range in the
|
|
interval [\fIaddr\fP,\ \fIaddr\fP+\fIlen\fP\-1].
|
|
.I addr
|
|
must be aligned to a page boundary.
|
|
|
|
If the calling process tries to access memory in a manner
|
|
that violates the protection, then the kernel generates a
|
|
.B SIGSEGV
|
|
signal for the process.
|
|
.PP
|
|
.I prot
|
|
is either
|
|
.B PROT_NONE
|
|
or a bitwise-or of the other values in the following list:
|
|
.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
|
|
The memory can be modified.
|
|
.TP
|
|
.B PROT_EXEC
|
|
The memory can be executed.
|
|
.SH RETURN VALUE
|
|
On success,
|
|
.BR mprotect ()
|
|
returns zero.
|
|
On error, \-1 is returned, and
|
|
.I errno
|
|
is set appropriately.
|
|
.SH ERRORS
|
|
.TP
|
|
.B EACCES
|
|
The memory cannot be given the specified access.
|
|
This can happen, for example, if you
|
|
.BR mmap (2)
|
|
a file to which you have read-only access, then ask
|
|
.BR mprotect ()
|
|
to mark it
|
|
.BR PROT_WRITE .
|
|
.TP
|
|
.B EINVAL
|
|
\fIaddr\fP is not a valid pointer,
|
|
or not a multiple of the system page size.
|
|
.\" Or: both PROT_GROWSUP and PROT_GROWSDOWN were specified in 'prot'.
|
|
.TP
|
|
.B ENOMEM
|
|
Internal kernel structures could not be allocated.
|
|
.TP
|
|
.B ENOMEM
|
|
Addresses in the range
|
|
.RI [ addr ,
|
|
.IR addr + len \-1]
|
|
are invalid for the address space of the process,
|
|
or specify one or more pages that are not mapped.
|
|
(Before kernel 2.4.19, the error
|
|
.BR EFAULT
|
|
was incorrectly produced for these cases.)
|
|
.TP
|
|
.B ENOMEM
|
|
Changing the protection of a memory region would result in the total number of
|
|
mappings with distinct attributes (e.g., read versus read/write protection)
|
|
exceeding the allowed maximum.
|
|
.\" I.e., the number of VMAs would exceed the 64kB maximum
|
|
(For example, making the protection of a range
|
|
.BR PROT_READ
|
|
in the middle of a region currently protected as
|
|
.BR PROT_READ|PROT_WRITE
|
|
would result in three mappings:
|
|
two read/write mappings at each end and a read-only mapping in the middle.)
|
|
.SH CONFORMING TO
|
|
POSIX.1-2001, POSIX.1-2008, SVr4.
|
|
.\" SVr4 defines an additional error
|
|
.\" code EAGAIN. The SVr4 error conditions don't map neatly onto Linux's.
|
|
POSIX says that the behavior of
|
|
.BR mprotect ()
|
|
is unspecified if it is applied to a region of memory that
|
|
was not obtained via
|
|
.BR mmap (2).
|
|
.SH NOTES
|
|
On Linux it is always permissible to call
|
|
.BR mprotect ()
|
|
on any address in a process's address space (except for the
|
|
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
|
|
depends on processor architecture, kernel version, and process state.
|
|
If
|
|
.B READ_IMPLIES_EXEC
|
|
is set in the process's personality flags (see
|
|
.BR personality (2)),
|
|
specifying
|
|
.B PROT_READ
|
|
will implicitly add
|
|
.BR PROT_EXEC.
|
|
|
|
On some hardware architectures (e.g., i386),
|
|
.B PROT_WRITE
|
|
implies
|
|
.BR PROT_READ .
|
|
|
|
POSIX.1 says that an implementation may permit access
|
|
other than that specified in
|
|
.IR prot ,
|
|
but at a minimum can allow write access only if
|
|
.B PROT_WRITE
|
|
has been set, and must not allow any access if
|
|
.B PROT_NONE
|
|
has been set.
|
|
.SH EXAMPLE
|
|
.\" sigaction.2 refers to this example
|
|
.PP
|
|
The program below allocates four pages of memory, makes the third
|
|
of these pages read-only, and then executes a loop that walks upward
|
|
through the allocated region modifying bytes.
|
|
|
|
An example of what we might see when running the program is the
|
|
following:
|
|
|
|
.in +4n
|
|
.nf
|
|
.RB "$" " ./a.out"
|
|
Start of region: 0x804c000
|
|
Got SIGSEGV at address: 0x804e000
|
|
.fi
|
|
.in
|
|
.SS Program source
|
|
\&
|
|
.nf
|
|
#include <unistd.h>
|
|
#include <signal.h>
|
|
#include <stdio.h>
|
|
#include <malloc.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include <sys/mman.h>
|
|
|
|
#define handle_error(msg) \\
|
|
do { perror(msg); exit(EXIT_FAILURE); } while (0)
|
|
|
|
static 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(int argc, char *argv[])
|
|
{
|
|
char *p;
|
|
int pagesize;
|
|
struct sigaction sa;
|
|
|
|
sa.sa_flags = SA_SIGINFO;
|
|
sigemptyset(&sa.sa_mask);
|
|
sa.sa_sigaction = handler;
|
|
if (sigaction(SIGSEGV, &sa, NULL) == \-1)
|
|
handle_error("sigaction");
|
|
|
|
pagesize = sysconf(_SC_PAGE_SIZE);
|
|
if (pagesize == \-1)
|
|
handle_error("sysconf");
|
|
|
|
/* Allocate a buffer aligned on a page boundary;
|
|
initial protection is PROT_READ | PROT_WRITE */
|
|
|
|
buffer = memalign(pagesize, 4 * pagesize);
|
|
if (buffer == NULL)
|
|
handle_error("memalign");
|
|
|
|
printf("Start of region: 0x%lx\\n", (long) buffer);
|
|
|
|
if (mprotect(buffer + pagesize * 2, pagesize,
|
|
PROT_READ) == \-1)
|
|
handle_error("mprotect");
|
|
|
|
for (p = buffer ; ; )
|
|
*(p++) = \(aqa\(aq;
|
|
|
|
printf("Loop completed\\n"); /* Should never happen */
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
.fi
|
|
.SH SEE ALSO
|
|
.BR mmap (2),
|
|
.BR sysconf (3)
|