diff options
Diffstat (limited to 'man/man2/mprotect.2')
-rw-r--r-- | man/man2/mprotect.2 | 363 |
1 files changed, 363 insertions, 0 deletions
diff --git a/man/man2/mprotect.2 b/man/man2/mprotect.2 new file mode 100644 index 0000000..b378166 --- /dev/null +++ b/man/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 2024-05-02 "Linux man-pages (unreleased)" +.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> +.P +.BI "int mprotect(void " addr [. len "], size_t " len ", int " prot ); +.P +.BR "#define _GNU_SOURCE" " /* See feature_test_macros(7) */" +.B #include <sys/mman.h> +.P +.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. +.P +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. +.P +.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). +.P +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). +.P +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). +.P +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. +.P +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 . +.P +On some hardware architectures (e.g., i386), +.B PROT_WRITE +implies +.BR PROT_READ . +.P +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. +.P +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. +.P +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. +.P +An example of what we might see when running the program is the +following: +.P +.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) |