Blame man2/mprotect.2

Packit 7cfc04
.\" Copyright (C) 2007 Michael Kerrisk <mtk.manpages@gmail.com>
Packit 7cfc04
.\" and Copyright (C) 1995 Michael Shields <shields@tembel.org>.
Packit 7cfc04
.\"
Packit 7cfc04
.\" %%%LICENSE_START(VERBATIM)
Packit 7cfc04
.\" Permission is granted to make and distribute verbatim copies of this
Packit 7cfc04
.\" manual provided the copyright notice and this permission notice are
Packit 7cfc04
.\" preserved on all copies.
Packit 7cfc04
.\"
Packit 7cfc04
.\" Permission is granted to copy and distribute modified versions of this
Packit 7cfc04
.\" manual under the conditions for verbatim copying, provided that the
Packit 7cfc04
.\" entire resulting derived work is distributed under the terms of a
Packit 7cfc04
.\" permission notice identical to this one.
Packit 7cfc04
.\"
Packit 7cfc04
.\" Since the Linux kernel and libraries are constantly changing, this
Packit 7cfc04
.\" manual page may be incorrect or out-of-date.  The author(s) assume no
Packit 7cfc04
.\" responsibility for errors or omissions, or for damages resulting from
Packit 7cfc04
.\" the use of the information contained herein.  The author(s) may not
Packit 7cfc04
.\" have taken the same level of care in the production of this manual,
Packit 7cfc04
.\" which is licensed free of charge, as they might when working
Packit 7cfc04
.\" professionally.
Packit 7cfc04
.\"
Packit 7cfc04
.\" Formatted or processed versions of this manual, if unaccompanied by
Packit 7cfc04
.\" the source, must acknowledge the copyright and author of this work.
Packit 7cfc04
.\" %%%LICENSE_END
Packit 7cfc04
.\"
Packit 7cfc04
.\" Modified 1996-10-22 by Eric S. Raymond <esr@thyrsus.com>
Packit 7cfc04
.\" Modified 1997-05-31 by Andries Brouwer <aeb@cwi.nl>
Packit 7cfc04
.\" Modified 2003-08-24 by Andries Brouwer <aeb@cwi.nl>
Packit 7cfc04
.\" Modified 2004-08-16 by Andi Kleen <ak@muc.de>
Packit 7cfc04
.\" 2007-06-02, mtk: Fairly substantial rewrites and additions, and
Packit 7cfc04
.\" a much improved example program.
Packit 7cfc04
.\"
Packit 7cfc04
.TH MPROTECT 2 2018-02-02 "Linux" "Linux Programmer's Manual"
Packit 7cfc04
.SH NAME
Packit 7cfc04
mprotect, pkey_mprotect \- set protection on a region of memory
Packit 7cfc04
.SH SYNOPSIS
Packit 7cfc04
.nf
Packit 7cfc04
.B #include <sys/mman.h>
Packit 7cfc04
.PP
Packit 7cfc04
.BI "int mprotect(void *" addr ", size_t " len ", int " prot );
Packit 7cfc04
.BI "int pkey_mprotect(void *" addr ", size_t " len ", int " prot ", int " pkey ");
Packit 7cfc04
.fi
Packit 7cfc04
.SH DESCRIPTION
Packit 7cfc04
.BR mprotect ()
Packit 7cfc04
changes the access protections for the calling process's memory pages
Packit 7cfc04
containing any part of the address range in the
Packit 7cfc04
interval [\fIaddr\fP,\ \fIaddr\fP+\fIlen\fP\-1].
Packit 7cfc04
.I addr
Packit 7cfc04
must be aligned to a page boundary.
Packit 7cfc04
.PP
Packit 7cfc04
If the calling process tries to access memory in a manner
Packit 7cfc04
that violates the protections, then the kernel generates a
Packit 7cfc04
.B SIGSEGV
Packit 7cfc04
signal for the process.
Packit 7cfc04
.PP
Packit 7cfc04
.I prot
Packit 7cfc04
is a combination of the following access flags:
Packit 7cfc04
.B PROT_NONE
Packit 7cfc04
or a bitwise-or of the other values in the following list:
Packit 7cfc04
.TP 1.1i
Packit 7cfc04
.B PROT_NONE
Packit 7cfc04
The memory cannot be accessed at all.
Packit 7cfc04
.TP
Packit 7cfc04
.B PROT_READ
Packit 7cfc04
The memory can be read.
Packit 7cfc04
.TP
Packit 7cfc04
.B PROT_WRITE
Packit 7cfc04
The memory can be modified.
Packit 7cfc04
.TP
Packit 7cfc04
.B PROT_EXEC
Packit 7cfc04
The memory can be executed.
Packit 7cfc04
.TP
Packit 7cfc04
.BR PROT_SEM " (since Linux 2.5.7)"
Packit 7cfc04
The memory can be used for atomic operations.
Packit 7cfc04
This flag was introduced as part of the
Packit 7cfc04
.BR futex (2)
Packit 7cfc04
implementation (in order to guarantee the ability to perform atomic
Packit 7cfc04
operations required by commands such as
Packit 7cfc04
.BR FUTEX_WAIT ),
Packit 7cfc04
but is not currently used in on any architecture.
Packit 7cfc04
.TP
Packit 7cfc04
.BR PROT_SAO " (since Linux 2.6.26)"
Packit 7cfc04
.\" commit aba46c5027cb59d98052231b36efcbbde9c77a1d
Packit 7cfc04
.\" commit ef3d3246a0d06be622867d21af25f997aeeb105f
Packit 7cfc04
The memory should have strong access ordering.
Packit 7cfc04
This feature is specific to
Packit 7cfc04
the PowerPC architecture
Packit 7cfc04
(version 2.06 of the architecture specification adds the SAO CPU feature,
Packit 7cfc04
and it is available on POWER 7 or PowerPC A2, for example).
Packit 7cfc04
.PP
Packit 7cfc04
Additionally (since Linux 2.6.0),
Packit 7cfc04
.I prot
Packit 7cfc04
can have one of the following flags set:
Packit 7cfc04
.TP 1.1i
Packit 7cfc04
.\" mm/mmap.c:
Packit 7cfc04
.\"	vm_flags |= calc_vm_prot_bits(prot, pkey) | calc_vm_flag_bits(flags) |
Packit 7cfc04
.\"			mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
Packit 7cfc04
.\" And calc_vm_flag_bits converts only GROWSDOWN/DENYWRITE/LOCKED.
Packit 7cfc04
.B PROT_GROWSUP
Packit 7cfc04
Apply the protection mode up to the end of a mapping
Packit 7cfc04
that grows upwards.
Packit 7cfc04
(Such mappings are created for the stack area on
Packit 7cfc04
architectures\(emfor example, HP-PARISC\(emthat
Packit 7cfc04
have an upwardly growing stack.)
Packit 7cfc04
.\" The VMA is one that was marked with VM_GROWSUP by the kernel
Packit 7cfc04
.\" when the stack was created. Note that (unlike VM_GROWSDOWN),
Packit 7cfc04
.\" there is no mmap() flag (analogous to MAP_GROWSDOWN) for
Packit 7cfc04
.\" creating a VMA that is marked VM_GROWSUP.
Packit 7cfc04
.TP
Packit 7cfc04
.B PROT_GROWSDOWN
Packit 7cfc04
Apply the protection mode down to the beginning of a mapping
Packit 7cfc04
that grows downward
Packit 7cfc04
(which should be a stack segment or a segment mapped with the
Packit 7cfc04
.B MAP_GROWSDOWN
Packit 7cfc04
flag set).
Packit 7cfc04
.PP
Packit 7cfc04
Like
Packit 7cfc04
.BR mprotect (),
Packit 7cfc04
.BR pkey_mprotect ()
Packit 7cfc04
changes the protection on the pages specified by
Packit 7cfc04
.IR addr
Packit 7cfc04
and
Packit 7cfc04
.IR len .
Packit 7cfc04
The
Packit 7cfc04
.I pkey
Packit 7cfc04
argument specifies the protection key (see
Packit 7cfc04
.BR pkeys (7))
Packit 7cfc04
to assign to the memory.
Packit 7cfc04
The protection key must be allocated with
Packit 7cfc04
.BR pkey_alloc (2)
Packit 7cfc04
before it is passed to
Packit 7cfc04
.BR pkey_mprotect ().
Packit 7cfc04
For an example of the use of this system call, see
Packit 7cfc04
.BR pkeys (7).
Packit 7cfc04
.SH RETURN VALUE
Packit 7cfc04
On success,
Packit 7cfc04
.BR mprotect ()
Packit 7cfc04
and
Packit 7cfc04
.BR pkey_mprotect ()
Packit 7cfc04
return zero.
Packit 7cfc04
On error, these system calls return \-1, and
Packit 7cfc04
.I errno
Packit 7cfc04
is set appropriately.
Packit 7cfc04
.SH ERRORS
Packit 7cfc04
.TP
Packit 7cfc04
.B EACCES
Packit 7cfc04
The memory cannot be given the specified access.
Packit 7cfc04
This can happen, for example, if you
Packit 7cfc04
.BR mmap (2)
Packit 7cfc04
a file to which you have read-only access, then ask
Packit 7cfc04
.BR mprotect ()
Packit 7cfc04
to mark it
Packit 7cfc04
.BR PROT_WRITE .
Packit 7cfc04
.TP
Packit 7cfc04
.B EINVAL
Packit 7cfc04
\fIaddr\fP is not a valid pointer,
Packit 7cfc04
or not a multiple of the system page size.
Packit 7cfc04
.TP
Packit 7cfc04
.BR EINVAL
Packit 7cfc04
.RB ( pkey_mprotect ())
Packit 7cfc04
\fIpkey\fP has not been allocated with
Packit 7cfc04
.BR pkey_alloc (2)
Packit 7cfc04
.TP
Packit 7cfc04
.BR EINVAL
Packit 7cfc04
Both
Packit 7cfc04
.BR PROT_GROWSUP
Packit 7cfc04
and
Packit 7cfc04
.BR PROT_GROWSDOWN
Packit 7cfc04
were specified in
Packit 7cfc04
.IR prot .
Packit 7cfc04
.TP
Packit 7cfc04
.BR EINVAL
Packit 7cfc04
Invalid flags specified in
Packit 7cfc04
.IR prot .
Packit 7cfc04
.TP
Packit 7cfc04
.BR EINVAL
Packit 7cfc04
(PowerPC architecture)
Packit 7cfc04
.B PROT_SAO
Packit 7cfc04
was specified in
Packit 7cfc04
.IR prot ,
Packit 7cfc04
but SAO hardware feature is not available.
Packit 7cfc04
.TP
Packit 7cfc04
.B ENOMEM
Packit 7cfc04
Internal kernel structures could not be allocated.
Packit 7cfc04
.TP
Packit 7cfc04
.B ENOMEM
Packit 7cfc04
Addresses in the range
Packit 7cfc04
.RI [ addr ,
Packit 7cfc04
.IR addr + len \-1]
Packit 7cfc04
are invalid for the address space of the process,
Packit 7cfc04
or specify one or more pages that are not mapped.
Packit 7cfc04
(Before kernel 2.4.19, the error
Packit 7cfc04
.BR EFAULT
Packit 7cfc04
was incorrectly produced for these cases.)
Packit 7cfc04
.TP
Packit 7cfc04
.B ENOMEM
Packit 7cfc04
Changing the protection of a memory region would result in the total number of
Packit 7cfc04
mappings with distinct attributes (e.g., read versus read/write protection)
Packit 7cfc04
exceeding the allowed maximum.
Packit 7cfc04
.\" I.e., the number of VMAs would exceed the 64 kB maximum
Packit 7cfc04
(For example, making the protection of a range
Packit 7cfc04
.BR PROT_READ
Packit 7cfc04
in the middle of a region currently protected as
Packit 7cfc04
.BR PROT_READ|PROT_WRITE
Packit 7cfc04
would result in three mappings:
Packit 7cfc04
two read/write mappings at each end and a read-only mapping in the middle.)
Packit 7cfc04
.SH VERSIONS
Packit 7cfc04
.BR pkey_mprotect ()
Packit 7cfc04
first appeared in Linux 4.9;
Packit 7cfc04
library support was added in glibc 2.27.
Packit 7cfc04
.SH CONFORMING TO
Packit 7cfc04
.BR mprotect ():
Packit 7cfc04
POSIX.1-2001, POSIX.1-2008, SVr4.
Packit 7cfc04
.\" SVr4 defines an additional error
Packit 7cfc04
.\" code EAGAIN. The SVr4 error conditions don't map neatly onto Linux's.
Packit 7cfc04
POSIX says that the behavior of
Packit 7cfc04
.BR mprotect ()
Packit 7cfc04
is unspecified if it is applied to a region of memory that
Packit 7cfc04
was not obtained via
Packit 7cfc04
.BR mmap (2).
Packit 7cfc04
.PP
Packit 7cfc04
.BR pkey_mprotect ()
Packit 7cfc04
is a nonportable Linux extension.
Packit 7cfc04
.SH NOTES
Packit 7cfc04
On Linux, it is always permissible to call
Packit 7cfc04
.BR mprotect ()
Packit 7cfc04
on any address in a process's address space (except for the
Packit 7cfc04
kernel vsyscall area).
Packit 7cfc04
In particular, it can be used
Packit 7cfc04
to change existing code mappings to be writable.
Packit 7cfc04
.PP
Packit 7cfc04
Whether
Packit 7cfc04
.B PROT_EXEC
Packit 7cfc04
has any effect different from
Packit 7cfc04
.B PROT_READ
Packit 7cfc04
depends on processor architecture, kernel version, and process state.
Packit 7cfc04
If
Packit 7cfc04
.B READ_IMPLIES_EXEC
Packit 7cfc04
is set in the process's personality flags (see
Packit 7cfc04
.BR personality (2)),
Packit 7cfc04
specifying
Packit 7cfc04
.B PROT_READ
Packit 7cfc04
will implicitly add
Packit 7cfc04
.BR PROT_EXEC.
Packit 7cfc04
.PP
Packit 7cfc04
On some hardware architectures (e.g., i386),
Packit 7cfc04
.B PROT_WRITE
Packit 7cfc04
implies
Packit 7cfc04
.BR PROT_READ .
Packit 7cfc04
.PP
Packit 7cfc04
POSIX.1 says that an implementation may permit access
Packit 7cfc04
other than that specified in
Packit 7cfc04
.IR prot ,
Packit 7cfc04
but at a minimum can allow write access only if
Packit 7cfc04
.B PROT_WRITE
Packit 7cfc04
has been set, and must not allow any access if
Packit 7cfc04
.B PROT_NONE
Packit 7cfc04
has been set.
Packit 7cfc04
.PP
Packit 7cfc04
Applications should be careful when mixing use of
Packit 7cfc04
.BR mprotect ()
Packit 7cfc04
and
Packit 7cfc04
.BR pkey_mprotect ().
Packit 7cfc04
On x86, when
Packit 7cfc04
.BR mprotect ()
Packit 7cfc04
is used with
Packit 7cfc04
.IR prot
Packit 7cfc04
set to
Packit 7cfc04
.B PROT_EXEC
Packit 7cfc04
a pkey is may be allocated and set on the memory implicitly
Packit 7cfc04
by the kernel, but only when the pkey was 0 previously.
Packit 7cfc04
.PP
Packit 7cfc04
On systems that do not support protection keys in hardware,
Packit 7cfc04
.BR pkey_mprotect ()
Packit 7cfc04
may still be used, but
Packit 7cfc04
.IR pkey
Packit 7cfc04
must be set to 0.
Packit 7cfc04
When called this way, the operation of
Packit 7cfc04
.BR pkey_mprotect ()
Packit 7cfc04
is equivalent to
Packit 7cfc04
.BR mprotect ().
Packit 7cfc04
.SH EXAMPLE
Packit 7cfc04
.\" sigaction.2 refers to this example
Packit 7cfc04
.PP
Packit 7cfc04
The program below demonstrates the use of
Packit 7cfc04
.BR mprotect ().
Packit 7cfc04
The program allocates four pages of memory, makes the third
Packit 7cfc04
of these pages read-only, and then executes a loop that walks upward
Packit 7cfc04
through the allocated region modifying bytes.
Packit 7cfc04
.PP
Packit 7cfc04
An example of what we might see when running the program is the
Packit 7cfc04
following:
Packit 7cfc04
.PP
Packit 7cfc04
.in +4n
Packit 7cfc04
.EX
Packit 7cfc04
.RB "$" " ./a.out"
Packit 7cfc04
Start of region:        0x804c000
Packit 7cfc04
Got SIGSEGV at address: 0x804e000
Packit 7cfc04
.EE
Packit 7cfc04
.in
Packit 7cfc04
.SS Program source
Packit 7cfc04
\&
Packit 7cfc04
.EX
Packit 7cfc04
#include <unistd.h>
Packit 7cfc04
#include <signal.h>
Packit 7cfc04
#include <stdio.h>
Packit 7cfc04
#include <malloc.h>
Packit 7cfc04
#include <stdlib.h>
Packit 7cfc04
#include <errno.h>
Packit 7cfc04
#include <sys/mman.h>
Packit 7cfc04
Packit 7cfc04
#define handle_error(msg) \\
Packit 7cfc04
    do { perror(msg); exit(EXIT_FAILURE); } while (0)
Packit 7cfc04
Packit 7cfc04
static char *buffer;
Packit 7cfc04
Packit 7cfc04
static void
Packit 7cfc04
handler(int sig, siginfo_t *si, void *unused)
Packit 7cfc04
{
Packit 7cfc04
    /* Note: calling printf() from a signal handler is not safe
Packit 7cfc04
       (and should not be done in production programs), since
Packit 7cfc04
       printf() is not async\-signal\-safe; see signal-safety(7).
Packit 7cfc04
       Nevertheless, we use printf() here as a simple way of
Packit 7cfc04
       showing that the handler was called. */
Packit 7cfc04
Packit 7cfc04
    printf("Got SIGSEGV at address: 0x%lx\\n",
Packit 7cfc04
            (long) si\->si_addr);
Packit 7cfc04
    exit(EXIT_FAILURE);
Packit 7cfc04
}
Packit 7cfc04
Packit 7cfc04
int
Packit 7cfc04
main(int argc, char *argv[])
Packit 7cfc04
{
Packit 7cfc04
    char *p;
Packit 7cfc04
    int pagesize;
Packit 7cfc04
    struct sigaction sa;
Packit 7cfc04
Packit 7cfc04
    sa.sa_flags = SA_SIGINFO;
Packit 7cfc04
    sigemptyset(&sa.sa_mask);
Packit 7cfc04
    sa.sa_sigaction = handler;
Packit 7cfc04
    if (sigaction(SIGSEGV, &sa, NULL) == \-1)
Packit 7cfc04
        handle_error("sigaction");
Packit 7cfc04
Packit 7cfc04
    pagesize = sysconf(_SC_PAGE_SIZE);
Packit 7cfc04
    if (pagesize == \-1)
Packit 7cfc04
        handle_error("sysconf");
Packit 7cfc04
Packit 7cfc04
    /* Allocate a buffer aligned on a page boundary;
Packit 7cfc04
       initial protection is PROT_READ | PROT_WRITE */
Packit 7cfc04
Packit 7cfc04
    buffer = memalign(pagesize, 4 * pagesize);
Packit 7cfc04
    if (buffer == NULL)
Packit 7cfc04
        handle_error("memalign");
Packit 7cfc04
Packit 7cfc04
    printf("Start of region:        0x%lx\\n", (long) buffer);
Packit 7cfc04
Packit 7cfc04
    if (mprotect(buffer + pagesize * 2, pagesize,
Packit 7cfc04
                PROT_READ) == \-1)
Packit 7cfc04
        handle_error("mprotect");
Packit 7cfc04
Packit 7cfc04
    for (p = buffer ; ; )
Packit 7cfc04
        *(p++) = \(aqa\(aq;
Packit 7cfc04
Packit 7cfc04
    printf("Loop completed\\n");     /* Should never happen */
Packit 7cfc04
    exit(EXIT_SUCCESS);
Packit 7cfc04
}
Packit 7cfc04
.EE
Packit 7cfc04
.SH SEE ALSO
Packit 7cfc04
.BR mmap (2),
Packit 7cfc04
.BR sysconf (3),
Packit 7cfc04
.BR pkeys (7)
Packit 7cfc04
.SH COLOPHON
Packit 7cfc04
This page is part of release 4.15 of the Linux
Packit 7cfc04
.I man-pages
Packit 7cfc04
project.
Packit 7cfc04
A description of the project,
Packit 7cfc04
information about reporting bugs,
Packit 7cfc04
and the latest version of this page,
Packit 7cfc04
can be found at
Packit 7cfc04
\%https://www.kernel.org/doc/man\-pages/.