diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2024-11-04 11:43:27 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2024-11-04 11:43:27 +0100 |
| commit | 3448e941710dbf11d2772d5782a0b2d44e7892b1 (patch) | |
| tree | 2c9ee9d17416e124b7baaa53eefafc2f0a0a7942 /src | |
| parent | 08085be36070ba22b9e2e99529826d60d5ba149f (diff) | |
| download | box64-3448e941710dbf11d2772d5782a0b2d44e7892b1.tar.gz box64-3448e941710dbf11d2772d5782a0b2d44e7892b1.zip | |
Improve handling of memory protection, and excution bit
Diffstat (limited to 'src')
| -rw-r--r-- | src/custommem.c | 10 | ||||
| -rw-r--r-- | src/dynarec/dynablock.c | 3 | ||||
| -rw-r--r-- | src/dynarec/dynarec_native_functions.c | 2 | ||||
| -rw-r--r-- | src/emu/modrm.h | 6 | ||||
| -rw-r--r-- | src/emu/x64run.c | 11 | ||||
| -rw-r--r-- | src/emu/x64run0f.c | 13 | ||||
| -rw-r--r-- | src/emu/x64runf20f.c | 1 | ||||
| -rw-r--r-- | src/include/signals.h | 1 | ||||
| -rw-r--r-- | src/libtools/signal32.c | 37 | ||||
| -rw-r--r-- | src/libtools/signals.c | 93 | ||||
| -rw-r--r-- | src/wrapped/wrappedlibc.c | 33 |
11 files changed, 162 insertions, 48 deletions
diff --git a/src/custommem.c b/src/custommem.c index 524e5f25..be9f39ed 100644 --- a/src/custommem.c +++ b/src/custommem.c @@ -1438,8 +1438,11 @@ void unprotectDB(uintptr_t addr, size_t size, int mark) if(mark) cleanDBFromAddressRange(cur, bend-cur, 0); mprotect((void*)cur, bend-cur, prot); - } else if(prot&PROT_DYNAREC_R) + } else if(prot&PROT_DYNAREC_R) { + if(mark) + cleanDBFromAddressRange(cur, bend-cur, 0); prot &= ~PROT_CUSTOM; + } } if (prot != oprot) rb_set(memprot, cur, bend, prot); @@ -1514,8 +1517,9 @@ void updateProtection(uintptr_t addr, size_t size, uint32_t prot) dyn = PROT_DYNAREC_R; } } - if ((prot|dyn) != oprot) - rb_set(memprot, cur, bend, prot|dyn); + uint32_t new_prot = prot?(prot|dyn):prot; + if (new_prot != oprot) + rb_set(memprot, cur, bend, new_prot); cur = bend; } UNLOCK_PROT(); diff --git a/src/dynarec/dynablock.c b/src/dynarec/dynablock.c index 4c703167..bfe10758 100644 --- a/src/dynarec/dynablock.c +++ b/src/dynarec/dynablock.c @@ -19,6 +19,7 @@ #include "dynarec_private.h" #include "elfloader.h" #include "bridge.h" +#include "signals.h" #include "dynarec_native.h" #include "native_lock.h" @@ -198,6 +199,8 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t { if(hasAlternate((void*)addr)) return NULL; + if((getProtection(addr)&(PROT_EXEC|PROT_READ))!=(PROT_EXEC|PROT_READ)) // cannot be run, get out of the Dynarec + return NULL; dynablock_t* block = getDB(addr); if(block || !create) return block; diff --git a/src/dynarec/dynarec_native_functions.c b/src/dynarec/dynarec_native_functions.c index 5a086018..c6ea65b0 100644 --- a/src/dynarec/dynarec_native_functions.c +++ b/src/dynarec/dynarec_native_functions.c @@ -172,7 +172,7 @@ void native_ud(x64emu_t* emu) void native_priv(x64emu_t* emu) { emu->test.test = 0; - emit_signal(emu, SIGSEGV, (void*)R_RIP, 0); + emit_signal(emu, SIGSEGV, (void*)R_RIP, 0xbad0); } void native_int(x64emu_t* emu, int num) diff --git a/src/emu/modrm.h b/src/emu/modrm.h index 2f2cd1fc..6b02e74a 100644 --- a/src/emu/modrm.h +++ b/src/emu/modrm.h @@ -11,9 +11,9 @@ #define F64S *(int64_t*)(addr+=8, addr-8) #define PK(a) *(uint8_t*)(addr+a) #ifdef DYNAREC -#define STEP if(step) return 0; -#define STEP2 if(step) {R_RIP = addr; return 0;} -#define STEP3 if(*step) (*step)++; +#define STEP check_exec(emu, addr); if(step) return 0; +#define STEP2 check_exec(emu, addr); if(step) {R_RIP = addr; return 0;} +#define STEP3 check_exec(emu, addr); if(*step) (*step)++; #else #define STEP #define STEP2 diff --git a/src/emu/x64run.c b/src/emu/x64run.c index 27232c9e..5859ec34 100644 --- a/src/emu/x64run.c +++ b/src/emu/x64run.c @@ -71,6 +71,7 @@ int Run(x64emu_t *emu, int step) #ifdef TEST_INTERPRETER test->memsize = 0; #else + check_exec(emu, R_RIP); x64emurun: while(1) #endif @@ -1813,7 +1814,7 @@ x64emurun: F8; if(rex.is32bits && box64_ignoreint3) {} else - emit_signal(emu, SIGSEGV, (void*)R_RIP, 0); + emit_signal(emu, SIGSEGV, (void*)R_RIP, 0xbad0); STEP; #endif break; @@ -1853,7 +1854,7 @@ x64emurun: #ifndef TEST_INTERPRETER if(rex.is32bits && box64_ignoreint3) {} else - emit_signal(emu, SIGSEGV, (void*)R_RIP, 0); + emit_signal(emu, SIGSEGV, (void*)R_RIP, 0xbad0); STEP; #endif break; @@ -1882,7 +1883,7 @@ x64emurun: case 0xF4: /* HLT */ // this is a privilege opcode... #ifndef TEST_INTERPRETER - emit_signal(emu, SIGSEGV, (void*)R_RIP, 0); + emit_signal(emu, SIGSEGV, (void*)R_RIP, 0xbad0); STEP; #endif break; @@ -2016,14 +2017,14 @@ x64emurun: // this is a privilege opcode if(rex.is32bits && box64_ignoreint3) {} else - emit_signal(emu, SIGSEGV, (void*)R_RIP, 0); + emit_signal(emu, SIGSEGV, (void*)R_RIP, 0xbad0); STEP; break; case 0xFB: /* STI */ // this is a privilege opcode if(rex.is32bits && box64_ignoreint3) {} else - emit_signal(emu, SIGSEGV, (void*)R_RIP, 0); + emit_signal(emu, SIGSEGV, (void*)R_RIP, 0xbad0); STEP; break; case 0xFC: /* CLD */ diff --git a/src/emu/x64run0f.c b/src/emu/x64run0f.c index d1ae6ff8..0364f4e9 100644 --- a/src/emu/x64run0f.c +++ b/src/emu/x64run0f.c @@ -387,6 +387,19 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) R_RAX = tmp64u&0xFFFFFFFF; break; + case 0x34: /* SYSENTER */ + #ifndef TEST_INTERPRETER + emit_signal(emu, SIGSEGV, (void*)R_RIP, 0xbad0); + STEP; + #endif + break; + case 0x35: /* SYSEXIT */ + #ifndef TEST_INTERPRETER + emit_signal(emu, SIGSEGV, (void*)R_RIP, 0xbad0); + STEP; + #endif + break; + case 0x38: // these are some SSE3 opcodes opcode = F8; switch(opcode) { diff --git a/src/emu/x64runf20f.c b/src/emu/x64runf20f.c index 5b28888f..097d0e32 100644 --- a/src/emu/x64runf20f.c +++ b/src/emu/x64runf20f.c @@ -20,6 +20,7 @@ #include "x87emu_private.h" #include "box64context.h" #include "bridge.h" +#include "signals.h" #include "modrm.h" diff --git a/src/include/signals.h b/src/include/signals.h index cf927503..ef72f401 100644 --- a/src/include/signals.h +++ b/src/include/signals.h @@ -62,5 +62,6 @@ void fini_signal_helper(void); void emit_signal(x64emu_t* emu, int sig, void* addr, int code); void emit_interruption(x64emu_t* emu, int num, void* addr); void emit_div0(x64emu_t* emu, void* addr, int code); +void check_exec(x64emu_t* emu, uintptr_t addr); #endif //__SIGNALS_H__ diff --git a/src/libtools/signal32.c b/src/libtools/signal32.c index 8a6a1613..064fd3a0 100644 --- a/src/libtools/signal32.c +++ b/src/libtools/signal32.c @@ -398,6 +398,7 @@ uint32_t RunFunctionHandler32(int* exit, int dynarec, i386_ucontext_t* sigcontex void my_sigactionhandler_oldcode_32(int32_t sig, int simple, siginfo_t* info, void * ucntx, int* old_code, void* cur_db) { int Locks = unlockMutex(); + int log_minimum = (box64_showsegv)?LOG_NONE:((sig==SIGSEGV && my_context->is_sigaction[sig])?LOG_DEBUG:LOG_INFO); printf_log(LOG_DEBUG, "Sigactionhanlder for signal #%d called (jump to %p/%s)\n", sig, (void*)my_context->signals[sig], GetNativeName((void*)my_context->signals[sig])); @@ -563,22 +564,42 @@ void my_sigactionhandler_oldcode_32(int32_t sig, int simple, siginfo_t* info, vo TRAP_x86_CACHEFLT = 19 // SIMD exception (via SIGFPE) if CPU is SSE capable otherwise Cache flush exception (via SIGSEV) */ uint32_t prot = getProtection((uintptr_t)info->si_addr); + uint32_t real_prot = 0; + if(prot&PROT_READ) real_prot|=PROT_READ; + if(prot&PROT_WRITE) real_prot|=PROT_WRITE; + if(prot&PROT_EXEC) real_prot|=PROT_WRITE; + if(prot&PROT_DYNAREC) real_prot|=PROT_WRITE; + sigcontext->uc_mcontext.gregs[I386_ERR] = 0; + sigcontext->uc_mcontext.gregs[I386_TRAPNO] = 0; if(sig==SIGBUS) sigcontext->uc_mcontext.gregs[I386_TRAPNO] = 17; else if(sig==SIGSEGV) { if((uintptr_t)info->si_addr == sigcontext->uc_mcontext.gregs[I386_EIP]) { - sigcontext->uc_mcontext.gregs[I386_ERR] = (info->si_errno==0x1234)?0:((info->si_errno==0xdead)?(0x2|(info->si_code<<3)):0x0010); // execution flag issue (probably), unless it's a #GP(0) - sigcontext->uc_mcontext.gregs[I386_TRAPNO] = ((info->si_code==SEGV_ACCERR) || (info->si_errno==0x1234) || (info->si_errno==0xdead) || ((uintptr_t)info->si_addr==0))?13:14; + if(info->si_errno==0xbad0) { + //bad opcode + sigcontext->uc_mcontext.gregs[I386_ERR] = 0; + sigcontext->uc_mcontext.gregs[I386_TRAPNO] = 13; + info2->si_errno = 0; + } else if (info->si_errno==0xecec) { + // no excute bit on segment + sigcontext->uc_mcontext.gregs[I386_ERR] = (real_prot&PROT_READ)?16:1; // EXECUTE_FAULT & READ_FAULT + sigcontext->uc_mcontext.gregs[I386_TRAPNO] = 14; + info2->si_errno = 0; + }else { + sigcontext->uc_mcontext.gregs[I386_ERR] = (real_prot&PROT_READ)?16:1;//(info->si_errno==0x1234)?0:((info->si_errno==0xdead)?(0x2|(info->si_code<<3)):0x0010); // execution flag issue (probably), unless it's a #GP(0) + sigcontext->uc_mcontext.gregs[I386_TRAPNO] = (getMmapped((uintptr_t)info->si_addr))?14:13; + //sigcontext->uc_mcontext.gregs[I386_TRAPNO] = ((info->si_code==SEGV_ACCERR) || (info->si_errno==0x1234) || (info->si_errno==0xdead) || ((uintptr_t)info->si_addr==0))?13:14; + } } else if(info->si_code==SEGV_ACCERR && !(prot&PROT_WRITE)) { - sigcontext->uc_mcontext.gregs[I386_ERR] = 0x0002; // write flag issue + sigcontext->uc_mcontext.gregs[I386_ERR] = (real_prot&PROT_READ)?2:1;//0x0002; // write flag issue sigcontext->uc_mcontext.gregs[I386_TRAPNO] = 14; } else { if((info->si_code!=SEGV_ACCERR) && labs((intptr_t)info->si_addr-(intptr_t)sigcontext->uc_mcontext.gregs[I386_ESP])<16) sigcontext->uc_mcontext.gregs[I386_TRAPNO] = 12; // stack overflow probably else - sigcontext->uc_mcontext.gregs[I386_TRAPNO] = (info->si_code == SEGV_ACCERR)?13:14; + sigcontext->uc_mcontext.gregs[I386_TRAPNO] = (info->si_code == SEGV_ACCERR)?14:13; //I386_ERR seems to be INT:8 CODE:8. So for write access segfault it's 0x0002 For a read it's 0x0004 (and 8 for exec). For an int 2d it could be 0x2D01 for example - sigcontext->uc_mcontext.gregs[I386_ERR] = 0x0004; // read error? there is no execute control in box64 anyway + sigcontext->uc_mcontext.gregs[I386_ERR] = 0x0001; // read error? } if(info->si_code == SEGV_ACCERR && old_code) *old_code = -1; @@ -586,7 +607,7 @@ void my_sigactionhandler_oldcode_32(int32_t sig, int simple, siginfo_t* info, vo info2->si_errno = 0; } else if(info->si_errno==0xdead) { // INT x - uint8_t int_n = info2->si_code; + uint8_t int_n = info->si_code; info2->si_errno = 0; info2->si_code = info->si_code; info2->si_addr = NULL; @@ -621,7 +642,7 @@ void my_sigactionhandler_oldcode_32(int32_t sig, int simple, siginfo_t* info, vo sigcontext->uc_mcontext.gregs[I386_ERR] = 0; } //TODO: SIGABRT generate what? - printf_log(LOG_DEBUG, "Signal %d: si_addr=%p, TRAPNO=%d, ERR=%d, RIP=%p\n", sig, (void*)info2->si_addr, sigcontext->uc_mcontext.gregs[I386_TRAPNO], sigcontext->uc_mcontext.gregs[I386_ERR],from_ptrv(sigcontext->uc_mcontext.gregs[I386_EIP])); + printf_log((sig==10)?LOG_DEBUG:log_minimum, "Signal %d: si_addr=%p, TRAPNO=%d, ERR=%d, RIP=%p\n", sig, (void*)info2->si_addr, sigcontext->uc_mcontext.gregs[I386_TRAPNO], sigcontext->uc_mcontext.gregs[I386_ERR],from_ptrv(sigcontext->uc_mcontext.gregs[I386_EIP])); // call the signal handler i386_ucontext_t sigcontext_copy = *sigcontext; // save old value from emu @@ -684,7 +705,7 @@ void my_sigactionhandler_oldcode_32(int32_t sig, int simple, siginfo_t* info, vo #undef GO for(int i=0; i<6; ++i) emu->segs_serial[i] = 0; - printf_log(LOG_DEBUG, "Context has been changed in Sigactionhanlder, doing siglongjmp to resume emu at %p, RSP=%p\n", (void*)R_RIP, (void*)R_RSP); + printf_log((sig==10)?LOG_DEBUG:log_minimum, "Context has been changed in Sigactionhanlder, doing siglongjmp to resume emu at %p, RSP=%p\n", (void*)R_RIP, (void*)R_RSP); if(old_code) *old_code = -1; // re-init the value to allow another segfault at the same place //relockMutex(Locks); // do not relock mutex, because of the siglongjmp, whatever was running is canceled diff --git a/src/libtools/signals.c b/src/libtools/signals.c index e7280663..eebae427 100644 --- a/src/libtools/signals.c +++ b/src/libtools/signals.c @@ -286,7 +286,7 @@ static __thread int signal_jmpbuf_active = 0; //1<<1 is mutex_prot, 1<<8 is mutex_dyndump #define is_memprot_locked (1<<1) #define is_dyndump_locked (1<<8) -uint64_t RunFunctionHandler(int* exit, int dynarec, x64_ucontext_t* sigcontext, uintptr_t fnc, int nargs, ...) +uint64_t RunFunctionHandler(x64emu_t* emu, int* exit, int dynarec, x64_ucontext_t* sigcontext, uintptr_t fnc, int nargs, ...) { if(fnc==0 || fnc==1) { va_list va; @@ -311,8 +311,8 @@ uint64_t RunFunctionHandler(int* exit, int dynarec, x64_ucontext_t* sigcontext, // Dynarec cannot be used in signal handling unless custom malloc is used dynarec = 0; #endif - - x64emu_t *emu = thread_get_emu(); + if(!emu) + emu = thread_get_emu(); #ifdef DYNAREC if(box64_dynarec_test) emu->test.test = 0; @@ -927,7 +927,7 @@ int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc, void* _fpsimd) #ifdef BOX32 void my_sigactionhandler_oldcode_32(int32_t sig, int simple, siginfo_t* info, void * ucntx, int* old_code, void* cur_db); #endif -void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void * ucntx, int* old_code, void* cur_db) +void my_sigactionhandler_oldcode(x64emu_t* emu, int32_t sig, int simple, siginfo_t* info, void * ucntx, int* old_code, void* cur_db) { #ifdef BOX32 if(box64_is32bits) { @@ -936,12 +936,14 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void } #endif int Locks = unlockMutex(); + int log_minimum = (box64_showsegv)?LOG_NONE:((sig==SIGSEGV && my_context->is_sigaction[sig])?LOG_DEBUG:LOG_INFO); printf_log(LOG_DEBUG, "Sigactionhanlder for signal #%d called (jump to %p/%s)\n", sig, (void*)my_context->signals[sig], GetNativeName((void*)my_context->signals[sig])); uintptr_t restorer = my_context->restorer[sig]; // get that actual ESP first! - x64emu_t *emu = thread_get_emu(); + if(!emu) + emu = thread_get_emu(); uintptr_t frame = R_RSP; #if defined(DYNAREC) #if defined(ARM64) @@ -1143,22 +1145,42 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void TRAP_x86_CACHEFLT = 19 // SIMD exception (via SIGFPE) if CPU is SSE capable otherwise Cache flush exception (via SIGSEV) */ uint32_t prot = getProtection((uintptr_t)info->si_addr); + uint32_t real_prot = 0; + if(prot&PROT_READ) real_prot|=PROT_READ; + if(prot&PROT_WRITE) real_prot|=PROT_WRITE; + if(prot&PROT_EXEC) real_prot|=PROT_WRITE; + if(prot&PROT_DYNAREC) real_prot|=PROT_WRITE; + sigcontext->uc_mcontext.gregs[X64_ERR] = 0; + sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 0; if(sig==SIGBUS) sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 17; else if(sig==SIGSEGV) { if((uintptr_t)info->si_addr == sigcontext->uc_mcontext.gregs[X64_RIP]) { - sigcontext->uc_mcontext.gregs[X64_ERR] = (info->si_errno==0x1234)?0:((info->si_errno==0xdead)?(0x2|(info->si_code<<3)):0x0010); // execution flag issue (probably), unless it's a #GP(0) - sigcontext->uc_mcontext.gregs[X64_TRAPNO] = ((info->si_code==SEGV_ACCERR) || (info->si_errno==0x1234) || (info->si_errno==0xdead) || ((uintptr_t)info->si_addr==0))?13:14; + if(info->si_errno==0xbad0) { + //bad opcode + sigcontext->uc_mcontext.gregs[X64_ERR] = 0; + sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 13; + info2->si_errno = 0; + } else if (info->si_errno==0xecec) { + // no excute bit on segment + sigcontext->uc_mcontext.gregs[X64_ERR] = (real_prot&PROT_READ)?16:1; // EXECUTE_FAULT & READ_FAULT + sigcontext->uc_mcontext.gregs[X64_TRAPNO] = (getMmapped((uintptr_t)info->si_addr))?14:13; + info2->si_errno = 0; + }else { + sigcontext->uc_mcontext.gregs[X64_ERR] = (real_prot&PROT_READ)?16:1;//(info->si_errno==0x1234)?0:((info->si_errno==0xdead)?(0x2|(info->si_code<<3)):0x0010); // execution flag issue (probably), unless it's a #GP(0) + sigcontext->uc_mcontext.gregs[X64_TRAPNO] = (getMmapped((uintptr_t)info->si_addr))?14:13; + //sigcontext->uc_mcontext.gregs[X64_TRAPNO] = ((info->si_code==SEGV_ACCERR) || (info->si_errno==0x1234) || (info->si_errno==0xdead) || ((uintptr_t)info->si_addr==0))?13:14; + } } else if(info->si_code==SEGV_ACCERR && !(prot&PROT_WRITE)) { - sigcontext->uc_mcontext.gregs[X64_ERR] = 0x0002; // write flag issue + sigcontext->uc_mcontext.gregs[X64_ERR] = (real_prot&PROT_READ)?2:1;//0x0002; // write flag issue sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 14; } else { if((info->si_code!=SEGV_ACCERR) && labs((intptr_t)info->si_addr-(intptr_t)sigcontext->uc_mcontext.gregs[X64_RSP])<16) sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 12; // stack overflow probably else - sigcontext->uc_mcontext.gregs[X64_TRAPNO] = (info->si_code == SEGV_ACCERR)?13:14; + sigcontext->uc_mcontext.gregs[X64_TRAPNO] = (info->si_code == SEGV_ACCERR)?14:13; //X64_ERR seems to be INT:8 CODE:8. So for write access segfault it's 0x0002 For a read it's 0x0004 (and 8 for exec). For an int 2d it could be 0x2D01 for example - sigcontext->uc_mcontext.gregs[X64_ERR] = 0x0004; // read error? there is no execute control in box64 anyway + sigcontext->uc_mcontext.gregs[X64_ERR] = 0x0001; // read error? } if(info->si_code == SEGV_ACCERR && old_code) *old_code = -1; @@ -1166,7 +1188,7 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void info2->si_errno = 0; } else if(info->si_errno==0xdead) { // INT x - uint8_t int_n = info2->si_code; + uint8_t int_n = info->si_code; info2->si_errno = 0; info2->si_code = info->si_code; info2->si_addr = NULL; @@ -1201,7 +1223,7 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void sigcontext->uc_mcontext.gregs[X64_ERR] = 0; } //TODO: SIGABRT generate what? - printf_log(LOG_DEBUG, "Signal %d: si_addr=%p, TRAPNO=%d, ERR=%d, RIP=%p\n", sig, (void*)info2->si_addr, sigcontext->uc_mcontext.gregs[X64_TRAPNO], sigcontext->uc_mcontext.gregs[X64_ERR],sigcontext->uc_mcontext.gregs[X64_RIP]); + printf_log((sig==10)?LOG_DEBUG:log_minimum, "Signal %d: si_addr=%p, TRAPNO=%d, ERR=%d, RIP=%p\n", sig, (void*)info2->si_addr, sigcontext->uc_mcontext.gregs[X64_TRAPNO], sigcontext->uc_mcontext.gregs[X64_ERR],sigcontext->uc_mcontext.gregs[X64_RIP]); // call the signal handler x64_ucontext_t sigcontext_copy = *sigcontext; // save old value from emu @@ -1227,7 +1249,7 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void if(sig!=SIGSEGV && !(Locks&is_dyndump_locked) && !(Locks&is_memprot_locked)) dynarec = 1; #endif - ret = RunFunctionHandler(&exits, dynarec, sigcontext, my_context->signals[info2->si_signo], 3, info2->si_signo, info2, sigcontext); + ret = RunFunctionHandler(emu, &exits, dynarec, sigcontext, my_context->signals[info2->si_signo], 3, info2->si_signo, info2, sigcontext); // restore old value from emu if(used_stack) // release stack new_ss->ss_flags = 0; @@ -1279,7 +1301,7 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void #undef GO for(int i=0; i<6; ++i) emu->segs_serial[i] = 0; - printf_log(LOG_DEBUG, "Context has been changed in Sigactionhanlder, doing siglongjmp to resume emu at %p, RSP=%p\n", (void*)R_RIP, (void*)R_RSP); + printf_log((sig==10)?LOG_DEBUG:log_minimum, "Context has been changed in Sigactionhanlder, doing siglongjmp to resume emu at %p, RSP=%p\n", (void*)R_RIP, (void*)R_RSP); if(old_code) *old_code = -1; // re-init the value to allow another segfault at the same place //relockMutex(Locks); // do not relock mutex, because of the siglongjmp, whatever was running is canceled @@ -1339,7 +1361,7 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void exit(ret); } if(restorer) - RunFunctionHandler(&exits, 0, NULL, restorer, 0); + RunFunctionHandler(emu, &exits, 0, NULL, restorer, 0); relockMutex(Locks); } @@ -1854,7 +1876,7 @@ dynarec_log(/*LOG_DEBUG*/LOG_INFO, "Repeated SIGSEGV with Access error on %p for } relockMutex(Locks); if(my_context->signals[sig] && my_context->signals[sig]!=1) { - my_sigactionhandler_oldcode(sig, my_context->is_sigaction[sig]?0:1, info, ucntx, &old_code, db); + my_sigactionhandler_oldcode(emu, sig, my_context->is_sigaction[sig]?0:1, info, ucntx, &old_code, db); return; } // no handler (or double identical segfault) @@ -1882,7 +1904,7 @@ void my_sigactionhandler(int32_t sig, siginfo_t* info, void * ucntx) void* db = NULL; #endif - my_sigactionhandler_oldcode(sig, 0, info, ucntx, NULL, db); + my_sigactionhandler_oldcode(NULL, sig, 0, info, ucntx, NULL, db); } #ifndef DYNAREC @@ -1895,6 +1917,13 @@ void emit_signal(x64emu_t* emu, int sig, void* addr, int code) info.si_signo = sig; info.si_errno = (sig==SIGSEGV)?0x1234:0; // Mark as a sign this is a #GP(0) (like privileged instruction) info.si_code = code; + if(sig==SIGSEGV && code==0xbad0) { + info.si_errno = 0xbad0; + info.si_code = 0; + } else if(sig==SIGSEGV && code==0xecec) { + info.si_errno = 0xecec; + info.si_code = SEGV_ACCERR; + } info.si_addr = addr; const char* x64name = NULL; const char* elfname = NULL; @@ -1903,13 +1932,33 @@ void emit_signal(x64emu_t* emu, int sig, void* addr, int code) elfheader_t* elf = FindElfAddress(my_context, R_RIP); if(elf) elfname = ElfName(elf); - printf_log(LOG_NONE, "Emit Signal %d at IP=%p(%s / %s) / addr=%p, code=%d\n", sig, (void*)R_RIP, x64name?x64name:"???", elfname?elfname:"?", addr, code); + printf_log(LOG_NONE, "Emit Signal %d at IP=%p(%s / %s) / addr=%p, code=0x%x\n", sig, (void*)R_RIP, x64name?x64name:"???", elfname?elfname:"?", addr, code); +printf_log(LOG_NONE, DumpCPURegs(emu, R_RIP, emu->segs[_CS]==0x23)); + //if(!elf) { + // FILE* f = fopen("/proc/self/maps", "r"); + // if(f) { + // char line[1024]; + // while(!feof(f)) { + // char* ret = fgets(line, sizeof(line), f); + // printf_log(LOG_NONE, "\t%s", ret); + // } + // fclose(f); + // } + //} if(sig==SIGILL) { uint8_t* mem = (uint8_t*)R_RIP; printf_log(LOG_NONE, "SIGILL: Opcode at ip is %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx\n", mem[0], mem[1], mem[2], mem[3], mem[4], mem[5]); } } - my_sigactionhandler_oldcode(sig, 0, &info, NULL, NULL, NULL); + my_sigactionhandler_oldcode(emu, sig, 0, &info, NULL, NULL, NULL); +} + +void check_exec(x64emu_t* emu, uintptr_t addr) +{ + while((getProtection(addr)&(PROT_EXEC|PROT_READ))!=(PROT_EXEC|PROT_READ)) { + R_RIP = addr; // incase there is a slight difference + emit_signal(emu, SIGSEGV, (void*)addr, 0xecec); + } } void emit_interruption(x64emu_t* emu, int num, void* addr) @@ -1918,7 +1967,7 @@ void emit_interruption(x64emu_t* emu, int num, void* addr) info.si_signo = SIGSEGV; info.si_errno = 0xdead; info.si_code = num; - info.si_addr = addr; + info.si_addr = NULL;//addr; const char* x64name = NULL; const char* elfname = NULL; if(box64_log>LOG_INFO || box64_dynarec_dump || box64_showsegv) { @@ -1928,7 +1977,7 @@ void emit_interruption(x64emu_t* emu, int num, void* addr) elfname = ElfName(elf); printf_log(LOG_NONE, "Emit Interruption 0x%x at IP=%p(%s / %s) / addr=%p\n", num, (void*)R_RIP, x64name?x64name:"???", elfname?elfname:"?", addr); } - my_sigactionhandler_oldcode(SIGSEGV, 0, &info, NULL, NULL, NULL); + my_sigactionhandler_oldcode(emu, SIGSEGV, 0, &info, NULL, NULL, NULL); } void emit_div0(x64emu_t* emu, void* addr, int code) @@ -1947,7 +1996,7 @@ void emit_div0(x64emu_t* emu, void* addr, int code) elfname = ElfName(elf); printf_log(LOG_NONE, "Emit Divide by 0 at IP=%p(%s / %s) / addr=%p\n", (void*)R_RIP, x64name?x64name:"???", elfname?elfname:"?", addr); } - my_sigactionhandler_oldcode(SIGSEGV, 0, &info, NULL, NULL, NULL); + my_sigactionhandler_oldcode(emu, SIGSEGV, 0, &info, NULL, NULL, NULL); } EXPORT sighandler_t my_signal(x64emu_t* emu, int signum, sighandler_t handler) diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c index 8ca4c5b9..d10289da 100644 --- a/src/wrapped/wrappedlibc.c +++ b/src/wrapped/wrappedlibc.c @@ -1703,6 +1703,14 @@ static int isSysCpuCache(const char *path, const char* w, int* _cpu, int* _index return 1; } +static long isProcMem(const char* path) +{ + long pid; + if(sscanf(path, "/proc/%ld/mem", &pid)==1) + return pid; + return 0; +} + EXPORT ssize_t my_readlink(x64emu_t* emu, void* path, void* buf, size_t sz) { if(isProcSelf((const char*)path, "exe")) { @@ -1919,6 +1927,10 @@ EXPORT int32_t my_open(x64emu_t* emu, void* pathname, int32_t flags, uint32_t mo lseek(tmp, 0, SEEK_SET); return tmp; } + if(box64_wine && isProcMem(pathname) && (mode&O_WRONLY)) { + // deny using proc/XX/mem as it messes up with dynarec memory protection & tracking + return -1; + } #endif int ret = open(pathname, flags, mode); return ret; @@ -3411,24 +3423,33 @@ EXPORT long my_ptrace(x64emu_t* emu, int request, pid_t pid, void* addr, uint32_ { if(request == PTRACE_POKEUSER) { if(ptrace(PTRACE_PEEKDATA, pid, &userdata_sign, NULL)==userdata_sign && (uintptr_t)addr < sizeof(userdata)) { - ptrace(PTRACE_POKEDATA, pid, addr+(uintptr_t)userdata, data); - return 0; + long ret = ptrace(PTRACE_POKEDATA, pid, addr+(uintptr_t)userdata, data); + return ret; } // fallback to a generic local faking - if((uintptr_t)addr < sizeof(userdata)) + if((uintptr_t)addr < sizeof(userdata)) { *(uintptr_t*)(addr+(uintptr_t)userdata) = (uintptr_t)data; // lets just ignore this for now! - return 0; + errno = 0; + return 0; + } + errno = EINVAL; + return -1; } if(request == PTRACE_PEEKUSER) { if(ptrace(PTRACE_PEEKDATA, pid, &userdata_sign, NULL)==userdata_sign && (uintptr_t)addr < sizeof(userdata)) { return ptrace(PTRACE_PEEKDATA, pid, addr+(uintptr_t)userdata, data); } // fallback to a generic local faking - if((uintptr_t)addr < sizeof(userdata)) + if((uintptr_t)addr < sizeof(userdata)) { + errno = 0; return *(uintptr_t*)(addr+(uintptr_t)userdata); + } + errno = EINVAL; + return -1; } - return ptrace(request, pid, addr, data); + long ret = ptrace(request, pid, addr, data); + return ret; } // Backtrace stuff |