about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2024-02-16 13:44:54 +0100
committerptitSeb <sebastien.chev@gmail.com>2024-02-16 13:44:54 +0100
commit65f75b0cc0ead29db622afc790b6167c476e4960 (patch)
treef4a2ab63e4f12ba67995a25c029468807d5e83fe /src
parentc50b0ef9e8342b634af873134a52ec3b7b889f42 (diff)
downloadbox64-65f75b0cc0ead29db622afc790b6167c476e4960.tar.gz
box64-65f75b0cc0ead29db622afc790b6167c476e4960.zip
[ELFLOADER] Better handling of STB_GNU_UNIQUE binded symbol (prevent dlclose)
Diffstat (limited to 'src')
-rw-r--r--src/elfs/elfloader.c15
-rw-r--r--src/elfs/elfloader_private.h1
-rw-r--r--src/wrapped/wrappedlibdl.c6
3 files changed, 21 insertions, 1 deletions
diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c
index 9f01f75b..f68658d7 100644
--- a/src/elfs/elfloader.c
+++ b/src/elfs/elfloader.c
@@ -499,6 +499,21 @@ void GrabX64CopyMainElfReloc(elfheader_t* head)
         }
     }
 }
+void CheckGNUUniqueBindings(elfheader_t* head)
+{
+    if(head->rela) {
+        int cnt = head->relasz / head->relaent;
+        Elf64_Rela* rela = (Elf64_Rela *)(head->rela + head->delta);
+        printf_dump(LOG_DEBUG, "Checking for symbol with STB_GNU_UNIQUE bindingsfor %s\n", head->name);
+        for (int i=0; i<cnt; ++i) {
+            int bind = ELF64_ST_BIND(rela[i].r_info);
+            if(bind == STB_GNU_UNIQUE) {
+                head->gnuunique = 1;
+                return; // can stop searching
+            }
+        }
+    }
+}
 
 static elfheader_t* checkElfLib(elfheader_t* h, library_t* lib)
 {
diff --git a/src/elfs/elfloader_private.h b/src/elfs/elfloader_private.h
index 4487e972..91b3b510 100644
--- a/src/elfs/elfloader_private.h
+++ b/src/elfs/elfloader_private.h
@@ -102,6 +102,7 @@ typedef struct elfheader_s {
     int         fini_done;
     int         refcnt;     // ref count for the elf
     int         malloc_hook_2;  // this elf hook malloc, hacking it
+    int         gnuunique;  // set if contains some STB_GNU_UNIQUE binding, preventing dlclose to unload the lib
 
     char*       memory;     // char* and not void* to allow math on memory pointer
     multiblock_t*  multiblocks;
diff --git a/src/wrapped/wrappedlibdl.c b/src/wrapped/wrappedlibdl.c
index f85b007d..b781b9cb 100644
--- a/src/wrapped/wrappedlibdl.c
+++ b/src/wrapped/wrappedlibdl.c
@@ -386,6 +386,7 @@ void* my_dlsym(x64emu_t* emu, void *handle, void *symbol)
     pthread_mutex_unlock(&mutex);
     return (void*)start;
 }
+static int actualy_closing = 0;
 int my_dlclose(x64emu_t* emu, void *handle)
 {
     (void)emu;
@@ -410,7 +411,9 @@ int my_dlclose(x64emu_t* emu, void *handle)
         return -1;
     }
     --dl->dllibs[nlib].count;
-    DecRefCount(&dl->dllibs[nlib].lib, emu);
+    elfheader_t* h = GetElf(dl->dllibs[nlib].lib);
+    if(!h || !h->gnuunique || actualy_closing)
+        DecRefCount(&dl->dllibs[nlib].lib, emu);
     return 0;
 }
 #ifdef ANDROID
@@ -597,6 +600,7 @@ EXPORT int my__dl_find_object(x64emu_t* emu, void* addr, my_dl_find_object_t* re
 void closeAllDLOpenned()
 {
     dlprivate_t *dl = my_context->dlprivate;
+    actualy_closing = 1;
     if(dl) {
         x64emu_t* emu = thread_get_emu();
         for(size_t i=0; i<dl->lib_sz; ++i)