memory mapped with mmap, and used with mprotect

1.8k views Asked by At

I have to do a provide memory regions for threads and apply basic concepts of memory management. The idea is create a Thread Local Storage, and manage the with write, read, and clone, and erase. The problem is when I try to unprotect with mprotect the page that is associated with a thread in a TLS, this send me an error. This is my structure:

The allocation for every page

int cnt;
for (cnt = 0; cnt < page_num; cnt++) {
    struct page *p;
    p = (struct page *) calloc(1, sizeof(struct page));

    int *map =  mmap(0, page_size, 0, MAP_ANON | MAP_PRIVATE, 0, 0);
    if (map == MAP_FAILED) {
        perror("Error mmapping the file");
        exit(EXIT_FAILURE);
    }

    p->address = (unsigned int)map; 

It is mapped by mmap, but when I try to protect the page with this code (or unprotect I have the same error, and it is in the first time I try to)

for(int i = 0; i < currentTLS->page_num; i++){
    tls_unprotect(currentTLS->pages[i]);
}

And the method tls_unprotect:

void tls_protect(struct page *p){
  if (mprotect((void *) p->address,PAGESIZE, PROT_READ | PROT_WRITE)) {
      fprintf(stderr, "tls_unprotect: could not unprotect page\n");
      exit(errno);
  }
} 

The protect method is the same.

The errorno code is 12.

I Appreciate any kind of help. Thanks.

1

There are 1 answers

0
Mat On
p->address = (unsigned int)map; 

This cast is very suspicious. On most 64bit systems (including OS X AFAIK), int is 32bit wide, so too short to hold a pointer.
That cast drops 4 bytes of the 8 that compose a pointer.

p->address should be declared as a void*, and that assignment should need no cast at all. If you need to store that as an unsigned integral type, use an uintptr_t (in <stdint.h>, C99).