Home > Software design >  How does MMAP_PAGE_ZERO personality flag work?
How does MMAP_PAGE_ZERO personality flag work?

Time:07-04

According to linux man pages, MMAP_PAGE_ZERO flag used in personality system call makes the system emulates SVr4 behavior, meaning that zero page is mapped as read only. However, this a little naive trial (visible in the code below) does not prevent segmentation fault ocurrence.

#include <stdio.h>
#include <sys/personality.h>

int main(void)
{
  int *ptr = 0;
  (void)personality(MMAP_PAGE_ZERO);
  printf("%d\n", *ptr);
  return 0;
}

What should be the right usage of personality(MMAP_PAGE_ZERO) to achieve zero page mapped as read only for a process?

CodePudding user response:

There are two reasons that wasn't working for you:

  1. The kernel only checks whether MMAP_PAGE_ZERO is set in load_elf_binary, so setting it after a process has started will have no effect.
  2. That setting doesn't override the vm.mmap_min_addr sysctl, which isn't 0 on most systems.

To fix the first problem, try this program instead, which re-executes itself after setting that:

#include <stdio.h>
#include <sys/auxv.h>
#include <sys/personality.h>
#include <unistd.h>

int main(int argc, char **argv) {
    int persona = personality(0xffffffff);
    if(persona == -1) {
        perror("personality");
        return 1;
    }
    if(persona & MMAP_PAGE_ZERO) {
        int *ptr = 0;
        printf("%d\n", *ptr);
        return 0;
    } else {
        if(personality(persona | MMAP_PAGE_ZERO) == -1) {
            perror("personality");
            return 1;
        }
        execv((const char *)getauxval(AT_EXECFN), argv);
        perror("execv");
        return 1;
    }
}

To fix the second problem, you have three choices:

  1. Run the executable as root, with sudo or something
  2. Give the executable CAP_SYS_RAWIO
  3. Change the vm.mmap_min_addr sysctl to 0

Note that all of those choices will have security consequences.

  • Related