Skip to content

Commit d5deaed

Browse files
jchzhouchadlwilson
authored andcommitted
Upgrade QEMU to 10.1.3
Signed-off-by: jchzhou <zhoujiacheng@iscas.ac.cn>
1 parent 9d31fb7 commit d5deaed

10 files changed

+709
-2
lines changed

docker-bake.hcl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ variable "QEMU_REPO" {
55
default = "https://github.com/qemu/qemu"
66
}
77
variable "QEMU_VERSION" {
8-
default = "v10.0.4"
8+
default = "v10.1.3"
99
}
1010
variable "QEMU_PATCHES" {
1111
default = "cpu-max-arm"
@@ -70,7 +70,7 @@ target "buildkit" {
7070
inherits = ["mainline"]
7171
args = {
7272
BINARY_PREFIX = "buildkit-"
73-
QEMU_PATCHES = "${QEMU_PATCHES},buildkit-direct-execve-v10.0"
73+
QEMU_PATCHES = "${QEMU_PATCHES},buildkit-direct-execve-v10.1"
7474
QEMU_PRESERVE_ARGV0 = ""
7575
}
7676
cache-from = ["${REPO_SLUG}:buildkit-master"]

patches/aports.config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
10.1.3,4fabd1965b4d7469b4f1b63fd5d3b86838e923d7
12
10.0.4,c9b4dbf9a02f4616c7e82fd4b97938da0f058c03
23
9.2.2,334b162677f79271980f61d410dc136b98b93fc4
34
8.1.50,e9d411e67e815ab0fcf1d00885cb55dd0f99e810
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
From b0ccc59b95c5520847354bd4ab57694e7510a4ea Mon Sep 17 00:00:00 2001
2+
From: CrazyMax <crazy-max@users.noreply.github.com>
3+
Date: Fri, 8 Sep 2023 10:47:29 +0200
4+
Subject: [PATCH 1/7] linux-user: have execve call qemu via /proc/self/exe to
5+
not rely on binfmt_misc
6+
7+
It is assumed that when a guest program calls execve syscall it wants to
8+
execute a program on the same guest architecture and not the host architecture.
9+
10+
Previously, such a guest program would have execve syscall error out with:
11+
"exec format error".
12+
13+
A common solution is to register the qemu binary in binfmt_misc but that is not a
14+
userland-friendly solution, requiring to modify kernel state.
15+
16+
This patch injects /proc/self/exe as the first parameter and the qemu program name
17+
as argv[0] to execve.
18+
19+
Signed-off-by: Tibor Vass <tibor@docker.com>
20+
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
21+
---
22+
linux-user/syscall.c | 44 +++++++++++++++++++++++++++++++-------------
23+
1 file changed, 31 insertions(+), 13 deletions(-)
24+
25+
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
26+
index 2edbd1ef15..b9808851e0 100644
27+
--- a/linux-user/syscall.c
28+
+++ b/linux-user/syscall.c
29+
@@ -8489,10 +8489,37 @@ static int do_execv(CPUArchState *cpu_env, int dirfd,
30+
envc++;
31+
}
32+
33+
- argp = g_new0(char *, argc + 1);
34+
+ argp = g_new0(char *, argc + 4);
35+
envp = g_new0(char *, envc + 1);
36+
37+
- for (gp = guest_argp, q = argp; gp; gp += sizeof(abi_ulong), q++) {
38+
+ if (!(p = lock_user_string(pathname)))
39+
+ goto execve_efault;
40+
+
41+
+ /* if pathname is /proc/self/exe then retrieve the path passed to qemu via command line */
42+
+ if (is_proc_myself(p, "exe")) {
43+
+ CPUState *cpu = env_cpu((CPUArchState *)cpu_env);
44+
+ TaskState *ts = cpu->opaque;
45+
+ p = ts->bprm->filename;
46+
+ }
47+
+
48+
+ /* retrieve guest argv0 */
49+
+ if (get_user_ual(addr, guest_argp))
50+
+ goto execve_efault;
51+
+
52+
+ /*
53+
+ * From the guest, the call
54+
+ * execve(pathname, [argv0, argv1], envp)
55+
+ * on the host, becomes:
56+
+ * execve("/proc/self/exe", [qemu_progname, "-0", argv0, pathname, argv1], envp)
57+
+ * where qemu_progname is the error message prefix for qemu
58+
+ */
59+
+ argp[0] = (char*)error_get_progname();
60+
+ argp[1] = (char*)"-0";
61+
+ argp[2] = (char*)lock_user_string(addr);
62+
+ argp[3] = p;
63+
+
64+
+ /* copy guest argv1 onwards to host argv4 onwards */
65+
+ for (gp = guest_argp + 1*sizeof(abi_ulong), q = argp + 4; gp; gp += sizeof(abi_ulong), q++) {
66+
if (get_user_ual(addr, gp)) {
67+
goto execve_efault;
68+
}
69+
@@ -8531,18 +8558,9 @@ static int do_execv(CPUArchState *cpu_env, int dirfd,
70+
* before the execve completes and makes it the other
71+
* program's problem.
72+
*/
73+
- p = lock_user_string(pathname);
74+
- if (!p) {
75+
- goto execve_efault;
76+
- }
77+
-
78+
- const char *exe = p;
79+
- if (is_proc_myself(p, "exe")) {
80+
- exe = exec_path;
81+
- }
82+
ret = is_execveat
83+
- ? safe_execveat(dirfd, exe, argp, envp, flags)
84+
- : safe_execve(exe, argp, envp);
85+
+ ? safe_execveat(dirfd, "/proc/self/exe", argp, envp, flags)
86+
+ : safe_execve("/proc/self/exe", argp, envp);
87+
ret = get_errno(ret);
88+
89+
unlock_user(p, pathname, 0);
90+
--
91+
2.39.3 (Apple Git-146)
92+
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
From 4a12f3c8b2d145ccbd5a437fbdf03e84f7b43b49 Mon Sep 17 00:00:00 2001
2+
From: Tibor Vass <tibor@docker.com>
3+
Date: Tue, 2 Jun 2020 10:39:48 +0000
4+
Subject: [PATCH 2/7] linux-user: lookup user program in PATH
5+
6+
Signed-off-by: Tibor Vass <tibor@docker.com>
7+
---
8+
linux-user/main.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
9+
1 file changed, 44 insertions(+), 1 deletion(-)
10+
11+
diff --git a/linux-user/main.c b/linux-user/main.c
12+
index 149e35432e..dd70ee10f1 100644
13+
--- a/linux-user/main.c
14+
+++ b/linux-user/main.c
15+
@@ -600,6 +600,45 @@ static void usage(int exitcode)
16+
exit(exitcode);
17+
}
18+
19+
+/*
20+
+ * path_lookup searches for an executable filename in the directories named by the PATH environment variable.
21+
+ * Returns a copy of filename if it is an absolute path or could not find a match.
22+
+ * Caller is responsible to free returned string.
23+
+ * Adapted from musl's execvp implementation.
24+
+ */
25+
+static char *path_lookup(char *filename) {
26+
+ const char *p, *z, *path = getenv("PATH");
27+
+ size_t l, k;
28+
+ struct stat buf;
29+
+
30+
+ /* if PATH is not set or filename is absolute path return filename */
31+
+ if (!path || !filename || filename[0] == '/')
32+
+ return strndup(filename, NAME_MAX+1);
33+
+
34+
+ k = strnlen(filename, NAME_MAX+1);
35+
+ if (k > NAME_MAX) {
36+
+ errno = ENAMETOOLONG;
37+
+ return NULL;
38+
+ }
39+
+ l = strnlen(path, PATH_MAX-1)+1;
40+
+
41+
+ for (p = path; ; p = z) {
42+
+ char *b = calloc(l+k+1, sizeof(char));
43+
+ z = strchrnul(p, ':');
44+
+ if (z-p >= l) {
45+
+ if (!*z++) break;
46+
+ continue;
47+
+ }
48+
+ memcpy(b, p, z-p);
49+
+ b[z-p] = '/';
50+
+ memcpy(b+(z-p)+(z>p), filename, k+1);
51+
+ if (!stat(b, &buf) && !(buf.st_mode & S_IFDIR) && (buf.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))
52+
+ return b;
53+
+ if (!*z++) break;
54+
+ }
55+
+ return strndup(filename, NAME_MAX+1);
56+
+}
57+
+
58+
static int parse_args(int argc, char **argv)
59+
{
60+
const char *r;
61+
@@ -665,7 +704,11 @@ static int parse_args(int argc, char **argv)
62+
exit(EXIT_FAILURE);
63+
}
64+
65+
- exec_path = argv[optind];
66+
+ /* not freeing exec_path as it is needed for the lifetime of the process */
67+
+ if (!(exec_path = path_lookup(argv[optind]))) {
68+
+ (void) fprintf(stderr, "qemu: could not find user program %s: %s\n", exec_path, strerror(errno));
69+
+ exit(EXIT_FAILURE);
70+
+ }
71+
72+
return optind;
73+
}
74+
--
75+
2.39.3 (Apple Git-146)
76+
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
From b05369333c5e7899e88fb1e7863b06c5690990bf Mon Sep 17 00:00:00 2001
2+
From: CrazyMax <crazy-max@users.noreply.github.com>
3+
Date: Wed, 3 May 2023 20:54:37 +0200
4+
Subject: [PATCH 3/7] linux-user: path in execve should be relative to working
5+
dir
6+
7+
Fixes regression introduced in parent commit where PATH handling was introduced.
8+
9+
When guest calls execve(filename, argp, envp) filename can be relative in which
10+
case Linux makes it relative to the working directory.
11+
12+
However, since execve is now handled by exec-ing qemu process again, filename
13+
would first get looked up in PATH in main() before calling host's execve.
14+
15+
With this change, if filename is relative and exists in working directory as
16+
well as in PATH, working directory will get precedence over PATH if guest is
17+
doing an execve syscall, but not if relative filename comes from qemu's argv.
18+
19+
Signed-off-by: Tibor Vass <tibor@docker.com>
20+
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
21+
Signed-off-by: Zewei Yang <yangzewei@loongson.cn>
22+
---
23+
include/qemu/path.h | 1 +
24+
linux-user/syscall.c | 9 +++++++--
25+
util/path.c | 33 +++++++++++++++++++++++++++++++++
26+
3 files changed, 41 insertions(+), 2 deletions(-)
27+
28+
diff --git a/include/qemu/path.h b/include/qemu/path.h
29+
index c6292a9..a81fb51 100644
30+
--- a/include/qemu/path.h
31+
+++ b/include/qemu/path.h
32+
@@ -3,5 +3,6 @@
33+
34+
void init_paths(const char *prefix);
35+
const char *path(const char *pathname);
36+
+const char *prepend_workdir_if_relative(const char *path);
37+
38+
#endif
39+
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
40+
index bd8f64e..7a23639 100644
41+
--- a/linux-user/syscall.c
42+
+++ b/linux-user/syscall.c
43+
@@ -8641,12 +8641,17 @@ static int do_execv(CPUArchState *cpu_env, int dirfd,
44+
* execve(pathname, [argv0, argv1], envp)
45+
* on the host, becomes:
46+
* execve("/proc/self/exe", [qemu_progname, "-0", argv0, pathname, argv1], envp)
47+
- * where qemu_progname is the error message prefix for qemu
48+
+ * where qemu_progname is the error message prefix for qemu.
49+
+ * Note: if pathname is relative, it will be prepended with the current working directory.
50+
*/
51+
argp[0] = (char*)error_get_progname();
52+
argp[1] = (char*)"-0";
53+
argp[2] = (char*)lock_user_string(addr);
54+
- argp[3] = p;
55+
+ argp[3] = (char*)prepend_workdir_if_relative(p);
56+
+ if (!argp[3]) {
57+
+ ret = -host_to_target_errno(errno);
58+
+ goto execve_end;
59+
+ }
60+
61+
/* copy guest argv1 onwards to host argv4 onwards */
62+
for (gp = guest_argp + 1*sizeof(abi_ulong), q = argp + 4; gp; gp += sizeof(abi_ulong), q++) {
63+
diff --git a/util/path.c b/util/path.c
64+
index 8e174eb..a5afd52 100644
65+
--- a/util/path.c
66+
+++ b/util/path.c
67+
@@ -68,3 +68,36 @@ const char *path(const char *name)
68+
qemu_mutex_unlock(&lock);
69+
return ret;
70+
}
71+
+
72+
+/* Prepends working directory if path is relative.
73+
+ * If path is absolute, it is returned as-is without any allocation.
74+
+ * Otherwise, caller is responsible to free returned path.
75+
+ * Returns NULL and sets errno upon error.
76+
+ * Note: realpath is not called to let the kernel do the rest of the resolution.
77+
+ */
78+
+const char *prepend_workdir_if_relative(const char *path)
79+
+{
80+
+ char buf[PATH_MAX];
81+
+ char *p;
82+
+ int i, j, k;
83+
+
84+
+ if (!path || path[0] == '/') return path;
85+
+
86+
+ if (!getcwd(buf, PATH_MAX)) return NULL;
87+
+ i = strlen(buf);
88+
+ j = strlen(path);
89+
+ k = i + 1 + j + 1; /* workdir + '/' + path + '\0' */
90+
+ if (i + j > PATH_MAX) {
91+
+ errno = ERANGE;
92+
+ return NULL;
93+
+ }
94+
+ if (!(p = malloc(k * sizeof(char)))) return NULL;
95+
+
96+
+ p[0] = '\0';
97+
+
98+
+ memcpy(p, buf, i);
99+
+ p[i] = '/';
100+
+ memcpy(p + i + 1, path, j);
101+
+ p[i + 1 + j] = '\0';
102+
+ return p;
103+
+}
104+
--
105+
2.47.3
106+

0 commit comments

Comments
 (0)