...instead of argv[0], which might or might not contain a valid path to the executable itself. Instead of mangling argv[0], use the same link to find out if we're already running the AVX2 build where supported. Alternatively, we could use execvpe(), but that might result in running a different installed version, in case e.g. the set of binaries is present in both /usr/bin and /usr/local/bin, with both being in $PATH. Reported-by: Wenli Quan <wquan(a)redhat.com> Link: https://bugzilla.redhat.com/show_bug.cgi?id=2101310 Signed-off-by: Stefano Brivio <sbrivio(a)redhat.com> --- arch.c | 25 +++++++++++++++---------- passt.c | 9 ++++++--- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/arch.c b/arch.c index ae21d59..71feda3 100644 --- a/arch.c +++ b/arch.c @@ -14,26 +14,31 @@ #include <limits.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <unistd.h> /** - * arch_avx2_exec() - Run AVX2 build if supported, drop suffix from argv[0] + * arch_avx2_exec() - Switch to AVX2 build if supported * @argv: Arguments from command line */ #ifdef __x86_64__ -static char avx2_path[PATH_MAX]; - void arch_avx2_exec(char **argv) { - char *p = strstr(argv[0], ".avx2"); + char exe[PATH_MAX], new_path[PATH_MAX + sizeof(".avx2")], *p; + + if (readlink("/proc/self/exe", exe, PATH_MAX) < 0) { + perror("readlink /proc/self/exe"); + exit(EXIT_FAILURE); + } + + p = strstr(exe, ".avx2"); + if (p && strlen(p) == strlen(".avx2")) + return; - if (p) { - *p = 0; - } else if (__builtin_cpu_supports("avx2")) { - snprintf(avx2_path, PATH_MAX, "%s.avx2", argv[0]); - argv[0] = avx2_path; - execve(avx2_path, argv, environ); + if (__builtin_cpu_supports("avx2")) { + snprintf(new_path, PATH_MAX + sizeof(".avx2"), "%s.avx2", exe); + execve(new_path, argv, environ); perror("Can't run AVX2 build, using non-AVX2 version"); } } diff --git a/passt.c b/passt.c index dd0229a..56fcf5f 100644 --- a/passt.c +++ b/passt.c @@ -35,6 +35,7 @@ #include <sys/mount.h> #include <netinet/ip.h> #include <net/ethernet.h> +#include <libgen.h> #include <stdlib.h> #include <unistd.h> #include <net/if.h> @@ -283,11 +284,11 @@ int main(int argc, char **argv) { int nfds, i, devnull_fd = -1, pidfile_fd = -1, quit_fd; struct epoll_event events[EPOLL_EVENTS]; + char *log_name, argv0[PATH_MAX], *name; struct ctx c = { 0 }; struct rlimit limit; struct timespec now; struct sigaction sa; - char *log_name; arch_avx2_exec(argv); @@ -304,14 +305,16 @@ int main(int argc, char **argv) if (argc < 1) exit(EXIT_FAILURE); - if (strstr(argv[0], "pasta")) { + strncpy(argv0, argv[0], PATH_MAX - 1); + name = basename(argv0); + if (strstr(name, "pasta")) { sa.sa_handler = pasta_child_handler; sigaction(SIGCHLD, &sa, NULL); signal(SIGPIPE, SIG_IGN); c.mode = MODE_PASTA; log_name = "pasta"; - } else if (strstr(argv[0], "passt")) { + } else if (strstr(name, "passt")) { c.mode = MODE_PASST; log_name = "passt"; } else { -- 2.35.1
On Wed, Jul 13, 2022 at 08:17:09AM +0200, Stefano Brivio wrote:...instead of argv[0], which might or might not contain a valid path to the executable itself. Instead of mangling argv[0], use the same link to find out if we're already running the AVX2 build where supported.Ah.. yeah, I remember seeing that usage of argv[0] and suspecting it might be a problem.Alternatively, we could use execvpe(), but that might result in running a different installed version, in case e.g. the set of binaries is present in both /usr/bin and /usr/local/bin, with both being in $PATH. Reported-by: Wenli Quan <wquan(a)redhat.com> Link: https://bugzilla.redhat.com/show_bug.cgi?id=2101310 Signed-off-by: Stefano Brivio <sbrivio(a)redhat.com>--- arch.c | 25 +++++++++++++++---------- passt.c | 9 ++++++--- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/arch.c b/arch.c index ae21d59..71feda3 100644 --- a/arch.c +++ b/arch.c @@ -14,26 +14,31 @@ #include <limits.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <unistd.h> /** - * arch_avx2_exec() - Run AVX2 build if supported, drop suffix from argv[0] + * arch_avx2_exec() - Switch to AVX2 build if supported * @argv: Arguments from command line */ #ifdef __x86_64__ -static char avx2_path[PATH_MAX]; - void arch_avx2_exec(char **argv) { - char *p = strstr(argv[0], ".avx2"); + char exe[PATH_MAX], new_path[PATH_MAX + sizeof(".avx2")], *p; + + if (readlink("/proc/self/exe", exe, PATH_MAX) < 0) { + perror("readlink /proc/self/exe"); + exit(EXIT_FAILURE); + } + + p = strstr(exe, ".avx2"); + if (p && strlen(p) == strlen(".avx2")) + return; - if (p) { - *p = 0; - } else if (__builtin_cpu_supports("avx2")) { - snprintf(avx2_path, PATH_MAX, "%s.avx2", argv[0]); - argv[0] = avx2_path; - execve(avx2_path, argv, environ); + if (__builtin_cpu_supports("avx2")) { + snprintf(new_path, PATH_MAX + sizeof(".avx2"), "%s.avx2", exe); + execve(new_path, argv, environ); perror("Can't run AVX2 build, using non-AVX2 version"); } } diff --git a/passt.c b/passt.c index dd0229a..56fcf5f 100644 --- a/passt.c +++ b/passt.c @@ -35,6 +35,7 @@ #include <sys/mount.h> #include <netinet/ip.h> #include <net/ethernet.h> +#include <libgen.h> #include <stdlib.h> #include <unistd.h> #include <net/if.h> @@ -283,11 +284,11 @@ int main(int argc, char **argv) { int nfds, i, devnull_fd = -1, pidfile_fd = -1, quit_fd; struct epoll_event events[EPOLL_EVENTS]; + char *log_name, argv0[PATH_MAX], *name; struct ctx c = { 0 }; struct rlimit limit; struct timespec now; struct sigaction sa; - char *log_name; arch_avx2_exec(argv); @@ -304,14 +305,16 @@ int main(int argc, char **argv) if (argc < 1) exit(EXIT_FAILURE); - if (strstr(argv[0], "pasta")) { + strncpy(argv0, argv[0], PATH_MAX - 1); + name = basename(argv0); + if (strstr(name, "pasta")) { sa.sa_handler = pasta_child_handler; sigaction(SIGCHLD, &sa, NULL); signal(SIGPIPE, SIG_IGN); c.mode = MODE_PASTA; log_name = "pasta"; - } else if (strstr(argv[0], "passt")) { + } else if (strstr(name, "passt")) { c.mode = MODE_PASST; log_name = "passt"; } else {-- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson