diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2023-02-18 15:06:40 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2023-02-18 15:06:40 +0100 |
| commit | 9705d5e38bdf4ec72daf480de0830dfde6e33a70 (patch) | |
| tree | 3c64f69ae2c5569bfe0fa91f321149ce49991c02 /src | |
| parent | 2e59b56f1691227e4a93ac1c2dd844adcc6334cd (diff) | |
| download | box64-9705d5e38bdf4ec72daf480de0830dfde6e33a70.tar.gz box64-9705d5e38bdf4ec72daf480de0830dfde6e33a70.zip | |
Preliminary work to get steamwebhelper working
Diffstat (limited to 'src')
| -rw-r--r-- | src/custommem.c | 36 | ||||
| -rw-r--r-- | src/include/custommem.h | 6 | ||||
| -rwxr-xr-x | src/include/debug.h | 1 | ||||
| -rwxr-xr-x | src/libtools/signals.c | 5 | ||||
| -rwxr-xr-x | src/main.c | 14 | ||||
| -rw-r--r-- | src/mallochook.c | 118 | ||||
| -rw-r--r-- | src/tools/rcfile.c | 1 | ||||
| -rwxr-xr-x | src/wrapped/wrappedlibc.c | 11 |
8 files changed, 174 insertions, 18 deletions
diff --git a/src/custommem.c b/src/custommem.c index 9f5422a9..cc236be4 100644 --- a/src/custommem.c +++ b/src/custommem.c @@ -948,15 +948,16 @@ void protectDB(uintptr_t addr, uintptr_t size) } for (uintptr_t i=idx; i<=end; ++i) { uint32_t prot = memprot[i>>16].prot[i&0xffff]; - uint32_t dyn = prot&PROT_CUSTOM; + uint32_t dyn = prot&PROT_DYN; + uint32_t mapped = prot&PROT_MMAP; prot&=~PROT_CUSTOM; if(!prot) prot = PROT_READ | PROT_WRITE | PROT_EXEC; // comes from malloc & co, so should not be able to execute if((prot&PROT_WRITE)) { if(!dyn) mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_WRITE); - memprot[i>>16].prot[i&0xffff] = prot|PROT_DYNAREC; // need to use atomic exchange? + memprot[i>>16].prot[i&0xffff] = prot|mapped|PROT_DYNAREC; // need to use atomic exchange? } else - memprot[i>>16].prot[i&0xffff] = prot|PROT_DYNAREC_R; + memprot[i>>16].prot[i&0xffff] = prot|mapped|PROT_DYNAREC_R; } mutex_unlock(&mutex_prot); } @@ -984,10 +985,10 @@ void unprotectDB(uintptr_t addr, size_t size, int mark) for (uintptr_t i=idx; i<=end; ++i) { uint32_t prot = memprot[i>>16].prot[i&0xffff]; if(prot&PROT_DYNAREC) { - prot&=~PROT_CUSTOM; + prot&=~PROT_DYN; if(mark) cleanDBFromAddressRange((i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, 0); - mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot); + mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_MMAP); memprot[i>>16].prot[i&0xffff] = prot; // need to use atomic exchange? } else if(prot&PROT_DYNAREC_R) memprot[i>>16].prot[i&0xffff] = prot&~PROT_CUSTOM; @@ -1128,14 +1129,15 @@ void updateProtection(uintptr_t addr, size_t size, uint32_t prot) memprot[i].prot = newblock; } for (uintptr_t i=idx; i<=end; ++i) { - uint32_t dyn=(memprot[i>>16].prot[i&0xffff]&(PROT_DYNAREC | PROT_DYNAREC_R)); + uint32_t dyn=(memprot[i>>16].prot[i&0xffff]&PROT_DYN); + uint32_t mapped=(memprot[i>>16].prot[i&0xffff]&PROT_MMAP); if(dyn && (prot&PROT_WRITE)) { // need to remove the write protection from this block dyn = PROT_DYNAREC; - mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_WRITE); + mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~(PROT_WRITE|PROT_MMAP)); } else if(dyn && !(prot&PROT_WRITE)) { dyn = PROT_DYNAREC_R; } - memprot[i>>16].prot[i&0xffff] = prot|dyn; + memprot[i>>16].prot[i&0xffff] = prot|dyn|mapped; } mutex_unlock(&mutex_prot); } @@ -1163,6 +1165,11 @@ void setProtection(uintptr_t addr, size_t size, uint32_t prot) mutex_unlock(&mutex_prot); } +void setProtection_mmap(uintptr_t addr, size_t size, uint32_t prot) +{ + setProtection(addr, size, prot|PROT_MMAP); +} + void refreshProtection(uintptr_t addr) { mutex_lock(&mutex_prot); @@ -1336,7 +1343,18 @@ uint32_t getProtection(uintptr_t addr) const uintptr_t idx = (addr>>MEMPROT_SHIFT); uint32_t ret = memprot[idx>>16].prot[idx&0xffff]; mutex_unlock(&mutex_prot); - return ret; + return ret&~PROT_MMAP; +} + +int getMmapped(uintptr_t addr) +{ + if(addr>=(1LL<<48)) + return 0; + mutex_lock(&mutex_prot); + const uintptr_t idx = (addr>>MEMPROT_SHIFT); + uint32_t ret = memprot[idx>>16].prot[idx&0xffff]; + mutex_unlock(&mutex_prot); + return (ret&PROT_MMAP)?1:0; } #define LOWEST (void*)0x10000 diff --git a/src/include/custommem.h b/src/include/custommem.h index 42f75a89..590fd561 100644 --- a/src/include/custommem.h +++ b/src/include/custommem.h @@ -38,13 +38,17 @@ uintptr_t getJumpAddress64(uintptr_t addr); #define PROT_DYNAREC 0x80 #define PROT_DYNAREC_R 0x40 -#define PROT_CUSTOM (PROT_DYNAREC | PROT_DYNAREC_R) +#define PROT_MMAP 0x20 +#define PROT_DYN (PROT_DYNAREC | PROT_DYNAREC_R) +#define PROT_CUSTOM (PROT_DYNAREC | PROT_DYNAREC_R | PROT_MMAP) void updateProtection(uintptr_t addr, size_t size, uint32_t prot); void setProtection(uintptr_t addr, size_t size, uint32_t prot); +void setProtection_mmap(uintptr_t addr, size_t size, uint32_t prot); void freeProtection(uintptr_t addr, size_t size); void refreshProtection(uintptr_t addr); uint32_t getProtection(uintptr_t addr); +int getMmapped(uintptr_t addr); void loadProtectionFromMap(); #ifdef DYNAREC void protectDB(uintptr_t addr, size_t size); diff --git a/src/include/debug.h b/src/include/debug.h index 7251c728..0a6f722e 100755 --- a/src/include/debug.h +++ b/src/include/debug.h @@ -45,6 +45,7 @@ extern char* box64_trace; extern uint64_t start_cnt; #endif extern int box64_nosandbox; +extern int box64_malloc_hack; extern int box64_dummy_crashhandler; extern int box64_sse_flushto0; extern int allow_missing_libs; diff --git a/src/libtools/signals.c b/src/libtools/signals.c index a3f0b796..9ab18a75 100755 --- a/src/libtools/signals.c +++ b/src/libtools/signals.c @@ -855,7 +855,7 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx) } dynablock_t* db = NULL; int db_searched = 0; - if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&PROT_CUSTOM)) { + if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&PROT_DYN)) { mutex_lock(&mutex_dynarec_prot); // check if SMC inside block db = FindDynablockFromNativeAddress(pc); @@ -981,7 +981,7 @@ dynarec_log(/*LOG_DEBUG*/LOG_INFO, "Repeated SIGSEGV with Access error on %p for printf_log(log_minimum, "%04d|Double %s (code=%d, pc=%p, addr=%p)!\n", GetTID(), signame, old_code, old_pc, old_addr); exit(-1); } else { - if(sig==SIGSEGV && info->si_code==2 && ((prot&~PROT_CUSTOM)==5 || (prot&~PROT_CUSTOM)==7)) { + if(sig==SIGSEGV && info->si_code==2 && ((prot&~PROT_DYN)==5 || (prot&~PROT_DYN)==7)) { static uintptr_t old_addr = 0; printf_log(/*LOG_DEBUG*/LOG_INFO, "Strange SIGSEGV with Access error on %p for %p, db=%p, prot=0x%x (old_addr=%p)\n", pc, addr, db, prot, (void*)old_addr); if(old_addr!=(uintptr_t)addr) { @@ -1105,7 +1105,6 @@ exit(-1); free(strings); } else printf_log(log_minimum, "EmulatedBT: none\n"); -printf_log(log_minimum, "RDI = %p, Prot=0x%02x, ElfName(RDI)=%s\n",(void*)R_RDI, getProtection(R_RDI), ElfName(FindElfAddress(my_context, R_RDI))); #define GO(A) R_##A = old_##A GO(RAX); GO(RBX); diff --git a/src/main.c b/src/main.c index 6df6c8b1..4c0af6cd 100755 --- a/src/main.c +++ b/src/main.c @@ -45,6 +45,7 @@ int box64_dynarec_log = LOG_NONE; uintptr_t box64_pagesize; uintptr_t box64_load_addr = 0; int box64_nosandbox = 0; +int box64_malloc_hack = 0; #ifdef DYNAREC int box64_dynarec = 1; int box64_dynarec_dump = 0; @@ -678,6 +679,19 @@ void LoadLogEnv() if(!box64_dummy_crashhandler) printf_log(LOG_INFO, "Don't use dummy crashhandler lib\n"); } + p = getenv("BOX64_MALLOC_HACK"); + if(p) { + if(strlen(p)==1) { + if(p[0]>='0' && p[0]<='0'+2) + box64_malloc_hack = p[0]-'0'; + } + if(!box64_malloc_hack) { + if(box64_malloc_hack==1) { + printf_log(LOG_INFO, "Malloc hook will not be redirected\n"); + } else + printf_log(LOG_INFO, "Malloc hook will check for mmap/free occurences\n"); + } + } p = getenv("BOX64_NOPULSE"); if(p) { if(strlen(p)==1) { diff --git a/src/mallochook.c b/src/mallochook.c index 4faa8c08..b3011436 100644 --- a/src/mallochook.c +++ b/src/mallochook.c @@ -4,6 +4,7 @@ #include <string.h> #include <errno.h> #include <sys/param.h> +#include <sys/mman.h> #include <dlfcn.h> #include "box64context.h" @@ -11,6 +12,7 @@ #include "callback.h" #include "librarian.h" #include "elfs/elfloader_private.h" +#include "custommem.h" /* This file here is for handling overriding of malloc functions @@ -139,6 +141,10 @@ void*(*__libc_memalign)(size_t, size_t) = NULL; size_t(*box_malloc_usable_size)(void*) = NULL; int GetTID(); +uint32_t getProtection(uintptr_t addr); +// malloc_hack "2" handling +// mmap history +static int malloc_hack_2 = 0; char* box_strdup(const char* s) { char* ret = box_calloc(1, strlen(s)+1); @@ -182,6 +188,13 @@ EXPORT void* malloc(size_t l) EXPORT void free(void* p) { + if(malloc_hack_2 && p) { + if(getMmapped((uintptr_t)p)) { + printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p); + // Mmaped, do not free... + return; + } + } box_free(p); } @@ -192,6 +205,16 @@ EXPORT void* calloc(size_t n, size_t s) EXPORT void* realloc(void* p, size_t s) { + if(malloc_hack_2) + if(getMmapped((uintptr_t)p)) { + // found! Will realloc using regular malloc then copy from old address as much as possible, but need to check size first + void* ret = box_malloc(s); + printf_log(LOG_DEBUG, "Malloc_Hack_2: hacking realloc(%p, %zu)", p, s); + while(s && !(getProtection((uintptr_t)p+s)&PROT_READ)) {if(s>box64_pagesize) s-=box64_pagesize; else s=0;} + memcpy(ret, p, s); + printf_log(LOG_DEBUG, " -> %p (copied %zu from old)\n", ret, s); + return ret; + } return box_realloc(p, s); } @@ -228,6 +251,13 @@ EXPORT void* pvalloc(size_t size) EXPORT void cfree(void* p) { + if(malloc_hack_2 && p) { + if(getMmapped((uintptr_t)p)) { + printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p); + // Mmaped, do not free... + return; + } + } box_free(p); } @@ -259,26 +289,61 @@ EXPORT void* my__ZnamRKSt9nothrow_t(size_t sz, void* p) //operator new[](size_ EXPORT void my__ZdaPv(void* p) //operator delete[](void*) { + if(malloc_hack_2 && p) { + if(getMmapped((uintptr_t)p)) { + printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p); + // Mmaped, do not free... + return; + } + } box_free(p); } EXPORT void my__ZdaPvm(void* p, size_t sz) //operator delete[](void*, size_t) { + if(malloc_hack_2 && p) { + if(getMmapped((uintptr_t)p)) { + printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p); + // Mmaped, do not free... + return; + } + } box_free(p); } EXPORT void my__ZdaPvmSt11align_val_t(void* p, size_t sz, size_t align) //operator delete[](void*, unsigned long, std::align_val_t) { + if(malloc_hack_2 && p) { + if(getMmapped((uintptr_t)p)) { + printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p); + // Mmaped, do not free... + return; + } + } box_free(p); } EXPORT void my__ZdlPv(void* p) //operator delete(void*) { + if(malloc_hack_2 && p) { + if(getMmapped((uintptr_t)p)) { + printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p); + // Mmaped, do not free... + return; + } + } box_free(p); } EXPORT void my__ZdlPvm(void* p, size_t sz) //operator delete(void*, size_t) { + if(malloc_hack_2 && p) { + if(getMmapped((uintptr_t)p)) { + printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p); + // Mmaped, do not free... + return; + } + } box_free(p); } @@ -304,36 +369,85 @@ EXPORT void* my__ZnamSt11align_val_tRKSt9nothrow_t(size_t sz, size_t align, void EXPORT void my__ZdlPvRKSt9nothrow_t(void* p, void* n) //operator delete(void*, std::nothrow_t const&) { + if(malloc_hack_2 && p) { + if(getMmapped((uintptr_t)p)) { + printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p); + // Mmaped, do not free... + return; + } + } box_free(p); } EXPORT void my__ZdaPvSt11align_val_tRKSt9nothrow_t(void* p, size_t align, void* n) //operator delete[](void*, std::align_val_t, std::nothrow_t const&) { + if(malloc_hack_2 && p) { + if(getMmapped((uintptr_t)p)) { + printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p); + // Mmaped, do not free... + return; + } + } box_free(p); } EXPORT void my__ZdlPvmSt11align_val_t(void* p, size_t sz, size_t align) //operator delete(void*, unsigned long, std::align_val_t) { + if(malloc_hack_2 && p) { + if(getMmapped((uintptr_t)p)) { + printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p); + // Mmaped, do not free... + return; + } + } box_free(p); } EXPORT void my__ZdaPvRKSt9nothrow_t(void* p, void* n) //operator delete[](void*, std::nothrow_t const&) { + if(malloc_hack_2 && p) { + if(getMmapped((uintptr_t)p)) { + printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p); + // Mmaped, do not free... + return; + } + } box_free(p); } EXPORT void my__ZdaPvSt11align_val_t(void* p, size_t align) //operator delete[](void*, std::align_val_t) { + if(malloc_hack_2 && p) { + if(getMmapped((uintptr_t)p)) { + printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p); + // Mmaped, do not free... + return; + } + } box_free(p); } EXPORT void my__ZdlPvSt11align_val_t(void* p, size_t align) //operator delete(void*, std::align_val_t) { + if(malloc_hack_2 && p) { + if(getMmapped((uintptr_t)p)) { + printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p); + // Mmaped, do not free... + return; + } + } box_free(p); } EXPORT void my__ZdlPvSt11align_val_tRKSt9nothrow_t(void* p, size_t align, void* n) //operator delete(void*, std::align_val_t, std::nothrow_t const&) { + if(malloc_hack_2 && p) { + if(getMmapped((uintptr_t)p)) { + printf_log(LOG_DEBUG, "%04d|Malloc_Hack_2: not freeing %p\n", GetTID(), p); + // Mmaped, do not free... + return; + } + } box_free(p); } @@ -590,6 +704,8 @@ static void addRelocJmp(void* offs, void* where, size_t size, const char* name) void checkHookedSymbols(lib_t *maplib, elfheader_t* h) { int hooked = 0; + if(box64_malloc_hack==1) + return; for (size_t i=0; i<h->numDynSym && hooked<2; ++i) { const char * symname = h->DynStr+h->DynSym[i].st_name; int bind = ELF64_ST_BIND(h->DynSym[i].st_info); @@ -611,6 +727,8 @@ void checkHookedSymbols(lib_t *maplib, elfheader_t* h) if(hooked<2) return; // only redirect on lib that hooked / redefined the operators printf_log(LOG_INFO, "Redirecting overriden malloc function for %s\n", ElfName(h)); + if(box64_malloc_hack==2) + malloc_hack_2 = 1; for (size_t i=0; i<h->numDynSym; ++i) { const char * symname = h->DynStr+h->DynSym[i].st_name; int bind = ELF64_ST_BIND(h->DynSym[i].st_info); diff --git a/src/tools/rcfile.c b/src/tools/rcfile.c index a1914fab..8a2ac920 100644 --- a/src/tools/rcfile.c +++ b/src/tools/rcfile.c @@ -76,6 +76,7 @@ ENTRYSTRING_(BOX64_BASH, bash) \ ENTRYINT(BOX64_JITGDB, jit_gdb, 0, 2, 2) \ ENTRYBOOL(BOX64_NOSANDBOX, box64_nosandbox) \ ENTRYBOOL(BOX64_EXIT, want_exit) \ +ENTRYINT(BOX64_MALLOC_HACK, box64_malloc_hack, 0, 2, 2) \ #ifdef HAVE_TRACE #define SUPER2() \ diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c index 4f4c208d..1b84ab7b 100755 --- a/src/wrapped/wrappedlibc.c +++ b/src/wrapped/wrappedlibc.c @@ -2425,7 +2425,6 @@ EXPORT int my_readlinkat(x64emu_t* emu, int fd, void* path, void* buf, size_t bu return readlinkat(fd, path, buf, bufsize); } - EXPORT void* my_mmap64(x64emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, int64_t offset) { (void)emu; @@ -2478,8 +2477,9 @@ EXPORT void* my_mmap64(x64emu_t* emu, void *addr, unsigned long length, int prot } } #endif - if(ret!=(void*)-1) - setProtection((uintptr_t)ret, length, prot); + if(ret!=(void*)-1) { + setProtection_mmap((uintptr_t)ret, length, prot); + } return ret; } EXPORT void* my_mmap(x64emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, int64_t offset) __attribute__((alias("my_mmap64"))); @@ -2525,7 +2525,7 @@ EXPORT void* my_mremap(x64emu_t* emu, void* old_addr, size_t old_size, size_t ne cleanDBFromAddressRange((uintptr_t)old_addr, old_size, 1); #endif } - setProtection((uintptr_t)ret, new_size, prot); // should copy the protection from old block + setProtection_mmap((uintptr_t)ret, new_size, prot); // should copy the protection from old block #ifdef DYNAREC if(box64_dynarec) addDBFromAddressRange((uintptr_t)ret, new_size); @@ -2544,8 +2544,9 @@ EXPORT int my_munmap(x64emu_t* emu, void* addr, unsigned long length) } #endif int ret = munmap(addr, length); - if(!ret) + if(!ret) { freeProtection((uintptr_t)addr, length); + } return ret; } |