about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2022-10-27 14:04:41 +0200
committerptitSeb <sebastien.chev@gmail.com>2022-10-27 14:04:41 +0200
commit978256179b9e45094251e79cdcfd6c52d7c9e9e0 (patch)
treeed335db81024986a3f1c1a6e358ccd4a8fcb79ee /src
parent742af765ba808ca89ac36922ac7fe5dcb5f976a6 (diff)
downloadbox64-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-xsrc/main.c24
-rwxr-xr-xsrc/wrapped/wrappedlibc.c101
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);