What's The Purpose of Mmap Memory Protection Prot_None

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



Leave a reply



Submit