summaryrefslogtreecommitdiffstats
path: root/man2/mprotect.2
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 19:40:15 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 19:40:15 +0000
commit399644e47874bff147afb19c89228901ac39340e (patch)
tree1c4c0b733f4c16b5783b41bebb19194a9ef62ad1 /man2/mprotect.2
parentInitial commit. (diff)
downloadmanpages-upstream/6.05.01.tar.xz
manpages-upstream/6.05.01.zip
Adding upstream version 6.05.01.upstream/6.05.01
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--man2/mprotect.2363
1 files changed, 363 insertions, 0 deletions
diff --git a/man2/mprotect.2 b/man2/mprotect.2
new file mode 100644
index 0000000..22aa42b
--- /dev/null
+++ b/man2/mprotect.2
@@ -0,0 +1,363 @@
+.\" Copyright (C) 2007 Michael Kerrisk <mtk.manpages@gmail.com>
+.\" and Copyright (C) 1995 Michael Shields <shields@tembel.org>.
+.\"
+.\" SPDX-License-Identifier: Linux-man-pages-copyleft
+.\"
+.\" 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.
+.\"
+.TH mprotect 2 2023-05-03 "Linux man-pages 6.05.01"
+.SH NAME
+mprotect, pkey_mprotect \- set protection on a region of memory
+.SH LIBRARY
+Standard C library
+.RI ( libc ", " \-lc )
+.SH SYNOPSIS
+.nf
+.B #include <sys/mman.h>
+.PP
+.BI "int mprotect(void " addr [. len "], size_t " len ", int " prot );
+.PP
+.BR "#define _GNU_SOURCE" " /* See feature_test_macros(7) */"
+.B #include <sys/mman.h>
+.PP
+.BI "int pkey_mprotect(void " addr [. len "], size_t " len ", int " prot ", int " pkey ");"
+.fi
+.SH DESCRIPTION
+.BR mprotect ()
+changes the access protections for the calling process's memory pages
+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.
+.PP
+If the calling process tries to access memory in a manner
+that violates the protections, then the kernel generates a
+.B SIGSEGV
+signal for the process.
+.PP
+.I prot
+is a combination of the following access flags:
+.B PROT_NONE
+or a bitwise OR of the other values in the following list:
+.TP
+.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.
+.TP
+.BR PROT_SEM " (since Linux 2.5.7)"
+The memory can be used for atomic operations.
+This flag was introduced as part of the
+.BR futex (2)
+implementation (in order to guarantee the ability to perform atomic
+operations required by commands such as
+.BR FUTEX_WAIT ),
+but is not currently used in on any architecture.
+.TP
+.BR PROT_SAO " (since Linux 2.6.26)"
+.\" commit aba46c5027cb59d98052231b36efcbbde9c77a1d
+.\" commit ef3d3246a0d06be622867d21af25f997aeeb105f
+The memory should have strong access ordering.
+This feature is specific to
+the PowerPC architecture
+(version 2.06 of the architecture specification adds the SAO CPU feature,
+and it is available on POWER 7 or PowerPC A2, for example).
+.PP
+Additionally (since Linux 2.6.0),
+.I prot
+can have one of the following flags set:
+.TP
+.\" mm/mmap.c:
+.\" vm_flags |= calc_vm_prot_bits(prot, pkey) | calc_vm_flag_bits(flags) |
+.\" mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
+.\" And calc_vm_flag_bits converts only GROWSDOWN/DENYWRITE/LOCKED.
+.B PROT_GROWSUP
+Apply the protection mode up to the end of a mapping
+that grows upwards.
+(Such mappings are created for the stack area on
+architectures\[em]for example, HP-PARISC\[em]that
+have an upwardly growing stack.)
+.\" The VMA is one that was marked with VM_GROWSUP by the kernel
+.\" when the stack was created. Note that (unlike VM_GROWSDOWN),
+.\" there is no mmap() flag (analogous to MAP_GROWSDOWN) for
+.\" creating a VMA that is marked VM_GROWSUP.
+.TP
+.B PROT_GROWSDOWN
+Apply the protection mode down to the beginning of a mapping
+that grows downward
+(which should be a stack segment or a segment mapped with the
+.B MAP_GROWSDOWN
+flag set).
+.PP
+Like
+.BR mprotect (),
+.BR pkey_mprotect ()
+changes the protection on the pages specified by
+.I addr
+and
+.IR len .
+The
+.I pkey
+argument specifies the protection key (see
+.BR pkeys (7))
+to assign to the memory.
+The protection key must be allocated with
+.BR pkey_alloc (2)
+before it is passed to
+.BR pkey_mprotect ().
+For an example of the use of this system call, see
+.BR pkeys (7).
+.SH RETURN VALUE
+On success,
+.BR mprotect ()
+and
+.BR pkey_mprotect ()
+return zero.
+On error, these system calls return \-1, and
+.I errno
+is set to indicate the error.
+.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.
+.TP
+.B EINVAL
+.RB ( pkey_mprotect ())
+\fIpkey\fP has not been allocated with
+.BR pkey_alloc (2)
+.TP
+.B EINVAL
+Both
+.B PROT_GROWSUP
+and
+.B PROT_GROWSDOWN
+were specified in
+.IR prot .
+.TP
+.B EINVAL
+Invalid flags specified in
+.IR prot .
+.TP
+.B EINVAL
+(PowerPC architecture)
+.B PROT_SAO
+was specified in
+.IR prot ,
+but SAO hardware feature is not available.
+.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 Linux 2.4.19, the error
+.B 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 64 kB maximum
+(For example, making the protection of a range
+.B PROT_READ
+in the middle of a region currently protected as
+.B 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 VERSIONS
+.\" 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).
+.PP
+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.
+.PP
+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 .
+.PP
+On some hardware architectures (e.g., i386),
+.B PROT_WRITE
+implies
+.BR PROT_READ .
+.PP
+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.
+.PP
+Applications should be careful when mixing use of
+.BR mprotect ()
+and
+.BR pkey_mprotect ().
+On x86, when
+.BR mprotect ()
+is used with
+.I prot
+set to
+.B PROT_EXEC
+a pkey may be allocated and set on the memory implicitly
+by the kernel, but only when the pkey was 0 previously.
+.PP
+On systems that do not support protection keys in hardware,
+.BR pkey_mprotect ()
+may still be used, but
+.I pkey
+must be set to \-1.
+When called this way, the operation of
+.BR pkey_mprotect ()
+is equivalent to
+.BR mprotect ().
+.SH STANDARDS
+.TP
+.BR mprotect ()
+POSIX.1-2008.
+.TP
+.BR pkey_mprotect ()
+Linux.
+.SH HISTORY
+.TP
+.BR mprotect ()
+POSIX.1-2001, SVr4.
+.TP
+.BR pkey_mprotect ()
+Linux 4.9,
+glibc 2.27.
+.SH NOTES
+.SH EXAMPLES
+.\" sigaction.2 refers to this example
+The program below demonstrates the use of
+.BR mprotect ().
+The program 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.
+.PP
+An example of what we might see when running the program is the
+following:
+.PP
+.in +4n
+.EX
+.RB "$" " ./a.out"
+Start of region: 0x804c000
+Got SIGSEGV at address: 0x804e000
+.EE
+.in
+.SS Program source
+\&
+.\" SRC BEGIN (mprotect.c)
+.EX
+#include <malloc.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <unistd.h>
+\&
+#define handle_error(msg) \e
+ do { perror(msg); exit(EXIT_FAILURE); } while (0)
+\&
+static char *buffer;
+\&
+static void
+handler(int sig, siginfo_t *si, void *unused)
+{
+ /* Note: calling printf() from a signal handler is not safe
+ (and should not be done in production programs), since
+ printf() is not async\-signal\-safe; see signal\-safety(7).
+ Nevertheless, we use printf() here as a simple way of
+ showing that the handler was called. */
+\&
+ printf("Got SIGSEGV at address: %p\en", si\->si_addr);
+ exit(EXIT_FAILURE);
+}
+\&
+int
+main(void)
+{
+ 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: %p\en", buffer);
+\&
+ if (mprotect(buffer + pagesize * 2, pagesize,
+ PROT_READ) == \-1)
+ handle_error("mprotect");
+\&
+ for (char *p = buffer ; ; )
+ *(p++) = \[aq]a\[aq];
+\&
+ printf("Loop completed\en"); /* Should never happen */
+ exit(EXIT_SUCCESS);
+}
+.EE
+.\" SRC END
+.SH SEE ALSO
+.BR mmap (2),
+.BR sysconf (3),
+.BR pkeys (7)