Reputation: 592
So I am trying to check if I can properly change the access rights on mmapped allocated memory using mprotect
and this is what I wrote:
#include <stdio.h>
#include <sys/mman.h>
#include <malloc.h>
#include <unistd.h>
void main()
{
int pagesize;
pagesize = getpagesize();
void *p;
p = malloc(pagesize);
getchar();
int q = posix_memalign(&p, pagesize, pagesize);
getchar();
int a = mprotect(p, pagesize, PROT_READ | PROT_WRITE | PROT_EXEC);
getchar();
free(p);
}
Now after each function i am using getchar
to analyze my memory segment using cat /proc/<pid>/maps
file and this is what I get:
(only showing the information regarding heap as that is my only concern)
After the posix_memalign
:
01776000-01798000 rw-p 00000000 00:00 0 [heap]
After the mprotect
function:
01776000-01778000 rw-p 00000000 00:00 0 [heap]
01778000-01779000 rwxp 00000000 00:00 0 [heap]
01779000-01798000 rw-p 00000000 00:00 0 [heap]
So if you notice the heap allocated before gets divided into three parts after i use mprotect
and only the second part of the heap gets the access permissions that i gave in the function.
Why does this division happens and why does only the second region of the divided heap gets the permissions?
Note: I have searched manpages and have found absolutely nothing regarding this.
Upvotes: 2
Views: 1372
Reputation: 8657
You allocated 0x1000
bytes at address p
, which is 0x1778000
in your example. When you called mprotect
with these parameters, it did indeed work as you wanted and marked 01778000-01779000 rwxp
.
Your question could thus be more aptly phrased as, why does posix_memalign(3)
seem to allocate more space than you requested?
Lets take a look at man posix_memalign
:
POSIX requires that memory obtained from posix_memalign() can be freed using free(3).
But how does free(3)
know how much bytes to free? It needs to store it somewhere outside the page you allocated. And how do subsequent invocations of malloc(3)
or friends know where to find freed blocks? These need to be stored somewhere too.
And it is no surprise that the heap allocator stores the data structures it uses to manage the heap on the heap.
If you want a more low-level way to allocate a page, use mmap(2)
:
p = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
This memory is managed by you, when you call munmap(2)
, the mapping is deleted by notifying the kernel directly. No recycling or management done in user space.
More information on what malloc(3)
does:
How do malloc() and free() work?
Wikipedia's article on C's dynamic memory facilities: https://en.wikipedia.org/wiki/C_dynamic_memory_allocation
glibc's implementation of malloc(3)
et al: https://github.com/lattera/glibc/blob/master/malloc/malloc.c#L3016
Blog post on glibc's implementation: https://sploitfun.wordpress.com/2015/02/10/understanding-glibc-malloc/
Upvotes: 3