diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2022-10-27 14:04:41 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2022-10-27 14:04:41 +0200 |
| commit | 978256179b9e45094251e79cdcfd6c52d7c9e9e0 (patch) | |
| tree | ed335db81024986a3f1c1a6e358ccd4a8fcb79ee /src | |
| parent | 742af765ba808ca89ac36922ac7fe5dcb5f976a6 (diff) | |
| download | box64-978256179b9e45094251e79cdcfd6c52d7c9e9e0.tar.gz box64-978256179b9e45094251e79cdcfd6c52d7c9e9e0.zip | |
Improved handling of execve and posix_spawn, especialy with arv[0] is not the expected value
Diffstat (limited to 'src')
| -rwxr-xr-x | src/main.c | 24 | ||||
| -rwxr-xr-x | src/wrapped/wrappedlibc.c | 101 |
2 files changed, 77 insertions, 48 deletions
diff --git a/src/main.c b/src/main.c index 4a661e48..2dfc0caf 100755 --- a/src/main.c +++ b/src/main.c @@ -1311,19 +1311,21 @@ int main(int argc, const char **argv, char **env) { } if(!(my_context->fullpath = realpath(my_context->argv[0], NULL))) my_context->fullpath = box_strdup(my_context->argv[0]); - FILE *f = fopen(my_context->argv[0], "rb"); + if(getenv("BOX64_ARG0")) + my_context->argv[0] = box_strdup(getenv("BOX64_ARG0")); + FILE *f = fopen(my_context->fullpath, "rb"); if(!f) { - printf_log(LOG_NONE, "Error: Cannot open %s\n", my_context->argv[0]); + printf_log(LOG_NONE, "Error: Cannot open %s\n", my_context->fullpath); free_contextargv(); FreeBox64Context(&my_context); FreeCollection(&ld_preload); return -1; } - elfheader_t *elf_header = LoadAndCheckElfHeader(f, my_context->argv[0], 1); + elfheader_t *elf_header = LoadAndCheckElfHeader(f, my_context->fullpath, 1); if(!elf_header) { - int x86 = my_context->box86path?FileIsX86ELF(my_context->argv[0]):0; - int script = my_context->bashpath?FileIsShell(my_context->argv[0]):0; - printf_log(LOG_NONE, "Error: reading elf header of %s, try to launch %s instead\n", my_context->argv[0], x86?"using box86":(script?"using bash":"natively")); + int x86 = my_context->box86path?FileIsX86ELF(my_context->fullpath):0; + int script = my_context->bashpath?FileIsShell(my_context->fullpath):0; + printf_log(LOG_NONE, "Error: reading elf header of %s, try to launch %s instead\n", my_context->fullpath, x86?"using box86":(script?"using bash":"natively")); fclose(f); FreeCollection(&ld_preload); int ret; @@ -1355,7 +1357,7 @@ int main(int argc, const char **argv, char **env) { AddElfHeader(my_context, elf_header); if(CalcLoadAddr(elf_header)) { - printf_log(LOG_NONE, "Error: reading elf header of %s\n", my_context->argv[0]); + printf_log(LOG_NONE, "Error: reading elf header of %s\n", my_context->fullpath); fclose(f); free_contextargv(); FreeBox64Context(&my_context); @@ -1364,7 +1366,7 @@ int main(int argc, const char **argv, char **env) { } // allocate memory if(AllocElfMemory(my_context, elf_header, 1)) { - printf_log(LOG_NONE, "Error: allocating memory for elf %s\n", my_context->argv[0]); + printf_log(LOG_NONE, "Error: allocating memory for elf %s\n", my_context->fullpath); fclose(f); free_contextargv(); FreeBox64Context(&my_context); @@ -1373,7 +1375,7 @@ int main(int argc, const char **argv, char **env) { } // Load elf into memory if(LoadElfMemory(f, my_context, elf_header)) { - printf_log(LOG_NONE, "Error: loading in memory elf %s\n", my_context->argv[0]); + printf_log(LOG_NONE, "Error: loading in memory elf %s\n", my_context->fullpath); fclose(f); free_contextargv(); FreeBox64Context(&my_context); @@ -1437,11 +1439,11 @@ int main(int argc, const char **argv, char **env) { #endif // change process name { - char* p = strrchr(my_context->argv[0], '/'); + char* p = strrchr(my_context->fullpath, '/'); if(p) ++p; else - p = my_context->argv[0]; + p = my_context->fullpath; if(prctl(PR_SET_NAME, p)==-1) printf_log(LOG_NONE, "Error setting process name (%s)\n", strerror(errno)); else diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c index 556f8f9f..f5d8c8b2 100755 --- a/src/wrapped/wrappedlibc.c +++ b/src/wrapped/wrappedlibc.c @@ -1711,7 +1711,14 @@ EXPORT int32_t my_execv(x64emu_t* emu, const char* path, char* const argv[]) newargv[0] = x86?emu->context->box86path:emu->context->box64path; if(script) newargv[1] = emu->context->bashpath; // script needs to be launched with bash memcpy(newargv+toadd, argv+skip_first, sizeof(char*)*(n+toadd)); - if(self) newargv[1] = emu->context->fullpath; else newargv[toadd] = skip_first?argv[skip_first]:path; + if(self) + newargv[1] = emu->context->fullpath; + else { + // TODO check if envp is not environ and add the value on a copy + if(strcmp(newargv[toadd], skip_first?argv[skip_first]:path)) + setenv(x86?"BOX86_ARG0":"BOX64_ARG0", newargv[toadd], 1); + newargv[toadd] = skip_first?argv[skip_first]:path; + } printf_log(LOG_DEBUG, " => execv(\"%s\", %p [\"%s\", \"%s\", \"%s\"...:%d])\n", newargv[0], newargv, newargv[0], n?newargv[1]:"", (n>1)?newargv[2]:"",n); char** envv = NULL; if(my_environ!=my_context->envv) envv = my_environ; @@ -1749,15 +1756,20 @@ EXPORT int32_t my_execve(x64emu_t* emu, const char* path, char* const argv[], ch int n=skip_first; while(argv[n]) ++n; int toadd = script?2:1; - const char** newargv = (const char**)box_calloc(n+1+toadd, sizeof(char*)); + const char** newargv = (const char**)alloca((n+1+toadd-skip_first)*sizeof(char*)); + memset(newargv, 0, (n+1+toadd)*sizeof(char*)); newargv[0] = x86?emu->context->box86path:emu->context->box64path; if(script) newargv[1] = emu->context->bashpath; // script needs to be launched with bash - memcpy(newargv+toadd, argv+skip_first, sizeof(char*)*(n+1)); + memcpy(newargv+toadd, argv+skip_first, sizeof(char*)*(n+1-skip_first)); if(self) newargv[toadd] = emu->context->fullpath; - else newargv[toadd] = path; - printf_log(LOG_DEBUG, " => execve(\"%s\", %p [\"%s\", \"%s\", \"%s\"...:%d], %p)\n", newargv[0], newargv, newargv[0], (n+toadd)?newargv[1]:"", ((n+toadd)>1)?newargv[2]:"",n, envp); + else { + // TODO check if envp is not environ and add the value on a copy + if(strcmp(newargv[toadd], path)) + setenv(x86?"BOX86_ARG0":"BOX64_ARG0", newargv[toadd], 1); + newargv[toadd] = path; + } + printf_log(LOG_DEBUG, " => execve(\"%s\", %p [\"%s\", \"%s\", \"%s\"...:%d], %p)\n", newargv[0], newargv, newargv[0], (n+toadd-skip_first)?newargv[1]:"", ((n+toadd-skip_first)>1)?newargv[2]:"",n, envp); int ret = execve(newargv[0], (char* const*)newargv, envp); - box_free(newargv); return ret; } #endif @@ -1775,8 +1787,8 @@ EXPORT int32_t my_execve(x64emu_t* emu, const char* path, char* const argv[], ch // special case of a bash script shell running grep on cpuinfo to extract capacities... int n=0; while(argv[n]) ++n; - const char** newargv = (const char**)box_calloc(n+1, sizeof(char*)); - memcpy(newargv, argv, sizeof(char*)*(n)); + const char** newargv = (const char**)alloca((n+1)*sizeof(char*)); + memcpy(newargv, argv, sizeof(char*)*(n+1)); // create a dummy cpuinfo in temp (that will stay there, sorry) const char* tmpdir = GetTmpDir(); char template[100] = {0}; @@ -1792,7 +1804,6 @@ EXPORT int32_t my_execve(x64emu_t* emu, const char* path, char* const argv[], ch newargv[2] = cpuinfo_file; printf_log(LOG_DEBUG, " => execve(\"%s\", %p [\"%s\", \"%s\", \"%s\"...:%d], %p)\n", path, newargv, newargv[0], newargv[1], newargv[2],n, envp); int ret = execve(path, (char* const*)newargv, envp); - box_free(newargv); return ret; } #endif @@ -1816,13 +1827,21 @@ EXPORT int32_t my_execvp(x64emu_t* emu, const char* path, char* const argv[]) int i=0; while(argv[i]) ++i; int toadd = script?2:1; - char** newargv = (char**)box_calloc(i+toadd+1, sizeof(char*)); + char** newargv = (char**)alloca((i+toadd+1)*sizeof(char*)); + memset(newargv, 0, (i+toadd+1)*sizeof(char*)); newargv[0] = x86?emu->context->box86path:emu->context->box64path; if(script) newargv[1] = emu->context->bashpath; // script needs to be launched with bash for (int j=0; j<i; ++j) newargv[j+toadd] = argv[j]; if(self) newargv[1] = emu->context->fullpath; - if(script) newargv[2] = fullpath; + //else if(script) newargv[2] = fullpath; + else { + // TODO check if envp is not environ and add the value on a copy + if(strcmp(newargv[toadd], path)) + setenv(x86?"BOX86_ARG0":"BOX64_ARG0", newargv[toadd], 1); + newargv[toadd] = fullpath; + } + printf_log(LOG_DEBUG, " => execvp(\"%s\", %p [\"%s\", \"%s\"...:%d])\n", newargv[0], newargv, newargv[1], i?newargv[2]:"", i); char** envv = NULL; if(my_environ!=my_context->envv) envv = my_environ; @@ -1833,8 +1852,7 @@ EXPORT int32_t my_execvp(x64emu_t* emu, const char* path, char* const argv[]) ret = execvpe(newargv[0], newargv, envv); else ret = execvp(newargv[0], newargv); - box_free(newargv); - box_free(fullpath); + box_free(fullpath); return ret; } if((!strcmp(path + strlen(path) - strlen("/uname"), "/uname") || !strcmp(path, "uname")) @@ -1921,29 +1939,35 @@ EXPORT int32_t my_posix_spawn(x64emu_t* emu, pid_t* pid, const char* fullpath, int x64 = FileIsX64ELF(fullpath); int x86 = my_context->box86path?FileIsX86ELF(fullpath):0; int script = (my_context->bashpath && FileIsShell(fullpath))?1:0; - printf_log(/*LOG_DEBUG*/LOG_INFO, "posix_spawn(%p, \"%s\", %p, %p, %p, %p), IsX64=%d, IsX86=%d IsScript=%d\n", pid, fullpath, actions, attrp, argv, envp, x64, x86, script); + int ret; + printf_log(/*LOG_DEBUG*/LOG_INFO, "posix_spawn(%p, \"%s\", %p, %p, %p[\"%s\", \"%s\", ...], %p), IsX64=%d, IsX86=%d IsScript=%d %s\n", pid, fullpath, actions, attrp, argv, argv[0], argv[1]?argv[1]:"", envp, x64, x86, script, (envp==my_context->envv)?"envp is context->envv":""); // hack to update the environ var if needed - /*if(envp == my_context->envv && environ) { + if(envp == my_context->envv && environ) { envp = environ; - }*/ + } if (x64 || x86 || script || self) { int n=1; while(argv[n]) ++n; int toadd = script?2:1; - const char** newargv = (const char**)box_calloc(n+1+toadd, sizeof(char*)); + const char** newargv = (const char**)alloca((n+1+toadd)*sizeof(char*)); + memset(newargv, 0, (n+1+toadd)*sizeof(char*)); newargv[0] = x86?emu->context->box86path:emu->context->box64path; if(script) newargv[1] = emu->context->bashpath; // script needs to be launched with bash - memcpy(newargv+toadd, argv+1, sizeof(char*)*(n+1)); + memcpy(newargv+toadd, argv, (n+1)*sizeof(char*)); if(self) newargv[toadd] = emu->context->fullpath; - else newargv[toadd] = fullpath; - printf_log(/*LOG_DEBUG*/LOG_INFO, " => posix_spawn(%p, \"%s\", %p, %p, %p [\"%s\", \"%s\", \"%s\"...:%d], %p)\n", pid, newargv[0], actions, attrp, newargv, newargv[0], newargv[1], n?newargv[2]:"", n, envp); - int ret = posix_spawn(pid, newargv[0], actions, attrp, (char* const*)newargv, envp); + else { + // TODO check if envp is not environ and add the value on a copy + if(strcmp(newargv[toadd], fullpath)) + setenv(x86?"BOX86_ARG0":"BOX64_ARG0", newargv[toadd], 1); + newargv[toadd] = fullpath; + } + printf_log(/*LOG_DEBUG*/LOG_INFO, " => posix_spawn(%p, \"%s\", %p, %p, %p [\"%s\", \"%s\", \"%s\"...:%d], %p)\n", pid, newargv[0], actions, attrp, newargv, newargv[0], newargv[1], newargv[2]?newargv[2]:"", n, envp); + ret = posix_spawn(pid, newargv[0], actions, attrp, (char* const*)newargv, envp); printf_log(/*LOG_DEBUG*/LOG_INFO, "posix_spawn returned %d\n", ret); //box_free(newargv); - return ret; - } - // fullpath is gone, so the search will only be on PATH, not on BOX64_PATH (is that an issue?) - return posix_spawn(pid, fullpath, actions, attrp, argv, envp); + } else + ret = posix_spawn(pid, fullpath, actions, attrp, argv, envp); + return ret; } // execvp should use PATH to search for the program first @@ -1960,21 +1984,24 @@ EXPORT int32_t my_posix_spawnp(x64emu_t* emu, pid_t* pid, const char* path, int ret; printf_log(/*LOG_DEBUG*/LOG_INFO, "posix_spawnp(%p, \"%s\", %p, %p, %p, %p), IsX86=%d / fullpath=\"%s\"\n", pid, path, actions, attrp, argv, envp, x64, fullpath); if (x64 || x86 || script || self) { - // count argv... - int i=0; - while(argv[i]) ++i; + int n=1; + while(argv[n]) ++n; int toadd = script?2:1; - char** newargv = (char**)box_calloc(i+toadd+1, sizeof(char*)); + const char** newargv = (const char**)alloca((n+1+toadd)*sizeof(char*)); + memset(newargv, 0, (n+1+toadd)*sizeof(char*)); newargv[0] = x86?emu->context->box86path:emu->context->box64path; if(script) newargv[1] = emu->context->bashpath; // script needs to be launched with bash - for (int j=0; j<i; ++j) - newargv[j+1] = argv[j]; - if(self) newargv[1] = emu->context->fullpath; - else newargv[1+toadd] = (char*)path; - printf_log(/*LOG_DEBUG*/LOG_INFO, " => posix_spawnp(%p, \"%s\", %p, %p, %p [\"%s\", \"%s\"...:%d], %p)\n", pid, newargv[0], actions, attrp, newargv, newargv[1], i?newargv[2]:"", i, envp); - ret = posix_spawnp(pid, newargv[0], actions, attrp, newargv, envp); - printf_log(/*LOG_DEBUG*/LOG_INFO, "posix_spawnp returned %d\n", ret); - box_free(fullpath); + memcpy(newargv+toadd, argv, (n+1)*sizeof(char*)); + if(self) newargv[toadd] = emu->context->fullpath; + else { + // TODO check if envp is not environ and add the value on a copy + if(strcmp(newargv[toadd], fullpath)) + setenv(x86?"BOX86_ARG0":"BOX64_ARG0", newargv[toadd], 1); + newargv[toadd] = fullpath; + } + printf_log(/*LOG_DEBUG*/LOG_INFO, " => posix_spawn(%p, \"%s\", %p, %p, %p [\"%s\", \"%s\", \"%s\"...:%d], %p)\n", pid, newargv[0], actions, attrp, newargv, newargv[0], newargv[1], newargv[2]?newargv[2]:"", n, envp); + ret = posix_spawn(pid, newargv[0], actions, attrp, (char* const*)newargv, envp); + printf_log(/*LOG_DEBUG*/LOG_INFO, "posix_spawn returned %d\n", ret); //box_free(newargv); } else ret = posix_spawnp(pid, path, actions, attrp, argv, envp); |