mirror of
https://github.com/qemu/qemu.git
synced 2026-07-08 17:46:17 +00:00
linux-user: Fix AT_EXECFN in AUXV for symlinked programs
The AT_EXECFN entry in AUXV needs to keep the value which was used when the program was started. Especially for symlinked programs qemu should not try to resolve the realpath. Here is a reproducer: (arm64-chroot)root@p100:/# cd /usr/bin (arm64-chroot)root@p100:/usr/bin# ln -s echo testprog (arm64-chroot)root@p100:/usr/bin# LD_SHOW_AUXV=1 ./testprog | grep AT_EXECFN AT_EXECFN: ./testprog In this example, "./testprog" is the correct output, and not "/usr/bin/echo". This patch fixes parts of commit258bec39("linux-user: Fix access to /proc/self/exe"). Fixes:258bec39("linux-user: Fix access to /proc/self/exe") Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3379 Signed-off-by: Helge Deller <deller@gmx.de>
This commit is contained in:
@@ -772,8 +772,10 @@ int main(int argc, char **argv, char **envp)
|
||||
}
|
||||
|
||||
/* Resolve executable file name to full path name */
|
||||
if (realpath(exec_path, real_exec_path)) {
|
||||
exec_path = real_exec_path;
|
||||
/* Keep how we started the program in exec_path, e.g. "./my_program" */
|
||||
/* Store real path in real_exec_path, e.g. "/usr/local/bin/my_program" */
|
||||
if (!realpath(exec_path, real_exec_path)) {
|
||||
printf("Could not resolve %s\n", exec_path);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -8790,9 +8790,9 @@ static int maybe_do_fake_open(CPUArchState *cpu_env, int dirfd,
|
||||
return -1;
|
||||
}
|
||||
if (safe) {
|
||||
return safe_openat(dirfd, exec_path, flags, mode);
|
||||
return safe_openat(dirfd, real_exec_path, flags, mode);
|
||||
} else {
|
||||
return openat(dirfd, exec_path, flags, mode);
|
||||
return openat(dirfd, real_exec_path, flags, mode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8929,9 +8929,9 @@ ssize_t do_guest_readlink(const char *pathname, char *buf, size_t bufsiz)
|
||||
* Don't worry about sign mismatch as earlier mapping
|
||||
* logic would have thrown a bad address error.
|
||||
*/
|
||||
ret = MIN(strlen(exec_path), bufsiz);
|
||||
ret = MIN(strlen(real_exec_path), bufsiz);
|
||||
/* We cannot NUL terminate the string. */
|
||||
memcpy(buf, exec_path, ret);
|
||||
memcpy(buf, real_exec_path, ret);
|
||||
} else {
|
||||
ret = readlink(path(pathname), buf, bufsiz);
|
||||
}
|
||||
@@ -9022,7 +9022,7 @@ static int do_execv(CPUArchState *cpu_env, int dirfd,
|
||||
|
||||
const char *exe = p;
|
||||
if (is_proc_myself(p, "exe")) {
|
||||
exe = exec_path;
|
||||
exe = real_exec_path;
|
||||
}
|
||||
ret = is_execveat
|
||||
? safe_execveat(dirfd, exe, argp, envp, flags)
|
||||
@@ -11033,9 +11033,9 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
|
||||
* Don't worry about sign mismatch as earlier mapping
|
||||
* logic would have thrown a bad address error.
|
||||
*/
|
||||
ret = MIN(strlen(exec_path), arg4);
|
||||
ret = MIN(strlen(real_exec_path), arg4);
|
||||
/* We cannot NUL terminate the string. */
|
||||
memcpy(p2, exec_path, ret);
|
||||
memcpy(p2, real_exec_path, ret);
|
||||
} else {
|
||||
ret = get_errno(readlinkat(arg1, path(p), p2, arg4));
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "exec/translation-block.h"
|
||||
|
||||
extern char *exec_path;
|
||||
extern char real_exec_path[PATH_MAX];
|
||||
void init_task_state(TaskState *ts);
|
||||
void task_settid(TaskState *);
|
||||
void stop_all_tasks(void);
|
||||
|
||||
Reference in New Issue
Block a user