about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2023-02-18 15:06:40 +0100
committerptitSeb <sebastien.chev@gmail.com>2023-02-18 15:06:40 +0100
commit9705d5e38bdf4ec72daf480de0830dfde6e33a70 (patch)
tree3c64f69ae2c5569bfe0fa91f321149ce49991c02 /src
parent2e59b56f1691227e4a93ac1c2dd844adcc6334cd (diff)
downloadbox64-9705d5e38bdf4ec72daf480de0830dfde6e33a70.tar.gz
box64-9705d5e38bdf4ec72daf480de0830dfde6e33a70.zip
Preliminary work to get steamwebhelper working
Diffstat (limited to 'src')
-rw-r--r--src/custommem.c36
-rw-r--r--src/include/custommem.h6
-rwxr-xr-xsrc/include/debug.h1
-rwxr-xr-xsrc/libtools/signals.c5
-rwxr-xr-xsrc/main.c14
-rw-r--r--src/mallochook.c118
-rw-r--r--src/tools/rcfile.c1
-rwxr-xr-xsrc/wrapped/wrappedlibc.c11
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;
 }