diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2023-07-09 12:38:48 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2023-07-09 12:38:48 +0200 |
| commit | dabbca767f9de4fc4cf68252037de3061592eae2 (patch) | |
| tree | bfc1dadad814a82a155c0c374097177b94154beb /src | |
| parent | ca9bc1361943575724eb5152798aa208ed5eed6c (diff) | |
| download | box64-dabbca767f9de4fc4cf68252037de3061592eae2.tar.gz box64-dabbca767f9de4fc4cf68252037de3061592eae2.zip | |
[ELFLOADER] Added a check if lib version is compatible with what the elf loading it wants (helps Linux games on Steam)
Diffstat (limited to 'src')
| -rwxr-xr-x | src/elfs/elfloader.c | 19 | ||||
| -rwxr-xr-x | src/elfs/elfparser.c | 52 | ||||
| -rwxr-xr-x | src/include/elfloader.h | 3 | ||||
| -rwxr-xr-x | src/include/librarian.h | 2 | ||||
| -rwxr-xr-x | src/include/library.h | 2 | ||||
| -rwxr-xr-x | src/librarian/librarian.c | 16 | ||||
| -rwxr-xr-x | src/librarian/library.c | 24 | ||||
| -rwxr-xr-x | src/main.c | 5 | ||||
| -rwxr-xr-x | src/wrapped/wrappedlibdl.c | 2 |
9 files changed, 91 insertions, 34 deletions
diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c index 4caa07ce..7977b592 100755 --- a/src/elfs/elfloader.c +++ b/src/elfs/elfloader.c @@ -374,6 +374,23 @@ int LoadElfMemory(FILE* f, box64context_t* context, elfheader_t* head) return 0; } +int isElfHasNeededVer(elfheader_t* head, const char* libname, elfheader_t* verneeded) +{ + if(!verneeded || !head) + return 1; + if(!head->VerDef || !verneeded->VerNeed) + return 1; + int cnt = GetNeededVersionCnt(verneeded, libname); + for (int i=0; i<cnt; ++i) { + const char* vername = GetNeededVersionString(verneeded, libname, i); + if(vername && !GetVersionIndice(head, vername)) { + printf_log(/*LOG_DEBUG*/LOG_INFO, "Discarding %s for missing version %s\n", head->path, vername); + return 0; // missing version + } + } + return 1; +} + int ReloadElfMemory(FILE* f, box64context_t* context, elfheader_t* head) { (void)context; @@ -1201,7 +1218,7 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, box64c h->needed->names[j++] = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val; // TODO: Add LD_LIBRARY_PATH and RPATH handling - if(AddNeededLib(maplib, local, bindnow, h->needed, box64, emu)) { + if(AddNeededLib(maplib, local, bindnow, h->needed, h, box64, emu)) { printf_log(LOG_INFO, "Error loading one of needed lib\n"); if(!allow_missing_libs) return 1; //error... diff --git a/src/elfs/elfparser.c b/src/elfs/elfparser.c index 7b83e07e..1701378f 100755 --- a/src/elfs/elfparser.c +++ b/src/elfs/elfparser.c @@ -416,18 +416,6 @@ int GetVersionIndice(elfheader_t* h, const char* vername) { if(!vername) return 0; - if(h->VerNeed) { - Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta); - while(ver) { - Elf64_Vernaux *aux = (Elf64_Vernaux*)((uintptr_t)ver + ver->vn_aux); - for(int j=0; j<ver->vn_cnt; ++j) { - if(!strcmp(h->DynStr+aux->vna_name, vername)) - return aux->vna_other; - aux = (Elf64_Vernaux*)((uintptr_t)aux + aux->vna_next); - } - ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL; - } - } if(h->VerDef) { Elf64_Verdef *def = (Elf64_Verdef*)((uintptr_t)h->VerDef + h->delta); while(def) { @@ -438,4 +426,44 @@ int GetVersionIndice(elfheader_t* h, const char* vername) } } return 0; +} + +int GetNeededVersionCnt(elfheader_t* h, const char* libname) +{ + if(!libname) + return 0; + if(h->VerNeed) { + Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta); + while(ver) { + char *filename = h->DynStr + ver->vn_file; + Elf64_Vernaux *aux = (Elf64_Vernaux*)((uintptr_t)ver + ver->vn_aux); + if(!strcmp(filename, libname)) + return ver->vn_cnt; + ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL; + } + } + return 0; +} + +const char* GetNeededVersionString(elfheader_t* h, const char* libname, int idx) +{ + if(!libname) + return 0; + if(h->VerNeed) { + Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta); + while(ver) { + char *filename = h->DynStr + ver->vn_file; + Elf64_Vernaux *aux = (Elf64_Vernaux*)((uintptr_t)ver + ver->vn_aux); + if(!strcmp(filename, libname)) { + for(int j=0; j<ver->vn_cnt; ++j) { + if(j==idx) + return h->DynStr+aux->vna_name; + aux = (Elf64_Vernaux*)((uintptr_t)aux + aux->vna_next); + } + return NULL; // idx out of bound, return NULL... + } + ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL; + } + } + return NULL; } \ No newline at end of file diff --git a/src/include/elfloader.h b/src/include/elfloader.h index d5b54145..ca8839df 100755 --- a/src/include/elfloader.h +++ b/src/include/elfloader.h @@ -25,6 +25,7 @@ int CalcLoadAddr(elfheader_t* head); int AllocElfMemory(box64context_t* context, elfheader_t* head, int mainbin); void FreeElfMemory(elfheader_t* head); int LoadElfMemory(FILE* f, box64context_t* context, elfheader_t* head); +int isElfHasNeededVer(elfheader_t* head, const char* libname, elfheader_t* verneeded); int ReloadElfMemory(FILE* f, box64context_t* context, elfheader_t* head); int RelocateElf(lib_t *maplib, lib_t* local_maplib, int bindnow, elfheader_t* head); int RelocateElfPlt(lib_t *maplib, lib_t* local_maplib, int bindnow, elfheader_t* head); @@ -64,6 +65,8 @@ const char* GetParentSymbolVersion(elfheader_t* h, int index); const char* VersionedName(const char* name, int ver, const char* vername); int SameVersionedSymbol(const char* name1, int ver1, const char* vername1, const char* name2, int ver2, const char* vername2); int GetVersionIndice(elfheader_t* h, const char* vername); +int GetNeededVersionCnt(elfheader_t* h, const char* libname); +const char* GetNeededVersionString(elfheader_t* h, const char* libname, int idx); kh_mapsymbols_t* GetMapSymbols(elfheader_t* h); kh_mapsymbols_t* GetWeakSymbols(elfheader_t* h); diff --git a/src/include/librarian.h b/src/include/librarian.h index c05ce963..80e108ca 100755 --- a/src/include/librarian.h +++ b/src/include/librarian.h @@ -21,7 +21,7 @@ void FreeDLPrivate(dlprivate_t **lib); box64context_t* GetLibrarianContext(lib_t* maplib); kh_mapsymbols_t* GetGlobalData(lib_t* maplib); -int AddNeededLib(lib_t* maplib, int local, int bindnow, needed_libs_t* needed, box64context_t* box64, x64emu_t* emu); // 0=success, 1=error +int AddNeededLib(lib_t* maplib, int local, int bindnow, needed_libs_t* needed, elfheader_t* verneeded, box64context_t* box64, x64emu_t* emu); // 0=success, 1=error void RemoveNeededLib(lib_t* maplib, int local, needed_libs_t* needed, box64context_t* box64, x64emu_t* emu); library_t* GetLibMapLib(lib_t* maplib, const char* name); library_t* GetLibInternal(const char* name); diff --git a/src/include/library.h b/src/include/library.h index ff48b691..b08927e0 100755 --- a/src/include/library.h +++ b/src/include/library.h @@ -15,7 +15,7 @@ typedef struct elfheader_s elfheader_t; #define LIB_EMULATED 1 #define LIB_UNNKNOW -1 -library_t *NewLibrary(const char* path, box64context_t* box64); +library_t *NewLibrary(const char* path, box64context_t* box64, elfheader_t* verneeded); int AddSymbolsLibrary(lib_t* maplib, library_t* lib, x64emu_t* emu); int FinalizeLibrary(library_t* lib, lib_t* local_maplib, int bindnow, x64emu_t* emu); diff --git a/src/librarian/librarian.c b/src/librarian/librarian.c index d9f20a9a..8ed3fe8b 100755 --- a/src/librarian/librarian.c +++ b/src/librarian/librarian.c @@ -177,7 +177,7 @@ int isLibLocal(library_t* lib) return libraryInMapLib(my_context->local_maplib, lib); } -int AddNeededLib_add(lib_t* maplib, int local, needed_libs_t* needed, int n, box64context_t* box64, x64emu_t* emu) +static int AddNeededLib_add(lib_t* maplib, int local, needed_libs_t* needed, int n, elfheader_t* verneeded, box64context_t* box64, x64emu_t* emu) { const char* path = needed->names[n]; printf_log(LOG_DEBUG, "Trying to add \"%s\" to maplib%s\n", path, local?" (local)":""); @@ -213,7 +213,7 @@ int AddNeededLib_add(lib_t* maplib, int local, needed_libs_t* needed, int n, box return 0; } // load a new one - needed->libs[n] = lib = NewLibrary(path, box64); + needed->libs[n] = lib = NewLibrary(path, box64, verneeded); if(!lib) { printf_log(LOG_DEBUG, "Faillure to create lib => fail\n"); return 1; //Error @@ -257,7 +257,7 @@ int AddNeededLib_add(lib_t* maplib, int local, needed_libs_t* needed, int n, box return 0; } -int AddNeededLib_init(lib_t* maplib, int local, int bindnow, library_t* lib, box64context_t* box64, x64emu_t* emu) +int AddNeededLib_init(lib_t* maplib, int local, int bindnow, library_t* lib, elfheader_t* verneeded, box64context_t* box64, x64emu_t* emu) { if(!lib) // no lib, error is already detected, no need to return a new one return 0; @@ -283,7 +283,7 @@ int AddNeededLib_init(lib_t* maplib, int local, int bindnow, library_t* lib, box tmp.size = tmp.cap = 1; tmp.names = names; tmp.libs = libs; - AddNeededLib(maplib, 0, 0, &tmp, box64, emu); + AddNeededLib(maplib, 0, 0, &tmp, verneeded, box64, emu); } if(!strcmp(GetNameLib(lib), "libmss.so.6")) { char* names[] = {"libSDL-1.2.so.0", "libdl.so.2"}; // TODO: they will never be uninit... @@ -292,7 +292,7 @@ int AddNeededLib_init(lib_t* maplib, int local, int bindnow, library_t* lib, box tmp.size = tmp.cap = 2; tmp.names = names; tmp.libs = libs; - AddNeededLib(maplib, 0, 0, &tmp, box64, emu); + AddNeededLib(maplib, 0, 0, &tmp, verneeded, box64, emu); } // finalize the lib @@ -318,7 +318,7 @@ void AddNeededLib_remove(lib_t* maplib, int local, library_t** lib, box64context } EXPORTDYN -int AddNeededLib(lib_t* maplib, int local, int bindnow, needed_libs_t* needed, box64context_t* box64, x64emu_t* emu) +int AddNeededLib(lib_t* maplib, int local, int bindnow, needed_libs_t* needed, elfheader_t* verneeded, box64context_t* box64, x64emu_t* emu) { if(!needed) // no needed libs, no problems return 0; @@ -326,7 +326,7 @@ int AddNeededLib(lib_t* maplib, int local, int bindnow, needed_libs_t* needed, b int ret = 0; // Add libs and symbol for(int i=0; i<needed->size; ++i) { - if(AddNeededLib_add(maplib, local, needed, i, box64, emu)) { + if(AddNeededLib_add(maplib, local, needed, i, verneeded, box64, emu)) { printf_log(strchr(needed->names[i],'/')?LOG_DEBUG:LOG_INFO, "Error loading needed lib %s\n", needed->names[i]); ret = 1; } @@ -337,7 +337,7 @@ int AddNeededLib(lib_t* maplib, int local, int bindnow, needed_libs_t* needed, b } // add dependant libs and init them for (int i=0; i<needed->size; ++i) - if(AddNeededLib_init(maplib, local, bindnow, needed->libs[i], box64, emu)) { + if(AddNeededLib_init(maplib, local, bindnow, needed->libs[i], verneeded, box64, emu)) { printf_log(LOG_INFO, "Error initializing needed lib %s\n", needed->names[i]); if(!allow_missing_libs) ret = 1; } diff --git a/src/librarian/library.c b/src/librarian/library.c index 9b2bb997..b3bec1b4 100755 --- a/src/librarian/library.c +++ b/src/librarian/library.c @@ -217,7 +217,7 @@ static void initWrappedLib(library_t *lib, box64context_t* context) { lib->type = LIB_WRAPPED; lib->w.refcnt = 1; // Call librarian to load all dependant elf - if(AddNeededLib(context->maplib, 0, 0, lib->w.needed, context, thread_get_emu())) { + if(AddNeededLib(context->maplib, 0, 0, lib->w.needed, NULL, context, thread_get_emu())) { printf_log(LOG_NONE, "Error: loading a needed libs in elf %s\n", lib->name); return; } @@ -240,7 +240,7 @@ static void initWrappedLib(library_t *lib, box64context_t* context) { } } -static int loadEmulatedLib(const char* libname, library_t *lib, box64context_t* context) +static int loadEmulatedLib(const char* libname, library_t *lib, box64context_t* context, elfheader_t* verneeded) { if(FileExist(libname, IS_FILE)) { @@ -255,28 +255,36 @@ static int loadEmulatedLib(const char* libname, library_t *lib, box64context_t* fclose(f); return 0; } - int mainelf = AddElfHeader(context, elf_header); if(CalcLoadAddr(elf_header)) { printf_log(LOG_NONE, "Error: reading elf header of %s\n", libname); + FreeElfHeader(&elf_header); fclose(f); return 0; } // allocate memory if(AllocElfMemory(context, elf_header, 0)) { printf_log(LOG_NONE, "Error: allocating memory for elf %s\n", libname); + FreeElfHeader(&elf_header); fclose(f); return 0; } // Load elf into memory if(LoadElfMemory(f, context, elf_header)) { printf_log(LOG_NONE, "Error: loading in memory elf %s\n", libname); + FreeElfHeader(&elf_header); fclose(f); return 0; } // can close the file now fclose(f); + if(verneeded && !isElfHasNeededVer(elf_header, lib->name, verneeded)) { + // incompatible, discard and continue the search + FreeElfHeader(&elf_header); + return 0; + } + int mainelf = AddElfHeader(context, elf_header); ElfAttachLib(elf_header, lib); lib->type = LIB_EMULATED; @@ -316,13 +324,13 @@ static int loadEmulatedLib(const char* libname, library_t *lib, box64context_t* return 0; } -static void initEmulatedLib(const char* path, library_t *lib, box64context_t* context) +static void initEmulatedLib(const char* path, library_t *lib, box64context_t* context, elfheader_t* verneeded) { char libname[MAX_PATH]; strcpy(libname, path); int found = FileIsX64ELF(libname); if(found) - if(loadEmulatedLib(libname, lib, context)) + if(loadEmulatedLib(libname, lib, context, verneeded)) return; if(!strchr(path, '/')) for(int i=0; i<context->box64_ld_lib.size; ++i) @@ -330,7 +338,7 @@ static void initEmulatedLib(const char* path, library_t *lib, box64context_t* co strcpy(libname, context->box64_ld_lib.paths[i]); strcat(libname, path); if(FileIsX64ELF(libname)) - if(loadEmulatedLib(libname, lib, context)) + if(loadEmulatedLib(libname, lib, context, verneeded)) return; } } @@ -353,7 +361,7 @@ static int isEssentialLib(const char* name) { return 0; } -library_t *NewLibrary(const char* path, box64context_t* context) +library_t *NewLibrary(const char* path, box64context_t* context, elfheader_t* verneeded) { printf_log(LOG_DEBUG, "Trying to load \"%s\"\n", path); library_t *lib = (library_t*)box_calloc(1, sizeof(library_t)); @@ -399,7 +407,7 @@ library_t *NewLibrary(const char* path, box64context_t* context) initWrappedLib(lib, context); // then look for a native one if(lib->type==LIB_UNNKNOW) - initEmulatedLib(path, lib, context); + initEmulatedLib(path, lib, context, verneeded); // still not loaded but notwrapped indicated: use wrapped... if(lib->type==LIB_UNNKNOW && notwrapped && !precise) initWrappedLib(lib, context); diff --git a/src/main.c b/src/main.c index e06cd2ad..00218c3d 100755 --- a/src/main.c +++ b/src/main.c @@ -917,7 +917,7 @@ int GatherEnv(char*** dest, char** env, char* prog) (*dest)[idx++] = box_strdup("BOX64_PATH=.:bin"); } if(!ld_path) { - (*dest)[idx++] = box_strdup("BOX64_LD_LIBRARY_PATH=.:lib:lib64"); + (*dest)[idx++] = box_strdup("BOX64_LD_LIBRARY_PATH=.:lib:lib64:x86_64:bin64:libs64"); } // add "_=prog" at the end... if(prog) { @@ -1045,6 +1045,7 @@ void LoadEnvVars(box64context_t *context) AddPath("libcrypto.so.1", &context->box64_emulated_libs, 0); AddPath("libcrypto.so.1.0.0", &context->box64_emulated_libs, 0); AddPath("libunwind.so.8", &context->box64_emulated_libs, 0); + AddPath("libpng12.so.0", &context->box64_emulated_libs, 0); if(getenv("BOX64_SSE_FLUSHTO0")) { if (strcmp(getenv("BOX64_SSE_FLUSHTO0"), "1")==0) { @@ -1744,7 +1745,7 @@ int main(int argc, const char **argv, char **env) { for(int i=0; i<ld_preload.size; ++i) { needed_libs_t* tmp = new_neededlib(1); tmp->names[0] = ld_preload.paths[i]; - if(AddNeededLib(my_context->maplib, 0, 0, tmp, my_context, emu)) { + if(AddNeededLib(my_context->maplib, 0, 0, tmp, elf_header, my_context, emu)) { printf_log(LOG_INFO, "Warning, cannot pre-load of %s\n", tmp->names[0]); RemoveNeededLib(my_context->maplib, 0, tmp, my_context, emu); } else { diff --git a/src/wrapped/wrappedlibdl.c b/src/wrapped/wrappedlibdl.c index c6787525..47c47c6b 100755 --- a/src/wrapped/wrappedlibdl.c +++ b/src/wrapped/wrappedlibdl.c @@ -177,7 +177,7 @@ void* my_dlopen(x64emu_t* emu, void *filename, int flag) int bindnow = (!box64_musl && (flag&0x2))?1:0; needed_libs_t *tmp = new_neededlib(1); tmp->names[0] = rfilename; - if(AddNeededLib(NULL, is_local, bindnow, tmp, my_context, emu)) { + if(AddNeededLib(NULL, is_local, bindnow, tmp, NULL, my_context, emu)) { printf_dlsym(strchr(rfilename,'/')?LOG_DEBUG:LOG_INFO, "Warning: Cannot dlopen(\"%s\"/%p, %X)\n", rfilename, filename, flag); if(!dl->last_error) dl->last_error = box_malloc(129); |