* [PATCH 0/2] linux-user: handle /proc/self/exe with execve() syscall
@ 2022-09-25 16:15 Laurent Vivier
2022-09-25 16:15 ` [PATCH 1/2] " Laurent Vivier
2022-09-25 16:15 ` [PATCH 2/2] linux-user: don't use AT_EXECFD in do_openat() Laurent Vivier
0 siblings, 2 replies; 3+ messages in thread
From: Laurent Vivier @ 2022-09-25 16:15 UTC (permalink / raw)
To: qemu-devel; +Cc: Laurent Vivier
Use execfd to re-exectute the binary from /proc/self/exe
Fix do_openat() that should not use execfd.
Laurent Vivier (2):
linux-user: handle /proc/self/exe with execve() syscall
linux-user: don't use AT_EXECFD in do_openat()
linux-user/main.c | 9 +++++++--
linux-user/syscall.c | 12 +++++++++---
linux-user/user-internals.h | 1 +
3 files changed, 17 insertions(+), 5 deletions(-)
--
2.37.3
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH 1/2] linux-user: handle /proc/self/exe with execve() syscall
2022-09-25 16:15 [PATCH 0/2] linux-user: handle /proc/self/exe with execve() syscall Laurent Vivier
@ 2022-09-25 16:15 ` Laurent Vivier
2022-09-25 16:15 ` [PATCH 2/2] linux-user: don't use AT_EXECFD in do_openat() Laurent Vivier
1 sibling, 0 replies; 3+ messages in thread
From: Laurent Vivier @ 2022-09-25 16:15 UTC (permalink / raw)
To: qemu-devel; +Cc: Laurent Vivier
If path is /proc/self/exe, use the executable file descriptor
provided by binfmt_misc (or opened by main()) with execveat().
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
linux-user/main.c | 9 +++++++--
linux-user/syscall.c | 9 ++++++++-
linux-user/user-internals.h | 1 +
3 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/linux-user/main.c b/linux-user/main.c
index e44bdb17b853..f915bdd7cef7 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -64,6 +64,7 @@
#endif
char *exec_path;
+int execfd;
int singlestep;
static const char *argv0;
@@ -646,7 +647,6 @@ int main(int argc, char **argv, char **envp)
int target_argc;
int i;
int ret;
- int execfd;
unsigned long max_reserved_va;
bool preserve_argv0;
@@ -845,7 +845,12 @@ int main(int argc, char **argv, char **envp)
fd_trans_init();
- ret = loader_exec(execfd, exec_path, target_argv, target_environ, regs,
+ /*
+ * loader_exec() closes the file descriptor provided by the caller.
+ * As we need to keep it available for execve("/proc/self/exe")
+ * we provide a copy to loader_exec().
+ */
+ ret = loader_exec(dup(execfd), exec_path, target_argv, target_environ, regs,
info, &bprm);
if (ret != 0) {
printf("Error while loading %s: %s\n", exec_path, strerror(-ret));
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index f4091212027c..6642652b7644 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -649,6 +649,8 @@ safe_syscall4(pid_t, wait4, pid_t, pid, int *, status, int, options, \
safe_syscall5(int, waitid, idtype_t, idtype, id_t, id, siginfo_t *, infop, \
int, options, struct rusage *, rusage)
safe_syscall3(int, execve, const char *, filename, char **, argv, char **, envp)
+safe_syscall5(int, execveat, int, dirfd, const char *, pathname, char **, \
+ argv, char **, envp, int, flags)
#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) || \
defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64)
safe_syscall6(int, pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds, \
@@ -8843,7 +8845,12 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
* before the execve completes and makes it the other
* program's problem.
*/
- ret = get_errno(safe_execve(p, argp, envp));
+ if (is_proc_myself(p, "exe")) {
+ ret = get_errno(safe_execveat(execfd, "", argp, envp,
+ AT_EMPTY_PATH));
+ } else {
+ ret = get_errno(safe_execve(p, argp, envp));
+ }
unlock_user(p, arg1, 0);
goto execve_end;
diff --git a/linux-user/user-internals.h b/linux-user/user-internals.h
index 0280e76addda..84f29a1e2990 100644
--- a/linux-user/user-internals.h
+++ b/linux-user/user-internals.h
@@ -23,6 +23,7 @@
#include "qemu/log.h"
extern char *exec_path;
+extern int execfd;
void init_task_state(TaskState *ts);
void task_settid(TaskState *);
void stop_all_tasks(void);
--
2.37.3
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 2/2] linux-user: don't use AT_EXECFD in do_openat()
2022-09-25 16:15 [PATCH 0/2] linux-user: handle /proc/self/exe with execve() syscall Laurent Vivier
2022-09-25 16:15 ` [PATCH 1/2] " Laurent Vivier
@ 2022-09-25 16:15 ` Laurent Vivier
1 sibling, 0 replies; 3+ messages in thread
From: Laurent Vivier @ 2022-09-25 16:15 UTC (permalink / raw)
To: qemu-devel; +Cc: Laurent Vivier
AT_EXECFD gives access to the binary file even if
it is not readable (only executable).
Moreover it can be opened with flags and mode that are not the ones
provided by do_openat() caller.
And finally the caller can close the file descriptor whereas
we can need it with execveat().
To avoid that, use only safe_openat() with the exec_path.
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
linux-user/syscall.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 6642652b7644..01f03535fe64 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -8265,8 +8265,7 @@ static int do_openat(CPUArchState *cpu_env, int dirfd, const char *pathname, int
};
if (is_proc_myself(pathname, "exe")) {
- int execfd = qemu_getauxval(AT_EXECFD);
- return execfd ? execfd : safe_openat(dirfd, exec_path, flags, mode);
+ return safe_openat(dirfd, exec_path, flags, mode);
}
for (fake_open = fakes; fake_open->filename; fake_open++) {
--
2.37.3
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2022-09-25 16:20 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-09-25 16:15 [PATCH 0/2] linux-user: handle /proc/self/exe with execve() syscall Laurent Vivier
2022-09-25 16:15 ` [PATCH 1/2] " Laurent Vivier
2022-09-25 16:15 ` [PATCH 2/2] linux-user: don't use AT_EXECFD in do_openat() Laurent Vivier
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).