An application dynamically allocates, say, four pages of memory. By default, this memory is both readable and writable; we refer to these as the memory protections on the page.
Wouldn't it be nice if the application developer could dynamically modify memory protections on a per-page basis? For example, keep the first page with default protections, make the second page read-only, the third page read+execute, and on the fourth page, not allow any kind of access (a guard page, perhaps?).
Well, this feature is precisely what the mprotect(2) system call is designed for. Let's delve into how we can exploit it to do all that. Here is its signature:
#include <sys/mman.h>
int mprotect(void *addr, size_t len, int prot);
It's really quite straightforward: starting at the (virtual) address, addr, for len bytes (that is, from addr up to addr+len-1 ), apply the memory protections specified by the prot bitmask. As the granularity of mprotect is a page, the first parameter, addr, is expected to be page-aligned (on a page boundary; recall that this is exactly what mlock[all](2) expects too).
The third parameter, prot, is where you specify the actual protections; it is a bitmask and can either be just the PROT_NONE bit or the bitwise OR of the remainder:
Protection bit |
Meaning of memory protection |
PROT_NONE | No access allowed on the page |
PROT_READ | Reads allowed on the page |
PROT_WRITE | Writes allowed on the page |
PROT_EXEC | Execute access allowed on the page |