I am writing a static program loader for Linux, I am reading ELF program headers and mapping the segments to the memory.
I have come across an executable which assumes that the virtual address of its first segment is at 0. My memory mapping fails, I get error allocating virtual page at address 0
.
I wonder if it is possible to allocate at all memory at address 0
for the user-space.
See this example code:
/*mmaptests.c*/
#include <sys/mman.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
int main()
{
void* p = mmap(0, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
printf("mmap result %p (errno %s)\n",p,strerror(errno));
return 0;
}
I compile it with:
gcc mmaptests.c
This is what it returns :
$./a.out
mmap result 0xffffffffffffffff (errno Operation not permitted)
I will be happy for any insights.
Thanks B
Linux will only let you mmap
the 0-th page if you have privileges, or on a system with the sysctl setting vm.mmap_min_addr = 0
(instead of the default 65536).
gcc mmaptests.c && sudo ./a.out
should get you:
mmap result (nil) (errno Success)
According to https://wiki.debian.org/mmap_min_addr, WINE for 16-bit Windows applications needs vm.mmap_min_addr = 0
, and so do old versions of QEMU to run as non-root. Most distros won't do that even in the installers for those packages, though, because making NULL-deref fail noisily by faulting is very desirable. (64 KiB also covers small array indexes from a base of 0.)
You can check your current setting with cat /proc/sys/vm/mmap_min_addr
, or to format as hex, printf '%#x\n' $(cat /proc/sys/vm/mmap_min_addr)