From f1a1313b55a3748d1cc6a19c2dad7bc36aa18a17 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Elan=20Ruusam=C3=A4e?= Date: Mon, 30 Apr 2018 21:44:00 +0300 Subject: [PATCH] update qemu-user-execve.patch updated from https://patchwork.kernel.org/patch/8052841/ --- qemu-user-execve.patch | 112 +++++++++++++---------------------------- 1 file changed, 36 insertions(+), 76 deletions(-) diff --git a/qemu-user-execve.patch b/qemu-user-execve.patch index 78c0e57..48e802c 100644 --- a/qemu-user-execve.patch +++ b/qemu-user-execve.patch @@ -1,4 +1,6 @@ +Discussion: https://resin.io/blog/building-arm-containers-on-any-x86-machine-even-dockerhub/ + https://github.com/resin-io/qemu/commit/782e5bb77014ff136f7bb6133a911e5f53e914a7 https://github.com/resin-io/qemu/commit/782e5bb77014ff136f7bb6133a911e5f53e914a7#commitcomment-17193923 @@ -43,17 +45,11 @@ Reviewed-by: Laurent Vivier v3 changes: - rebase the patchset against current code ---- qemu-2.7.0/linux-user/main.c~ 2016-09-26 12:07:20.000000000 +0300 -+++ qemu-2.7.0/linux-user/main.c 2016-09-26 12:09:24.258470304 +0300 -@@ -18,6 +18,7 @@ - */ - #include "qemu/osdep.h" - #include "qemu-version.h" -+#include - #include - #include - -@@ -75,6 +76,7 @@ static void usage(int exitcode); +diff --git a/linux-user/main.c b/linux-user/main.c +index ee12035..5951279 100644 +--- a/linux-user/main.c ++++ b/linux-user/main.c +@@ -79,6 +79,7 @@ static void usage(int exitcode); static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX; const char *qemu_uname_release; @@ -61,51 +57,24 @@ v3 changes: /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so we allocate a bigger stack. Need a better solution, for example -@@ -3824,6 +3826,38 @@ static void handle_arg_guest_base(const char *arg) +@@ -3828,6 +3829,11 @@ static void handle_arg_guest_base(const char *arg) have_guest_base = 1; } +static void handle_arg_execve(const char *arg) +{ -+ const char *execfn; -+ char buf[PATH_MAX]; -+ char *ret; -+ int len; -+ -+ /* try getauxval() */ -+ execfn = (const char *) getauxval(AT_EXECFN); -+ -+ if (execfn != 0) { -+ ret = realpath(execfn, buf); -+ -+ if (ret != NULL) { -+ qemu_execve_path = strdup(buf); -+ return; -+ } -+ } -+ -+ /* try /proc/self/exe */ -+ len = readlink("/proc/self/exe", buf, sizeof(buf) - 1); -+ -+ if (len != -1) { -+ buf[len] = '\0'; -+ qemu_execve_path = strdup(buf); -+ return; -+ } -+ -+ fprintf(stderr, "qemu_execve: unable to determine intepreter's path\n"); -+ exit(EXIT_FAILURE); ++ qemu_execve_path = strdup(arg); +} + static void handle_arg_reserved_va(const char *arg) { char *p; -@@ -3909,6 +3943,8 @@ static const struct qemu_argument arg_table[] = { +@@ -3913,6 +3919,8 @@ static const struct qemu_argument arg_table[] = { "uname", "set qemu uname release string to 'uname'"}, {"B", "QEMU_GUEST_BASE", true, handle_arg_guest_base, "address", "set guest_base address to 'address'"}, -+ {"execve", "QEMU_EXECVE", false, handle_arg_execve, -+ "", "use this interpreter when a process calls execve()"}, ++ {"execve", "QEMU_EXECVE", true, handle_arg_execve, ++ "path", "use interpreter at 'path' when a process calls execve()"}, {"R", "QEMU_RESERVED_VA", true, handle_arg_reserved_va, "size", "reserve 'size' bytes for guest virtual address space"}, {"d", "QEMU_LOG", true, handle_arg_log, @@ -121,20 +90,16 @@ index bd90cc3..0d9b058 100644 extern unsigned long mmap_min_addr; /* ??? See if we can avoid exposing so much of the loader internals. */ ---- qemu-2.7.0/linux-user/syscall.c~ 2016-09-26 12:10:36.000000000 +0300 -+++ qemu-2.7.0/linux-user/syscall.c 2016-09-26 12:13:54.312490312 +0300 -@@ -99,6 +99,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -5842,6 +5843,118 @@ static target_timer_t get_timer_id(abi_long arg) +diff --git a/linux-user/syscall.c b/linux-user/syscall.c +index 0cbace4..d0b5442 100644 +--- a/linux-user/syscall.c ++++ b/linux-user/syscall.c +@@ -5854,6 +5854,109 @@ static target_timer_t get_timer_id(abi_long arg) return timerid; } ++#define BINPRM_BUF_SIZE 128 ++ +/* qemu_execve() Must return target values and target errnos. */ +static abi_long qemu_execve(char *filename, char *argv[], + char *envp[]) @@ -145,30 +110,19 @@ index bd90cc3..0d9b058 100644 + char *cp; + char buf[BINPRM_BUF_SIZE]; + -+ /* normal execve case */ -+ if (qemu_execve_path == NULL || *qemu_execve_path == 0) { -+ return get_errno(execve(filename, argv, envp)); -+ } -+ + for (argc = 0; argv[argc] != NULL; argc++) { + /* nothing */ ; + } + + fd = open(filename, O_RDONLY); + if (fd == -1) { -+ return get_errno(fd); ++ return -ENOENT; + } + + ret = read(fd, buf, BINPRM_BUF_SIZE); + if (ret == -1) { + close(fd); -+ return get_errno(ret); -+ } -+ -+ /* if we have less than 2 bytes, we can guess it is not executable */ -+ if (ret < 2) { -+ close(fd); -+ return -host_to_target_errno(ENOEXEC); ++ return -ENOENT; + } + + close(fd); @@ -185,7 +139,7 @@ index bd90cc3..0d9b058 100644 + buf[BINPRM_BUF_SIZE - 1] = '\0'; + cp = strchr(buf, '\n'); + if (cp == NULL) { -+ cp = buf + BINPRM_BUF_SIZE - 1; ++ cp = buf+BINPRM_BUF_SIZE-1; + } + *cp = '\0'; + while (cp > buf) { @@ -196,7 +150,7 @@ index bd90cc3..0d9b058 100644 + break; + } + } -+ for (cp = buf + 2; (*cp == ' ') || (*cp == '\t'); cp++) { ++ for (cp = buf+2; (*cp == ' ') || (*cp == '\t'); cp++) { + /* nothing */ ; + } + if (*cp == '\0') { @@ -244,18 +198,24 @@ index bd90cc3..0d9b058 100644 + new_argp[2] = argv[0]; + } + -+ return get_errno(safe_execve(qemu_execve_path, new_argp, envp)); ++ return get_errno(execve(qemu_execve_path, new_argp, envp)); +} + /* do_syscall() should always have a single exit point at the end so that actions, such as logging of syscall results, can be performed. All errnos that do_syscall() returns must be -TARGET_. */ -@@ -7703,7 +7703,7 @@ - * before the execve completes and makes it the other - * program's problem. - */ -- ret = get_errno(safe_execve(p, argp, envp)); -+ ret = qemu_execve(p, argp, envp); +@@ -6113,7 +6216,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, + + if (!(p = lock_user_string(arg1))) + goto execve_efault; +- ret = get_errno(execve(p, argp, envp)); ++ ++ if (qemu_execve_path && *qemu_execve_path) { ++ ret = get_errno(qemu_execve(p, argp, envp)); ++ } else { ++ ret = get_errno(execve(p, argp, envp)); ++ } ++ unlock_user(p, arg1, 0); goto execve_end; -- 2.44.0