What’s the purpose of mmap memory protection PROT_NONE
PROT_NONE
can be used to implement guard pages, Microsoft has the same concept (MSDN).
To quote the first link:
... allocation of additional inaccessible memory during memory allocation
operations is a technique for mitigating against exploitation of heap
buffer overflows. These guard pages are unmapped pages placed between
all memory allocations of one page or larger. The guard page causes a
segmentation fault upon any access.
Thus useful in implementing protection for areas such as network interfacing, virtual machines, and interpreters. An example usage: pthread_attr_setguardsize, pthread_attr_getguardsize.
How does linux implement PROT_NONE mode of mprotect on x64 platform?
Note that mprotect is called from user space on virtual address regions. When protection is set to PROT_NONE, the _PAGE_PRESENT bit is cleared and the _PAGE_PROTNONE bit is set. Attempting to access the address will cause a page fault. Source
Why does calling mmap() with large size not fail?
mmap
reserves a region of the process's virtual address space, but does not immediately allocate physical RAM for it. Therefore, on a 64-bit platform, you can reserve a vast amount without failure (although you still need to check for failure; your example code doesn't). Physical pages of RAM are allocated later when the memory is accessed.
mprotect
just changes the read/write access of the reserved memory; it won't make it resident in RAM either. You would get the same effect by passing PROT_READ | PROT_WRITE
instead of PROT_NONE
to mmap
, and removing the call to mprotect
.
If you need the memory to be resident in RAM straight away, then use mlock
for that. It will fail if there isn't enough RAM available. On many linux platforms (including Ubuntu), there is a resource limit (RLIMIT_MEMLOCK
) which restricts how much memory any process can lock; you can adjust this with ulimit -l
.
mprotect(addr, size, PROT_NONE) for guard pages and its memory consumption
Linux applications are using virtual memory. Only the kernel is managing physical RAM. Application code don't see the physical RAM.
A segment protected with mprotect
& PROT_NONE
won't consume any RAM.
You should allocate your segment with mmap(2) (maybe you want MAP_NORESERVE
). Mixing memalign
with mprotect
may probably break libc invariants.
Read carefully madvise(2) man page. MADV_SOFT_OFFLINE
may require a specially configured kernel.
mmap protection flag effect to sharing between processes
According to the mmap(2) man page on a recent Linux system, MAP_PRIVATE allocates the memory using copy-on-write (COW). This means, your memory will not be duplicated unless you make changes to it. As COW is an efficient method to implement this, I assume it is also done this way in other *NIX systems.
The memory for mmap is organized in equal-sized chunks, so called pages. Memory will always be mapped in multiples of the page size, i.e. whole pages. Each page can be swapped independently. So if you write something to this mmap'ed memory range, only at least one page has to be copied.
The page size depends on your system, on x86 it is usually 4096 bytes. If you are interested in the page size of your system, you can use sysconf(3).
#include <unistd.h>
long pagesize = sysconf(_SC_PAGESIZE);
The pointer you get from mmap() will already point to a multiple of the page size and you should pass mprotect() an address being aligned to a page boundary.
Why in mmap PROT_READ equals PROT_EXEC
After doing some research I realized that Linux only activates memory protection when a GNU_STACK
program header is included in the ELF
program headers.
By memory protection I mean the use of the NX bit of the processor, so memory pages can be marked as not executable.
For what I understand, GNU_STACK
program header is designed to tell the kernel that you want some specific properties for the stack, one those properties is a non-executable stack. It appears that if you don't explicitly ask for a non-executable stack, all the ELF
sections marked as readable will be executable too. And also all the memory mapping with mmap
while have the same behavior.
Sadly there is no enough documentation on what GNU_STACK
does, and the documentation of mmap
doesn't specify its connection with GNU_STACK
to enable execute protection.
References:
https://wiki.gentoo.org/wiki/Hardened/GNU_stack_quickstart
usage of mprotect() on array
mprotect
granularity is limited and it will always protect full pages. As the size of page is 4kB on x86, it's not possible to protect 100 int array.
Secondly, current mmap
is a bit weird as you can't mmap to address which is already occupied in the process. Pass NULL and allocate completely new memory which will later free by calling munmap
.
Last but not least - to achieve the above, you can allocate full page and then adjust the array pointer so the end points to the end of the page.
Related Topics
How to Add Export Statement in a Bash_Profile File
Running Docker on Google Colab
Principle of Qemu CPU Emulation
How Is a Memory Barrier in Linux Kernel Is Used
Transpose Rows into Column in Unix
Cx_Oracle: Distutils.Errors.Distutilssetuperror: Cannot Locate Oracle Include Files
Bash - How to Print Multi Line Strings (With '\N') Using Printf
Why Does The Call Latency on Clock_Gettime(Clock_Realtime, ..) Vary So Much
How to Manually Install The Eclipse-Cdt Plugin from an Archive/Zip on Ubuntu
How to Keep Directory Structure with Aria2
Extract a Specific Folder to Specific Directory from a Tar.Gz
Using Su/Sudo When Accessing Remote Git Repositories Over Ssh
How to Check Character Encoding of a File in Linux
Crystalspace VS. Irrlicht VS. .....
Amazon Ec2 Lost Private Key, How to Get Access to The Server
How to Simulate Two Consecutive Enter Key Presses for a Command in a Bash Script