Some context: I have been seeing crashes in Android apps when running them under gdbserver (nvidia's) or valgrind (custom build), but not when running natively or under strace. It so happens that dalvik is getting ashmem fds through the binder, and maps them. But in a specific case, that mmap fails. What happens is the following:
- some process creates an ashmem region, and sets its protection mask to PROT_READ. that process doesn't have personality READ_IMPLIES_EXEC.
- another process gets that ashmem fd through the binder. This process has personality READ_IMPLIES_EXEC.
- when calling mmap on the fd with PROT_READ, as personality has READ_IMPLIES_EXEC, the kernel calls ashmem_mmap with PROT_READ | PROT_EXEC, which fails the protection check in ashmem_map, since the ashmem region is PROT_READ and not PROT_READ | PROT_EXEC.
(The reason the other process has personality READ_IMPLIES_EXEC is because the executable has executable stack, which, unfortunately, is what you get by default with the android NDK)
The following program highlights the problem:
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <linux/ashmem.h>
#include <unistd.h>
#include <sys/syscall.h>
void set_personality (unsigned int p) { __NR_personalit y, p);
syscall(
}
int main() { ty(0); SET_PROT_ MASK, PROT_READ); ty(0x0400000 /* READ_IMPLIES_EXEC */);
int fd = open("/dev/ashmem", O_RDWR);
set_personali
ioctl(fd, ASHMEM_SET_SIZE, 4096);
ioctl(fd, ASHMEM_
set_personali
if (mmap(NULL, 4096, PROT_READ, MAP_SHARED, fd, 0) == MAP_FAILED)
return 1;
return 0;
}