2

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.

a3f
  • 8,517
  • 1
  • 41
  • 46
Crazy Psychild
  • 552
  • 5
  • 16

1 Answers1

3

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.

Community
  • 1
  • 1
a3f
  • 8,517
  • 1
  • 41
  • 46
  • Slightly unrelated: You are leaking memory by overwriting `p` and the proper return type for `main` is `int` not `void`. – a3f Feb 06 '16 at 11:14
  • How did you come to know i allocate 1000 bytes (since I tried to allocate `pagesize` bytes which is 4096 bytes) and the address for that is `0x1778000` as after allocation the memory shown is `0x1776000-0x1798000`?Please elaborate that part, the rest I understood. – Crazy Psychild Feb 06 '16 at 13:00
  • @AbhinavJain Memory related stuff is usually represented in hexadecimal. 4096 in decimal equals 0x1000 in hex. If you `printf("%p", p)` you will get `0x1778000`, add `0x1000` to that and you will arrive at `0x01779000`, just like procfs told you. – a3f Feb 06 '16 at 13:09
  • Ok but what the previous `0x1000` were used for? – Crazy Psychild Feb 06 '16 at 13:49
  • 2
    Data internal to the `malloc(3)` implementation. Check out the last two links to see what kind of data glibc stores there. – a3f Feb 06 '16 at 13:50