Submitted by wh5a on Thu, 07/23/2009 - 19:11.
This post is actually stimulated by a recent kernel bug
I always took it as granted that null pointers aren't accessible. However, after reading that lwn article I learned that it's by default allowed to map a page at address 0. This behavior of course can be controlled by the vm.mmap_min_addr sysctl knob. (UPDATE: According to this blog, this knob was introduced since kernel 2.6.23.)
The following code demonstrates my point.
$ cat a.c
#include "stdio.h"
#include "sys/mman.h"
#define PAGESIZE 4096
#define STEP (4096/sizeof(int))
int main() {
int *p = 0;
void *ret = mmap(p, 4096, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED, -1, 0);
if ((int)ret == -1) {
perror("mmap");
// Look for the lowest mappable address
do {
p += STEP;
ret = mmap(p, 4096, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED, -1, 0);
} while ((int)ret == -1);
}
*p = 3;
printf("*(%p) == %d\n", p, *p);
}
By default, we can establish a mapping at address 0.
$ /sbin/sysctl vm.mmap_min_addr
vm.mmap_min_addr = 0
$ ./a.out
*((nil)) == 3
(UPDATE: On 8/15/09, Debian kernel 2.6.30-6 changed this default value to 4096. Presumably, this change is made to defeat this even more powerful exploit.)
We can enforce a restriction through sysctl. The lowest mappable address will be rounded to the next page boundary. The root user doesn't seem to be restricted at all.
$ sudo sysctl vm.mmap_min_addr=10000
vm.mmap_min_addr = 10000
$ ./a.out
mmap: Permission denied
*(0x3000) == 3
$ sudo ./a.out
*((nil)) == 3
Recent comments
1 week 3 days ago
2 weeks 4 days ago
3 weeks 1 day ago
5 weeks 1 day ago
13 weeks 3 days ago
17 weeks 5 days ago
18 weeks 4 days ago
21 weeks 1 day ago
1 year 4 weeks ago
1 year 4 weeks ago