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:
- The kernel only checks whether
MMAP_PAGE_ZERO
is set inload_elf_binary
, so setting it after a process has started will have no effect. - 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:
- Run the executable as
root
, withsudo
or something - Give the executable
CAP_SYS_RAWIO
- Change the
vm.mmap_min_addr
sysctl to 0
Note that all of those choices will have security consequences.