summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/qemu
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2024-02-29 12:32:12 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2024-03-03 16:25:20 +0000
commit9d1a99cf452f4dbd68327f1dc220d34a0dad932f (patch)
treef6e83fbe93efa65c2a77aece50466d400fe93903 /meta/recipes-devtools/qemu
parent9b5c6444f772972544185b7745bd9491194a8cfd (diff)
downloadpoky-9d1a99cf452f4dbd68327f1dc220d34a0dad932f.tar.gz
qemu: Replace workaround with proper usermode fix for shmat
We were using a workaround to avoid problems with the behaviour of shmat() calls in usermode qemu. Switch to patches from upstream which are in review but not merged yet. Update the mmap fixed/noreplace workaround for the changes. (From OE-Core rev: 8a571e352734045176bac310441a1003efbf0891) Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/recipes-devtools/qemu')
-rw-r--r--meta/recipes-devtools/qemu/qemu.inc7
-rw-r--r--meta/recipes-devtools/qemu/qemu/0001-linux-user-x86_64-Handle-the-vsyscall-page-in-open_s.patch56
-rw-r--r--meta/recipes-devtools/qemu/qemu/0002-linux-user-loongarch64-Remove-TARGET_FORCE_SHMLBA.patch43
-rw-r--r--meta/recipes-devtools/qemu/qemu/0003-linux-user-Add-strace-for-shmat.patch71
-rw-r--r--meta/recipes-devtools/qemu/qemu/0004-linux-user-Rewrite-target_shmat.patch236
-rw-r--r--meta/recipes-devtools/qemu/qemu/0005-tests-tcg-Check-that-shmat-does-not-break-proc-self-.patch85
-rw-r--r--meta/recipes-devtools/qemu/qemu/0011-linux-user-workaround-for-missing-MAP_FIXED_NOREPLAC.patch62
-rw-r--r--meta/recipes-devtools/qemu/qemu/4a8579ad8629b57a43daa62e46cc7af6e1078116.patch60
-rw-r--r--meta/recipes-devtools/qemu/qemu/fix_segv.patch47
9 files changed, 586 insertions, 81 deletions
diff --git a/meta/recipes-devtools/qemu/qemu.inc b/meta/recipes-devtools/qemu/qemu.inc
index a403f7d69f..b42cc120f1 100644
--- a/meta/recipes-devtools/qemu/qemu.inc
+++ b/meta/recipes-devtools/qemu/qemu.inc
@@ -33,7 +33,12 @@ SRC_URI = "https://download.qemu.org/${BPN}-${PV}.tar.xz \
33 file://0002-linux-user-Replace-use-of-lfs64-related-functions-an.patch \ 33 file://0002-linux-user-Replace-use-of-lfs64-related-functions-an.patch \
34 file://fixedmeson.patch \ 34 file://fixedmeson.patch \
35 file://no-pip.patch \ 35 file://no-pip.patch \
36 file://fix_segv.patch \ 36 file://4a8579ad8629b57a43daa62e46cc7af6e1078116.patch \
37 file://0001-linux-user-x86_64-Handle-the-vsyscall-page-in-open_s.patch \
38 file://0002-linux-user-loongarch64-Remove-TARGET_FORCE_SHMLBA.patch \
39 file://0003-linux-user-Add-strace-for-shmat.patch \
40 file://0004-linux-user-Rewrite-target_shmat.patch \
41 file://0005-tests-tcg-Check-that-shmat-does-not-break-proc-self-.patch \
37 file://qemu-guest-agent.init \ 42 file://qemu-guest-agent.init \
38 file://qemu-guest-agent.udev \ 43 file://qemu-guest-agent.udev \
39 " 44 "
diff --git a/meta/recipes-devtools/qemu/qemu/0001-linux-user-x86_64-Handle-the-vsyscall-page-in-open_s.patch b/meta/recipes-devtools/qemu/qemu/0001-linux-user-x86_64-Handle-the-vsyscall-page-in-open_s.patch
new file mode 100644
index 0000000000..2eaebe883c
--- /dev/null
+++ b/meta/recipes-devtools/qemu/qemu/0001-linux-user-x86_64-Handle-the-vsyscall-page-in-open_s.patch
@@ -0,0 +1,56 @@
1From 4517e2046610722879761bcdb60edbb2b929c848 Mon Sep 17 00:00:00 2001
2From: Richard Henderson <richard.henderson@linaro.org>
3Date: Wed, 28 Feb 2024 10:25:14 -1000
4Subject: [PATCH 1/5] linux-user/x86_64: Handle the vsyscall page in
5 open_self_maps_{2,4}
6
7This is the only case in which we expect to have no host memory backing
8for a guest memory page, because in general linux user processes cannot
9map any pages in the top half of the 64-bit address space.
10
11Upstream-Status: Submitted [https://www.mail-archive.com/qemu-devel@nongnu.org/msg1026793.html]
12
13Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2170
14Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
16---
17 linux-user/syscall.c | 16 ++++++++++++++++
18 1 file changed, 16 insertions(+)
19
20diff --git a/linux-user/syscall.c b/linux-user/syscall.c
21index a114f29a8..8307a8a61 100644
22--- a/linux-user/syscall.c
23+++ b/linux-user/syscall.c
24@@ -7922,6 +7922,10 @@ static void open_self_maps_4(const struct open_self_maps_data *d,
25 path = "[heap]";
26 } else if (start == info->vdso) {
27 path = "[vdso]";
28+#ifdef TARGET_X86_64
29+ } else if (start == TARGET_VSYSCALL_PAGE) {
30+ path = "[vsyscall]";
31+#endif
32 }
33
34 /* Except null device (MAP_ANON), adjust offset for this fragment. */
35@@ -8010,6 +8014,18 @@ static int open_self_maps_2(void *opaque, target_ulong guest_start,
36 uintptr_t host_start = (uintptr_t)g2h_untagged(guest_start);
37 uintptr_t host_last = (uintptr_t)g2h_untagged(guest_end - 1);
38
39+#ifdef TARGET_X86_64
40+ /*
41+ * Because of the extremely high position of the page within the guest
42+ * virtual address space, this is not backed by host memory at all.
43+ * Therefore the loop below would fail. This is the only instance
44+ * of not having host backing memory.
45+ */
46+ if (guest_start == TARGET_VSYSCALL_PAGE) {
47+ return open_self_maps_3(opaque, guest_start, guest_end, flags);
48+ }
49+#endif
50+
51 while (1) {
52 IntervalTreeNode *n =
53 interval_tree_iter_first(d->host_maps, host_start, host_start);
54--
552.34.1
56
diff --git a/meta/recipes-devtools/qemu/qemu/0002-linux-user-loongarch64-Remove-TARGET_FORCE_SHMLBA.patch b/meta/recipes-devtools/qemu/qemu/0002-linux-user-loongarch64-Remove-TARGET_FORCE_SHMLBA.patch
new file mode 100644
index 0000000000..3f01aaa644
--- /dev/null
+++ b/meta/recipes-devtools/qemu/qemu/0002-linux-user-loongarch64-Remove-TARGET_FORCE_SHMLBA.patch
@@ -0,0 +1,43 @@
1From 5bf65b24414d3ff8339f6f1beb221c7c35c91e5d Mon Sep 17 00:00:00 2001
2From: Richard Henderson <richard.henderson@linaro.org>
3Date: Wed, 28 Feb 2024 10:25:15 -1000
4Subject: [PATCH 2/5] linux-user/loongarch64: Remove TARGET_FORCE_SHMLBA
5
6The kernel abi was changed with
7
8 commit d23b77953f5a4fbf94c05157b186aac2a247ae32
9 Author: Huacai Chen <chenhuacai@kernel.org>
10 Date: Wed Jan 17 12:43:08 2024 +0800
11
12 LoongArch: Change SHMLBA from SZ_64K to PAGE_SIZE
13
14during the v6.8 cycle.
15
16Upstream-Status: Submitted [https://www.mail-archive.com/qemu-devel@nongnu.org/msg1026793.html]
17
18Reviewed-by: Song Gao <gaosong@loongson.cn>
19Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
20Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
21---
22 linux-user/loongarch64/target_syscall.h | 7 -------
23 1 file changed, 7 deletions(-)
24
25diff --git a/linux-user/loongarch64/target_syscall.h b/linux-user/loongarch64/target_syscall.h
26index 8b5de5212..39f229bb9 100644
27--- a/linux-user/loongarch64/target_syscall.h
28+++ b/linux-user/loongarch64/target_syscall.h
29@@ -38,11 +38,4 @@ struct target_pt_regs {
30 #define TARGET_MCL_FUTURE 2
31 #define TARGET_MCL_ONFAULT 4
32
33-#define TARGET_FORCE_SHMLBA
34-
35-static inline abi_ulong target_shmlba(CPULoongArchState *env)
36-{
37- return 64 * KiB;
38-}
39-
40 #endif
41--
422.34.1
43
diff --git a/meta/recipes-devtools/qemu/qemu/0003-linux-user-Add-strace-for-shmat.patch b/meta/recipes-devtools/qemu/qemu/0003-linux-user-Add-strace-for-shmat.patch
new file mode 100644
index 0000000000..0c601c804a
--- /dev/null
+++ b/meta/recipes-devtools/qemu/qemu/0003-linux-user-Add-strace-for-shmat.patch
@@ -0,0 +1,71 @@
1From e8f06676c6c88e12cd5f4f81a839b7111c683596 Mon Sep 17 00:00:00 2001
2From: Richard Henderson <richard.henderson@linaro.org>
3Date: Wed, 28 Feb 2024 10:25:16 -1000
4Subject: [PATCH 3/5] linux-user: Add strace for shmat
5
6Upstream-Status: Submitted [https://www.mail-archive.com/qemu-devel@nongnu.org/msg1026793.html]
7
8Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
10---
11 linux-user/strace.c | 23 +++++++++++++++++++++++
12 linux-user/strace.list | 2 +-
13 2 files changed, 24 insertions(+), 1 deletion(-)
14
15diff --git a/linux-user/strace.c b/linux-user/strace.c
16index cf26e5526..47d6ec326 100644
17--- a/linux-user/strace.c
18+++ b/linux-user/strace.c
19@@ -670,6 +670,25 @@ print_semctl(CPUArchState *cpu_env, const struct syscallname *name,
20 }
21 #endif
22
23+static void
24+print_shmat(CPUArchState *cpu_env, const struct syscallname *name,
25+ abi_long arg0, abi_long arg1, abi_long arg2,
26+ abi_long arg3, abi_long arg4, abi_long arg5)
27+{
28+ static const struct flags shmat_flags[] = {
29+ FLAG_GENERIC(SHM_RND),
30+ FLAG_GENERIC(SHM_REMAP),
31+ FLAG_GENERIC(SHM_RDONLY),
32+ FLAG_GENERIC(SHM_EXEC),
33+ };
34+
35+ print_syscall_prologue(name);
36+ print_raw_param(TARGET_ABI_FMT_ld, arg0, 0);
37+ print_pointer(arg1, 0);
38+ print_flags(shmat_flags, arg2, 1);
39+ print_syscall_epilogue(name);
40+}
41+
42 #ifdef TARGET_NR_ipc
43 static void
44 print_ipc(CPUArchState *cpu_env, const struct syscallname *name,
45@@ -683,6 +702,10 @@ print_ipc(CPUArchState *cpu_env, const struct syscallname *name,
46 print_ipc_cmd(arg3);
47 qemu_log(",0x" TARGET_ABI_FMT_lx ")", arg4);
48 break;
49+ case IPCOP_shmat:
50+ print_shmat(cpu_env, &(const struct syscallname){ .name = "shmat" },
51+ arg1, arg4, arg2, 0, 0, 0);
52+ break;
53 default:
54 qemu_log(("%s("
55 TARGET_ABI_FMT_ld ","
56diff --git a/linux-user/strace.list b/linux-user/strace.list
57index 6655d4f26..dfd4237d1 100644
58--- a/linux-user/strace.list
59+++ b/linux-user/strace.list
60@@ -1398,7 +1398,7 @@
61 { TARGET_NR_sgetmask, "sgetmask" , NULL, NULL, NULL },
62 #endif
63 #ifdef TARGET_NR_shmat
64-{ TARGET_NR_shmat, "shmat" , NULL, NULL, print_syscall_ret_addr },
65+{ TARGET_NR_shmat, "shmat" , NULL, print_shmat, print_syscall_ret_addr },
66 #endif
67 #ifdef TARGET_NR_shmctl
68 { TARGET_NR_shmctl, "shmctl" , NULL, NULL, NULL },
69--
702.34.1
71
diff --git a/meta/recipes-devtools/qemu/qemu/0004-linux-user-Rewrite-target_shmat.patch b/meta/recipes-devtools/qemu/qemu/0004-linux-user-Rewrite-target_shmat.patch
new file mode 100644
index 0000000000..88c3ed40b0
--- /dev/null
+++ b/meta/recipes-devtools/qemu/qemu/0004-linux-user-Rewrite-target_shmat.patch
@@ -0,0 +1,236 @@
1From cb48d5d1592e63ebd0d4a3e300ef98e38e6306d7 Mon Sep 17 00:00:00 2001
2From: Richard Henderson <richard.henderson@linaro.org>
3Date: Wed, 28 Feb 2024 10:25:17 -1000
4Subject: [PATCH 4/5] linux-user: Rewrite target_shmat
5
6Handle combined host and guest alignment requirements.
7Handle host and guest page size differences.
8Handle SHM_EXEC.
9
10Upstream-Status: Submitted [https://www.mail-archive.com/qemu-devel@nongnu.org/msg1026793.html]
11
12Resolves: https://gitlab.com/qemu-project/qemu/-/issues/115
13Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
15---
16 linux-user/mmap.c | 166 +++++++++++++++++++++++++++++++++++++---------
17 1 file changed, 133 insertions(+), 33 deletions(-)
18
19diff --git a/linux-user/mmap.c b/linux-user/mmap.c
20index 18fb3aaf7..6a2f649bb 100644
21--- a/linux-user/mmap.c
22+++ b/linux-user/mmap.c
23@@ -1062,69 +1062,161 @@ static inline abi_ulong target_shmlba(CPUArchState *cpu_env)
24 }
25 #endif
26
27+#if defined(__arm__) || defined(__mips__) || defined(__sparc__)
28+#define HOST_FORCE_SHMLBA 1
29+#else
30+#define HOST_FORCE_SHMLBA 0
31+#endif
32+
33 abi_ulong target_shmat(CPUArchState *cpu_env, int shmid,
34 abi_ulong shmaddr, int shmflg)
35 {
36 CPUState *cpu = env_cpu(cpu_env);
37- abi_ulong raddr;
38 struct shmid_ds shm_info;
39 int ret;
40- abi_ulong shmlba;
41+ int h_pagesize;
42+ int t_shmlba, h_shmlba, m_shmlba;
43+ size_t t_len, h_len, m_len;
44
45 /* shmat pointers are always untagged */
46
47- /* find out the length of the shared memory segment */
48+ /*
49+ * Because we can't use host shmat() unless the address is sufficiently
50+ * aligned for the host, we'll need to check both.
51+ * TODO: Could be fixed with softmmu.
52+ */
53+ t_shmlba = target_shmlba(cpu_env);
54+ h_pagesize = qemu_real_host_page_size();
55+ h_shmlba = (HOST_FORCE_SHMLBA ? SHMLBA : h_pagesize);
56+ m_shmlba = MAX(t_shmlba, h_shmlba);
57+
58+ if (shmaddr) {
59+ if (shmaddr & (m_shmlba - 1)) {
60+ if (shmflg & SHM_RND) {
61+ /*
62+ * The guest is allowing the kernel to round the address.
63+ * Assume that the guest is ok with us rounding to the
64+ * host required alignment too. Anyway if we don't, we'll
65+ * get an error from the kernel.
66+ */
67+ shmaddr &= ~(m_shmlba - 1);
68+ if (shmaddr == 0 && (shmflg & SHM_REMAP)) {
69+ return -TARGET_EINVAL;
70+ }
71+ } else {
72+ int require = TARGET_PAGE_SIZE;
73+#ifdef TARGET_FORCE_SHMLBA
74+ require = t_shmlba;
75+#endif
76+ /*
77+ * Include host required alignment, as otherwise we cannot
78+ * use host shmat at all.
79+ */
80+ require = MAX(require, h_shmlba);
81+ if (shmaddr & (require - 1)) {
82+ return -TARGET_EINVAL;
83+ }
84+ }
85+ }
86+ } else {
87+ if (shmflg & SHM_REMAP) {
88+ return -TARGET_EINVAL;
89+ }
90+ }
91+ /* All rounding now manually concluded. */
92+ shmflg &= ~SHM_RND;
93+
94+ /* Find out the length of the shared memory segment. */
95 ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
96 if (is_error(ret)) {
97 /* can't get length, bail out */
98 return ret;
99 }
100+ t_len = TARGET_PAGE_ALIGN(shm_info.shm_segsz);
101+ h_len = ROUND_UP(shm_info.shm_segsz, h_pagesize);
102+ m_len = MAX(t_len, h_len);
103
104- shmlba = target_shmlba(cpu_env);
105-
106- if (shmaddr & (shmlba - 1)) {
107- if (shmflg & SHM_RND) {
108- shmaddr &= ~(shmlba - 1);
109- } else {
110- return -TARGET_EINVAL;
111- }
112- }
113- if (!guest_range_valid_untagged(shmaddr, shm_info.shm_segsz)) {
114+ if (!guest_range_valid_untagged(shmaddr, m_len)) {
115 return -TARGET_EINVAL;
116 }
117
118 WITH_MMAP_LOCK_GUARD() {
119- void *host_raddr;
120+ bool mapped = false;
121+ void *want, *test;
122 abi_ulong last;
123
124- if (shmaddr) {
125- host_raddr = shmat(shmid, (void *)g2h_untagged(shmaddr), shmflg);
126+ if (!shmaddr) {
127+ shmaddr = mmap_find_vma(0, m_len, m_shmlba);
128+ if (shmaddr == -1) {
129+ return -TARGET_ENOMEM;
130+ }
131+ mapped = !reserved_va;
132+ } else if (shmflg & SHM_REMAP) {
133+ /*
134+ * If host page size > target page size, the host shmat may map
135+ * more memory than the guest expects. Reject a mapping that
136+ * would replace memory in the unexpected gap.
137+ * TODO: Could be fixed with softmmu.
138+ */
139+ if (t_len < h_len &&
140+ !page_check_range_empty(shmaddr + t_len,
141+ shmaddr + h_len - 1)) {
142+ return -TARGET_EINVAL;
143+ }
144 } else {
145- abi_ulong mmap_start;
146+ if (!page_check_range_empty(shmaddr, shmaddr + m_len - 1)) {
147+ return -TARGET_EINVAL;
148+ }
149+ }
150
151- /* In order to use the host shmat, we need to honor host SHMLBA. */
152- mmap_start = mmap_find_vma(0, shm_info.shm_segsz,
153- MAX(SHMLBA, shmlba));
154+ /* All placement is now complete. */
155+ want = (void *)g2h_untagged(shmaddr);
156
157- if (mmap_start == -1) {
158- return -TARGET_ENOMEM;
159+ /*
160+ * Map anonymous pages across the entire range, then remap with
161+ * the shared memory. This is required for a number of corner
162+ * cases for which host and guest page sizes differ.
163+ */
164+ if (h_len != t_len) {
165+ int mmap_p = PROT_READ | (shmflg & SHM_RDONLY ? 0 : PROT_WRITE);
166+ int mmap_f = MAP_PRIVATE | MAP_ANONYMOUS
167+ | (reserved_va || (shmflg & SHM_REMAP)
168+ ? MAP_FIXED : MAP_FIXED_NOREPLACE);
169+
170+ test = mmap(want, m_len, mmap_p, mmap_f, -1, 0);
171+ if (unlikely(test != want)) {
172+ /* shmat returns EINVAL not EEXIST like mmap. */
173+ ret = (test == MAP_FAILED && errno != EEXIST
174+ ? get_errno(-1) : -TARGET_EINVAL);
175+ if (mapped) {
176+ do_munmap(want, m_len);
177+ }
178+ return ret;
179 }
180- host_raddr = shmat(shmid, g2h_untagged(mmap_start),
181- shmflg | SHM_REMAP);
182+ mapped = true;
183 }
184
185- if (host_raddr == (void *)-1) {
186- return get_errno(-1);
187+ if (reserved_va || mapped) {
188+ shmflg |= SHM_REMAP;
189+ }
190+ test = shmat(shmid, want, shmflg);
191+ if (test == MAP_FAILED) {
192+ ret = get_errno(-1);
193+ if (mapped) {
194+ do_munmap(want, m_len);
195+ }
196+ return ret;
197 }
198- raddr = h2g(host_raddr);
199- last = raddr + shm_info.shm_segsz - 1;
200+ assert(test == want);
201
202- page_set_flags(raddr, last,
203+ last = shmaddr + m_len - 1;
204+ page_set_flags(shmaddr, last,
205 PAGE_VALID | PAGE_RESET | PAGE_READ |
206- (shmflg & SHM_RDONLY ? 0 : PAGE_WRITE));
207+ (shmflg & SHM_RDONLY ? 0 : PAGE_WRITE) |
208+ (shmflg & SHM_EXEC ? PAGE_EXEC : 0));
209
210- shm_region_rm_complete(raddr, last);
211- shm_region_add(raddr, last);
212+ shm_region_rm_complete(shmaddr, last);
213+ shm_region_add(shmaddr, last);
214 }
215
216 /*
217@@ -1138,7 +1230,15 @@ abi_ulong target_shmat(CPUArchState *cpu_env, int shmid,
218 tb_flush(cpu);
219 }
220
221- return raddr;
222+ if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
223+ FILE *f = qemu_log_trylock();
224+ if (f) {
225+ fprintf(f, "page layout changed following shmat\n");
226+ page_dump(f);
227+ qemu_log_unlock(f);
228+ }
229+ }
230+ return shmaddr;
231 }
232
233 abi_long target_shmdt(abi_ulong shmaddr)
234--
2352.34.1
236
diff --git a/meta/recipes-devtools/qemu/qemu/0005-tests-tcg-Check-that-shmat-does-not-break-proc-self-.patch b/meta/recipes-devtools/qemu/qemu/0005-tests-tcg-Check-that-shmat-does-not-break-proc-self-.patch
new file mode 100644
index 0000000000..5afb35ea0c
--- /dev/null
+++ b/meta/recipes-devtools/qemu/qemu/0005-tests-tcg-Check-that-shmat-does-not-break-proc-self-.patch
@@ -0,0 +1,85 @@
1From 1234063488134ad1f541f56dd30caa7896905f06 Mon Sep 17 00:00:00 2001
2From: Ilya Leoshkevich <iii@linux.ibm.com>
3Date: Wed, 28 Feb 2024 10:25:18 -1000
4Subject: [PATCH 5/5] tests/tcg: Check that shmat() does not break
5 /proc/self/maps
6
7Add a regression test for a recently fixed issue, where shmat()
8desynced the guest and the host view of the address space and caused
9open("/proc/self/maps") to SEGV.
10
11Upstream-Status: Submitted [https://www.mail-archive.com/qemu-devel@nongnu.org/msg1026793.html]
12
13Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
14Message-Id: <jwyuvao4apydvykmsnvacwshdgy3ixv7qvkh4dbxm3jkwgnttw@k4wpaayou7oq>
15Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
16Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
17---
18 tests/tcg/multiarch/linux/linux-shmat-maps.c | 55 ++++++++++++++++++++
19 1 file changed, 55 insertions(+)
20 create mode 100644 tests/tcg/multiarch/linux/linux-shmat-maps.c
21
22diff --git a/tests/tcg/multiarch/linux/linux-shmat-maps.c b/tests/tcg/multiarch/linux/linux-shmat-maps.c
23new file mode 100644
24index 000000000..0ccf7a973
25--- /dev/null
26+++ b/tests/tcg/multiarch/linux/linux-shmat-maps.c
27@@ -0,0 +1,55 @@
28+/*
29+ * Test that shmat() does not break /proc/self/maps.
30+ *
31+ * SPDX-License-Identifier: GPL-2.0-or-later
32+ */
33+#include <assert.h>
34+#include <fcntl.h>
35+#include <stdlib.h>
36+#include <sys/ipc.h>
37+#include <sys/shm.h>
38+#include <unistd.h>
39+
40+int main(void)
41+{
42+ char buf[128];
43+ int err, fd;
44+ int shmid;
45+ ssize_t n;
46+ void *p;
47+
48+ shmid = shmget(IPC_PRIVATE, 1, IPC_CREAT | 0600);
49+ assert(shmid != -1);
50+
51+ /*
52+ * The original bug required a non-NULL address, which skipped the
53+ * mmap_find_vma step, which could result in a host mapping smaller
54+ * than the target mapping. Choose an address at random.
55+ */
56+ p = shmat(shmid, (void *)0x800000, SHM_RND);
57+ if (p == (void *)-1) {
58+ /*
59+ * Because we are now running the testcase for all guests for which
60+ * we have a cross-compiler, the above random address might conflict
61+ * with the guest executable in some way. Rather than stopping,
62+ * continue with a system supplied address, which should never fail.
63+ */
64+ p = shmat(shmid, NULL, 0);
65+ assert(p != (void *)-1);
66+ }
67+
68+ fd = open("/proc/self/maps", O_RDONLY);
69+ assert(fd != -1);
70+ do {
71+ n = read(fd, buf, sizeof(buf));
72+ assert(n >= 0);
73+ } while (n != 0);
74+ close(fd);
75+
76+ err = shmdt(p);
77+ assert(err == 0);
78+ err = shmctl(shmid, IPC_RMID, NULL);
79+ assert(err == 0);
80+
81+ return EXIT_SUCCESS;
82+}
83--
842.34.1
85
diff --git a/meta/recipes-devtools/qemu/qemu/0011-linux-user-workaround-for-missing-MAP_FIXED_NOREPLAC.patch b/meta/recipes-devtools/qemu/qemu/0011-linux-user-workaround-for-missing-MAP_FIXED_NOREPLAC.patch
index 672d5458cd..cc53b1eedd 100644
--- a/meta/recipes-devtools/qemu/qemu/0011-linux-user-workaround-for-missing-MAP_FIXED_NOREPLAC.patch
+++ b/meta/recipes-devtools/qemu/qemu/0011-linux-user-workaround-for-missing-MAP_FIXED_NOREPLAC.patch
@@ -40,10 +40,10 @@ Signed-off-by: Mark Hatle <mark.hatle@amd.com>
40 create mode 100644 linux-user/mmap-fixed.c 40 create mode 100644 linux-user/mmap-fixed.c
41 create mode 100644 linux-user/mmap-fixed.h 41 create mode 100644 linux-user/mmap-fixed.h
42 42
43Index: qemu-8.2.0/linux-user/elfload.c 43Index: qemu-8.2.1/linux-user/elfload.c
44=================================================================== 44===================================================================
45--- qemu-8.2.0.orig/linux-user/elfload.c 45--- qemu-8.2.1.orig/linux-user/elfload.c
46+++ qemu-8.2.0/linux-user/elfload.c 46+++ qemu-8.2.1/linux-user/elfload.c
47@@ -22,6 +22,7 @@ 47@@ -22,6 +22,7 @@
48 #include "qemu/error-report.h" 48 #include "qemu/error-report.h"
49 #include "target_signal.h" 49 #include "target_signal.h"
@@ -65,10 +65,10 @@ Index: qemu-8.2.0/linux-user/elfload.c
65 int ret; 65 int ret;
66 66
67 if (p == MAP_FAILED) { 67 if (p == MAP_FAILED) {
68Index: qemu-8.2.0/linux-user/meson.build 68Index: qemu-8.2.1/linux-user/meson.build
69=================================================================== 69===================================================================
70--- qemu-8.2.0.orig/linux-user/meson.build 70--- qemu-8.2.1.orig/linux-user/meson.build
71+++ qemu-8.2.0/linux-user/meson.build 71+++ qemu-8.2.1/linux-user/meson.build
72@@ -14,6 +14,7 @@ linux_user_ss.add(files( 72@@ -14,6 +14,7 @@ linux_user_ss.add(files(
73 'linuxload.c', 73 'linuxload.c',
74 'main.c', 74 'main.c',
@@ -77,10 +77,10 @@ Index: qemu-8.2.0/linux-user/meson.build
77 'signal.c', 77 'signal.c',
78 'strace.c', 78 'strace.c',
79 'syscall.c', 79 'syscall.c',
80Index: qemu-8.2.0/linux-user/mmap-fixed.c 80Index: qemu-8.2.1/linux-user/mmap-fixed.c
81=================================================================== 81===================================================================
82--- /dev/null 82--- /dev/null
83+++ qemu-8.2.0/linux-user/mmap-fixed.c 83+++ qemu-8.2.1/linux-user/mmap-fixed.c
84@@ -0,0 +1,63 @@ 84@@ -0,0 +1,63 @@
85+/* 85+/*
86+ * Workaround for MAP_FIXED_NOREPLACE 86+ * Workaround for MAP_FIXED_NOREPLACE
@@ -145,10 +145,10 @@ Index: qemu-8.2.0/linux-user/mmap-fixed.c
145+} 145+}
146+ 146+
147+#endif 147+#endif
148Index: qemu-8.2.0/linux-user/mmap-fixed.h 148Index: qemu-8.2.1/linux-user/mmap-fixed.h
149=================================================================== 149===================================================================
150--- /dev/null 150--- /dev/null
151+++ qemu-8.2.0/linux-user/mmap-fixed.h 151+++ qemu-8.2.1/linux-user/mmap-fixed.h
152@@ -0,0 +1,39 @@ 152@@ -0,0 +1,39 @@
153+/* 153+/*
154+ * Workaround for MAP_FIXED_NOREPLACE 154+ * Workaround for MAP_FIXED_NOREPLACE
@@ -189,10 +189,10 @@ Index: qemu-8.2.0/linux-user/mmap-fixed.h
189+#endif /* MAP_FIXED_NOREPLACE */ 189+#endif /* MAP_FIXED_NOREPLACE */
190+ 190+
191+#endif /* MMAP_FIXED_H */ 191+#endif /* MMAP_FIXED_H */
192Index: qemu-8.2.0/linux-user/mmap.c 192Index: qemu-8.2.1/linux-user/mmap.c
193=================================================================== 193===================================================================
194--- qemu-8.2.0.orig/linux-user/mmap.c 194--- qemu-8.2.1.orig/linux-user/mmap.c
195+++ qemu-8.2.0/linux-user/mmap.c 195+++ qemu-8.2.1/linux-user/mmap.c
196@@ -25,6 +25,7 @@ 196@@ -25,6 +25,7 @@
197 #include "user-mmap.h" 197 #include "user-mmap.h"
198 #include "target_mman.h" 198 #include "target_mman.h"
@@ -201,7 +201,16 @@ Index: qemu-8.2.0/linux-user/mmap.c
201 201
202 #ifdef TARGET_ARM 202 #ifdef TARGET_ARM
203 #include "target/arm/cpu-features.h" 203 #include "target/arm/cpu-features.h"
204@@ -304,9 +305,9 @@ static bool mmap_frag(abi_ulong real_sta 204@@ -273,7 +274,7 @@ int target_mprotect(abi_ulong start, abi
205 static int do_munmap(void *addr, size_t len)
206 {
207 if (reserved_va) {
208- void *ptr = mmap(addr, len, PROT_NONE,
209+ void *ptr = mmap_fixed_noreplace(addr, len, PROT_NONE,
210 MAP_FIXED | MAP_ANONYMOUS
211 | MAP_PRIVATE | MAP_NORESERVE, -1, 0);
212 return ptr == addr ? 0 : -1;
213@@ -319,9 +320,9 @@ static bool mmap_frag(abi_ulong real_sta
205 * outside of the fragment we need to map. Allocate a new host 214 * outside of the fragment we need to map. Allocate a new host
206 * page to cover, discarding whatever else may have been present. 215 * page to cover, discarding whatever else may have been present.
207 */ 216 */
@@ -214,7 +223,7 @@ Index: qemu-8.2.0/linux-user/mmap.c
214 if (p != host_start) { 223 if (p != host_start) {
215 if (p != MAP_FAILED) { 224 if (p != MAP_FAILED) {
216 munmap(p, qemu_host_page_size); 225 munmap(p, qemu_host_page_size);
217@@ -405,8 +406,9 @@ abi_ulong mmap_find_vma(abi_ulong start, 226@@ -420,8 +421,9 @@ abi_ulong mmap_find_vma(abi_ulong start,
218 * - mremap() with MREMAP_FIXED flag 227 * - mremap() with MREMAP_FIXED flag
219 * - shmat() with SHM_REMAP flag 228 * - shmat() with SHM_REMAP flag
220 */ 229 */
@@ -226,7 +235,7 @@ Index: qemu-8.2.0/linux-user/mmap.c
226 235
227 /* ENOMEM, if host address space has no memory */ 236 /* ENOMEM, if host address space has no memory */
228 if (ptr == MAP_FAILED) { 237 if (ptr == MAP_FAILED) {
229@@ -600,16 +602,16 @@ abi_long target_mmap(abi_ulong start, ab 238@@ -615,16 +617,16 @@ abi_long target_mmap(abi_ulong start, ab
230 * especially important if qemu_host_page_size > 239 * especially important if qemu_host_page_size >
231 * qemu_real_host_page_size. 240 * qemu_real_host_page_size.
232 */ 241 */
@@ -247,7 +256,7 @@ Index: qemu-8.2.0/linux-user/mmap.c
247 if (p == MAP_FAILED) { 256 if (p == MAP_FAILED) {
248 munmap(g2h_untagged(start), host_len); 257 munmap(g2h_untagged(start), host_len);
249 goto fail; 258 goto fail;
250@@ -734,8 +736,9 @@ abi_long target_mmap(abi_ulong start, ab 259@@ -749,8 +751,9 @@ abi_long target_mmap(abi_ulong start, ab
251 len1 = real_last - real_start + 1; 260 len1 = real_last - real_start + 1;
252 want_p = g2h_untagged(real_start); 261 want_p = g2h_untagged(real_start);
253 262
@@ -259,23 +268,10 @@ Index: qemu-8.2.0/linux-user/mmap.c
259 if (p != want_p) { 268 if (p != want_p) {
260 if (p != MAP_FAILED) { 269 if (p != MAP_FAILED) {
261 munmap(p, len1); 270 munmap(p, len1);
262@@ -837,9 +840,9 @@ static int mmap_reserve_or_unmap(abi_ulo 271Index: qemu-8.2.1/linux-user/syscall.c
263 host_start = g2h_untagged(real_start);
264
265 if (reserved_va) {
266- void *ptr = mmap(host_start, real_len, PROT_NONE,
267- MAP_FIXED | MAP_ANONYMOUS
268- | MAP_PRIVATE | MAP_NORESERVE, -1, 0);
269+ void *ptr = mmap_fixed_noreplace(host_start, real_len, PROT_NONE,
270+ MAP_FIXED | MAP_ANONYMOUS
271+ | MAP_PRIVATE | MAP_NORESERVE, -1, 0);
272 return ptr == host_start ? 0 : -1;
273 }
274 return munmap(host_start, real_len);
275Index: qemu-8.2.0/linux-user/syscall.c
276=================================================================== 272===================================================================
277--- qemu-8.2.0.orig/linux-user/syscall.c 273--- qemu-8.2.1.orig/linux-user/syscall.c
278+++ qemu-8.2.0/linux-user/syscall.c 274+++ qemu-8.2.1/linux-user/syscall.c
279@@ -145,6 +145,7 @@ 275@@ -145,6 +145,7 @@
280 #include "qapi/error.h" 276 #include "qapi/error.h"
281 #include "fd-trans.h" 277 #include "fd-trans.h"
diff --git a/meta/recipes-devtools/qemu/qemu/4a8579ad8629b57a43daa62e46cc7af6e1078116.patch b/meta/recipes-devtools/qemu/qemu/4a8579ad8629b57a43daa62e46cc7af6e1078116.patch
new file mode 100644
index 0000000000..5ad859ebe6
--- /dev/null
+++ b/meta/recipes-devtools/qemu/qemu/4a8579ad8629b57a43daa62e46cc7af6e1078116.patch
@@ -0,0 +1,60 @@
1From 4a8579ad8629b57a43daa62e46cc7af6e1078116 Mon Sep 17 00:00:00 2001
2From: Richard Henderson <richard.henderson@linaro.org>
3Date: Tue, 13 Feb 2024 10:20:27 -1000
4Subject: [PATCH] linux-user: Split out do_munmap
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9Upstream-Status: Submitted [https://gitlab.com/rth7680/qemu/-/commit/4a8579ad8629b57a43daa62e46cc7af6e1078116]
10
11Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13---
14 linux-user/mmap.c | 23 ++++++++++++++++-------
15 1 file changed, 16 insertions(+), 7 deletions(-)
16
17diff --git a/linux-user/mmap.c b/linux-user/mmap.c
18index 1bbfeb25b14..8ebcca44444 100644
19--- a/linux-user/mmap.c
20+++ b/linux-user/mmap.c
21@@ -267,6 +267,21 @@ int target_mprotect(abi_ulong start, abi_ulong len, int target_prot)
22 return ret;
23 }
24
25+/*
26+ * Perform munmap on behalf of the target, with host parameters.
27+ * If reserved_va, we must replace the memory reservation.
28+ */
29+static int do_munmap(void *addr, size_t len)
30+{
31+ if (reserved_va) {
32+ void *ptr = mmap(addr, len, PROT_NONE,
33+ MAP_FIXED | MAP_ANONYMOUS
34+ | MAP_PRIVATE | MAP_NORESERVE, -1, 0);
35+ return ptr == addr ? 0 : -1;
36+ }
37+ return munmap(addr, len);
38+}
39+
40 /* map an incomplete host page */
41 static bool mmap_frag(abi_ulong real_start, abi_ulong start, abi_ulong last,
42 int prot, int flags, int fd, off_t offset)
43@@ -854,13 +869,7 @@ static int mmap_reserve_or_unmap(abi_ulong start, abi_ulong len)
44 real_len = real_last - real_start + 1;
45 host_start = g2h_untagged(real_start);
46
47- if (reserved_va) {
48- void *ptr = mmap(host_start, real_len, PROT_NONE,
49- MAP_FIXED | MAP_ANONYMOUS
50- | MAP_PRIVATE | MAP_NORESERVE, -1, 0);
51- return ptr == host_start ? 0 : -1;
52- }
53- return munmap(host_start, real_len);
54+ return do_munmap(host_start, real_len);
55 }
56
57 int target_munmap(abi_ulong start, abi_ulong len)
58--
59GitLab
60
diff --git a/meta/recipes-devtools/qemu/qemu/fix_segv.patch b/meta/recipes-devtools/qemu/qemu/fix_segv.patch
deleted file mode 100644
index da5ae87e0c..0000000000
--- a/meta/recipes-devtools/qemu/qemu/fix_segv.patch
+++ /dev/null
@@ -1,47 +0,0 @@
1With qemu 8.2.0 we started seeing SEGV errors when compiling webkitgtk from
2usermode qemu:
3
4qemu-x86_64: QEMU internal SIGSEGV {code=MAPERR, addr=0x20}
5Segmentation fault
6
7By bisection, this was tracked down to:
8
9commit 7b7a3366e142d3baeb3fd1d3660a50e7956c19eb
10Author: Richard Henderson <richard.henderson@linaro.org>
11Date: Tue Aug 8 20:02:19 2023 -0700
12
13 linux-user: Use walk_memory_regions for open_self_maps
14
15 Replace the by-hand method of region identification with
16 the official user-exec interface. Cross-check the region
17 provided to the callback with the interval tree from
18 read_self_maps().
19
20 Tested-by: Helge Deller <deller@gmx.de>
21 Reviewed-by: Ilya Leoshkevich <iii@linux.ibm.com>
22 Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
23
24and specifically to 'n' being NULL. For now, just skip in that case
25until a proper fix can be identified.
26
27Reported upstream: https://www.mail-archive.com/qemu-devel@nongnu.org/msg1018813.html
28
29YOCTO #15367
30
31Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
32Upstream-Status: Pending
33
34diff --git a/linux-user/syscall.c b/linux-user/syscall.c
35index e384e14248..2577fb770d 100644
36--- a/linux-user/syscall.c
37+++ b/linux-user/syscall.c
38@@ -8085,6 +8085,9 @@ static int open_self_maps_2(void *opaque, target_ulong guest_start,
39 while (1) {
40 IntervalTreeNode *n =
41 interval_tree_iter_first(d->host_maps, host_start, host_start);
42+ if (!n) {
43+ return 0;
44+ }
45 MapInfo *mi = container_of(n, MapInfo, itree);
46 uintptr_t this_hlast = MIN(host_last, n->last);
47 target_ulong this_gend = h2g(this_hlast) + 1;