Crazy Psychild
Crazy Psychild

Reputation: 592

mprotect on heap aligned memory works mysteriously

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

Answers (1)

a3f
a3f

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.

Upvotes: 3

Related Questions