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>
This commit is contained in:
Richard Purdie
2024-02-29 12:32:12 +00:00
parent 9b5c6444f7
commit 9d1a99cf45
9 changed files with 586 additions and 81 deletions

View File

@@ -33,7 +33,12 @@ SRC_URI = "https://download.qemu.org/${BPN}-${PV}.tar.xz \
file://0002-linux-user-Replace-use-of-lfs64-related-functions-an.patch \
file://fixedmeson.patch \
file://no-pip.patch \
file://fix_segv.patch \
file://4a8579ad8629b57a43daa62e46cc7af6e1078116.patch \
file://0001-linux-user-x86_64-Handle-the-vsyscall-page-in-open_s.patch \
file://0002-linux-user-loongarch64-Remove-TARGET_FORCE_SHMLBA.patch \
file://0003-linux-user-Add-strace-for-shmat.patch \
file://0004-linux-user-Rewrite-target_shmat.patch \
file://0005-tests-tcg-Check-that-shmat-does-not-break-proc-self-.patch \
file://qemu-guest-agent.init \
file://qemu-guest-agent.udev \
"

View File

@@ -0,0 +1,56 @@
From 4517e2046610722879761bcdb60edbb2b929c848 Mon Sep 17 00:00:00 2001
From: Richard Henderson <richard.henderson@linaro.org>
Date: Wed, 28 Feb 2024 10:25:14 -1000
Subject: [PATCH 1/5] linux-user/x86_64: Handle the vsyscall page in
open_self_maps_{2,4}
This is the only case in which we expect to have no host memory backing
for a guest memory page, because in general linux user processes cannot
map any pages in the top half of the 64-bit address space.
Upstream-Status: Submitted [https://www.mail-archive.com/qemu-devel@nongnu.org/msg1026793.html]
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2170
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
---
linux-user/syscall.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index a114f29a8..8307a8a61 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -7922,6 +7922,10 @@ static void open_self_maps_4(const struct open_self_maps_data *d,
path = "[heap]";
} else if (start == info->vdso) {
path = "[vdso]";
+#ifdef TARGET_X86_64
+ } else if (start == TARGET_VSYSCALL_PAGE) {
+ path = "[vsyscall]";
+#endif
}
/* Except null device (MAP_ANON), adjust offset for this fragment. */
@@ -8010,6 +8014,18 @@ static int open_self_maps_2(void *opaque, target_ulong guest_start,
uintptr_t host_start = (uintptr_t)g2h_untagged(guest_start);
uintptr_t host_last = (uintptr_t)g2h_untagged(guest_end - 1);
+#ifdef TARGET_X86_64
+ /*
+ * Because of the extremely high position of the page within the guest
+ * virtual address space, this is not backed by host memory at all.
+ * Therefore the loop below would fail. This is the only instance
+ * of not having host backing memory.
+ */
+ if (guest_start == TARGET_VSYSCALL_PAGE) {
+ return open_self_maps_3(opaque, guest_start, guest_end, flags);
+ }
+#endif
+
while (1) {
IntervalTreeNode *n =
interval_tree_iter_first(d->host_maps, host_start, host_start);
--
2.34.1

View File

@@ -0,0 +1,43 @@
From 5bf65b24414d3ff8339f6f1beb221c7c35c91e5d Mon Sep 17 00:00:00 2001
From: Richard Henderson <richard.henderson@linaro.org>
Date: Wed, 28 Feb 2024 10:25:15 -1000
Subject: [PATCH 2/5] linux-user/loongarch64: Remove TARGET_FORCE_SHMLBA
The kernel abi was changed with
commit d23b77953f5a4fbf94c05157b186aac2a247ae32
Author: Huacai Chen <chenhuacai@kernel.org>
Date: Wed Jan 17 12:43:08 2024 +0800
LoongArch: Change SHMLBA from SZ_64K to PAGE_SIZE
during the v6.8 cycle.
Upstream-Status: Submitted [https://www.mail-archive.com/qemu-devel@nongnu.org/msg1026793.html]
Reviewed-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
---
linux-user/loongarch64/target_syscall.h | 7 -------
1 file changed, 7 deletions(-)
diff --git a/linux-user/loongarch64/target_syscall.h b/linux-user/loongarch64/target_syscall.h
index 8b5de5212..39f229bb9 100644
--- a/linux-user/loongarch64/target_syscall.h
+++ b/linux-user/loongarch64/target_syscall.h
@@ -38,11 +38,4 @@ struct target_pt_regs {
#define TARGET_MCL_FUTURE 2
#define TARGET_MCL_ONFAULT 4
-#define TARGET_FORCE_SHMLBA
-
-static inline abi_ulong target_shmlba(CPULoongArchState *env)
-{
- return 64 * KiB;
-}
-
#endif
--
2.34.1

View File

@@ -0,0 +1,71 @@
From e8f06676c6c88e12cd5f4f81a839b7111c683596 Mon Sep 17 00:00:00 2001
From: Richard Henderson <richard.henderson@linaro.org>
Date: Wed, 28 Feb 2024 10:25:16 -1000
Subject: [PATCH 3/5] linux-user: Add strace for shmat
Upstream-Status: Submitted [https://www.mail-archive.com/qemu-devel@nongnu.org/msg1026793.html]
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
---
linux-user/strace.c | 23 +++++++++++++++++++++++
linux-user/strace.list | 2 +-
2 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/linux-user/strace.c b/linux-user/strace.c
index cf26e5526..47d6ec326 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -670,6 +670,25 @@ print_semctl(CPUArchState *cpu_env, const struct syscallname *name,
}
#endif
+static void
+print_shmat(CPUArchState *cpu_env, const struct syscallname *name,
+ abi_long arg0, abi_long arg1, abi_long arg2,
+ abi_long arg3, abi_long arg4, abi_long arg5)
+{
+ static const struct flags shmat_flags[] = {
+ FLAG_GENERIC(SHM_RND),
+ FLAG_GENERIC(SHM_REMAP),
+ FLAG_GENERIC(SHM_RDONLY),
+ FLAG_GENERIC(SHM_EXEC),
+ };
+
+ print_syscall_prologue(name);
+ print_raw_param(TARGET_ABI_FMT_ld, arg0, 0);
+ print_pointer(arg1, 0);
+ print_flags(shmat_flags, arg2, 1);
+ print_syscall_epilogue(name);
+}
+
#ifdef TARGET_NR_ipc
static void
print_ipc(CPUArchState *cpu_env, const struct syscallname *name,
@@ -683,6 +702,10 @@ print_ipc(CPUArchState *cpu_env, const struct syscallname *name,
print_ipc_cmd(arg3);
qemu_log(",0x" TARGET_ABI_FMT_lx ")", arg4);
break;
+ case IPCOP_shmat:
+ print_shmat(cpu_env, &(const struct syscallname){ .name = "shmat" },
+ arg1, arg4, arg2, 0, 0, 0);
+ break;
default:
qemu_log(("%s("
TARGET_ABI_FMT_ld ","
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 6655d4f26..dfd4237d1 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -1398,7 +1398,7 @@
{ TARGET_NR_sgetmask, "sgetmask" , NULL, NULL, NULL },
#endif
#ifdef TARGET_NR_shmat
-{ TARGET_NR_shmat, "shmat" , NULL, NULL, print_syscall_ret_addr },
+{ TARGET_NR_shmat, "shmat" , NULL, print_shmat, print_syscall_ret_addr },
#endif
#ifdef TARGET_NR_shmctl
{ TARGET_NR_shmctl, "shmctl" , NULL, NULL, NULL },
--
2.34.1

View File

@@ -0,0 +1,236 @@
From cb48d5d1592e63ebd0d4a3e300ef98e38e6306d7 Mon Sep 17 00:00:00 2001
From: Richard Henderson <richard.henderson@linaro.org>
Date: Wed, 28 Feb 2024 10:25:17 -1000
Subject: [PATCH 4/5] linux-user: Rewrite target_shmat
Handle combined host and guest alignment requirements.
Handle host and guest page size differences.
Handle SHM_EXEC.
Upstream-Status: Submitted [https://www.mail-archive.com/qemu-devel@nongnu.org/msg1026793.html]
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/115
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
---
linux-user/mmap.c | 166 +++++++++++++++++++++++++++++++++++++---------
1 file changed, 133 insertions(+), 33 deletions(-)
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 18fb3aaf7..6a2f649bb 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -1062,69 +1062,161 @@ static inline abi_ulong target_shmlba(CPUArchState *cpu_env)
}
#endif
+#if defined(__arm__) || defined(__mips__) || defined(__sparc__)
+#define HOST_FORCE_SHMLBA 1
+#else
+#define HOST_FORCE_SHMLBA 0
+#endif
+
abi_ulong target_shmat(CPUArchState *cpu_env, int shmid,
abi_ulong shmaddr, int shmflg)
{
CPUState *cpu = env_cpu(cpu_env);
- abi_ulong raddr;
struct shmid_ds shm_info;
int ret;
- abi_ulong shmlba;
+ int h_pagesize;
+ int t_shmlba, h_shmlba, m_shmlba;
+ size_t t_len, h_len, m_len;
/* shmat pointers are always untagged */
- /* find out the length of the shared memory segment */
+ /*
+ * Because we can't use host shmat() unless the address is sufficiently
+ * aligned for the host, we'll need to check both.
+ * TODO: Could be fixed with softmmu.
+ */
+ t_shmlba = target_shmlba(cpu_env);
+ h_pagesize = qemu_real_host_page_size();
+ h_shmlba = (HOST_FORCE_SHMLBA ? SHMLBA : h_pagesize);
+ m_shmlba = MAX(t_shmlba, h_shmlba);
+
+ if (shmaddr) {
+ if (shmaddr & (m_shmlba - 1)) {
+ if (shmflg & SHM_RND) {
+ /*
+ * The guest is allowing the kernel to round the address.
+ * Assume that the guest is ok with us rounding to the
+ * host required alignment too. Anyway if we don't, we'll
+ * get an error from the kernel.
+ */
+ shmaddr &= ~(m_shmlba - 1);
+ if (shmaddr == 0 && (shmflg & SHM_REMAP)) {
+ return -TARGET_EINVAL;
+ }
+ } else {
+ int require = TARGET_PAGE_SIZE;
+#ifdef TARGET_FORCE_SHMLBA
+ require = t_shmlba;
+#endif
+ /*
+ * Include host required alignment, as otherwise we cannot
+ * use host shmat at all.
+ */
+ require = MAX(require, h_shmlba);
+ if (shmaddr & (require - 1)) {
+ return -TARGET_EINVAL;
+ }
+ }
+ }
+ } else {
+ if (shmflg & SHM_REMAP) {
+ return -TARGET_EINVAL;
+ }
+ }
+ /* All rounding now manually concluded. */
+ shmflg &= ~SHM_RND;
+
+ /* Find out the length of the shared memory segment. */
ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
if (is_error(ret)) {
/* can't get length, bail out */
return ret;
}
+ t_len = TARGET_PAGE_ALIGN(shm_info.shm_segsz);
+ h_len = ROUND_UP(shm_info.shm_segsz, h_pagesize);
+ m_len = MAX(t_len, h_len);
- shmlba = target_shmlba(cpu_env);
-
- if (shmaddr & (shmlba - 1)) {
- if (shmflg & SHM_RND) {
- shmaddr &= ~(shmlba - 1);
- } else {
- return -TARGET_EINVAL;
- }
- }
- if (!guest_range_valid_untagged(shmaddr, shm_info.shm_segsz)) {
+ if (!guest_range_valid_untagged(shmaddr, m_len)) {
return -TARGET_EINVAL;
}
WITH_MMAP_LOCK_GUARD() {
- void *host_raddr;
+ bool mapped = false;
+ void *want, *test;
abi_ulong last;
- if (shmaddr) {
- host_raddr = shmat(shmid, (void *)g2h_untagged(shmaddr), shmflg);
+ if (!shmaddr) {
+ shmaddr = mmap_find_vma(0, m_len, m_shmlba);
+ if (shmaddr == -1) {
+ return -TARGET_ENOMEM;
+ }
+ mapped = !reserved_va;
+ } else if (shmflg & SHM_REMAP) {
+ /*
+ * If host page size > target page size, the host shmat may map
+ * more memory than the guest expects. Reject a mapping that
+ * would replace memory in the unexpected gap.
+ * TODO: Could be fixed with softmmu.
+ */
+ if (t_len < h_len &&
+ !page_check_range_empty(shmaddr + t_len,
+ shmaddr + h_len - 1)) {
+ return -TARGET_EINVAL;
+ }
} else {
- abi_ulong mmap_start;
+ if (!page_check_range_empty(shmaddr, shmaddr + m_len - 1)) {
+ return -TARGET_EINVAL;
+ }
+ }
- /* In order to use the host shmat, we need to honor host SHMLBA. */
- mmap_start = mmap_find_vma(0, shm_info.shm_segsz,
- MAX(SHMLBA, shmlba));
+ /* All placement is now complete. */
+ want = (void *)g2h_untagged(shmaddr);
- if (mmap_start == -1) {
- return -TARGET_ENOMEM;
+ /*
+ * Map anonymous pages across the entire range, then remap with
+ * the shared memory. This is required for a number of corner
+ * cases for which host and guest page sizes differ.
+ */
+ if (h_len != t_len) {
+ int mmap_p = PROT_READ | (shmflg & SHM_RDONLY ? 0 : PROT_WRITE);
+ int mmap_f = MAP_PRIVATE | MAP_ANONYMOUS
+ | (reserved_va || (shmflg & SHM_REMAP)
+ ? MAP_FIXED : MAP_FIXED_NOREPLACE);
+
+ test = mmap(want, m_len, mmap_p, mmap_f, -1, 0);
+ if (unlikely(test != want)) {
+ /* shmat returns EINVAL not EEXIST like mmap. */
+ ret = (test == MAP_FAILED && errno != EEXIST
+ ? get_errno(-1) : -TARGET_EINVAL);
+ if (mapped) {
+ do_munmap(want, m_len);
+ }
+ return ret;
}
- host_raddr = shmat(shmid, g2h_untagged(mmap_start),
- shmflg | SHM_REMAP);
+ mapped = true;
}
- if (host_raddr == (void *)-1) {
- return get_errno(-1);
+ if (reserved_va || mapped) {
+ shmflg |= SHM_REMAP;
+ }
+ test = shmat(shmid, want, shmflg);
+ if (test == MAP_FAILED) {
+ ret = get_errno(-1);
+ if (mapped) {
+ do_munmap(want, m_len);
+ }
+ return ret;
}
- raddr = h2g(host_raddr);
- last = raddr + shm_info.shm_segsz - 1;
+ assert(test == want);
- page_set_flags(raddr, last,
+ last = shmaddr + m_len - 1;
+ page_set_flags(shmaddr, last,
PAGE_VALID | PAGE_RESET | PAGE_READ |
- (shmflg & SHM_RDONLY ? 0 : PAGE_WRITE));
+ (shmflg & SHM_RDONLY ? 0 : PAGE_WRITE) |
+ (shmflg & SHM_EXEC ? PAGE_EXEC : 0));
- shm_region_rm_complete(raddr, last);
- shm_region_add(raddr, last);
+ shm_region_rm_complete(shmaddr, last);
+ shm_region_add(shmaddr, last);
}
/*
@@ -1138,7 +1230,15 @@ abi_ulong target_shmat(CPUArchState *cpu_env, int shmid,
tb_flush(cpu);
}
- return raddr;
+ if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
+ FILE *f = qemu_log_trylock();
+ if (f) {
+ fprintf(f, "page layout changed following shmat\n");
+ page_dump(f);
+ qemu_log_unlock(f);
+ }
+ }
+ return shmaddr;
}
abi_long target_shmdt(abi_ulong shmaddr)
--
2.34.1

View File

@@ -0,0 +1,85 @@
From 1234063488134ad1f541f56dd30caa7896905f06 Mon Sep 17 00:00:00 2001
From: Ilya Leoshkevich <iii@linux.ibm.com>
Date: Wed, 28 Feb 2024 10:25:18 -1000
Subject: [PATCH 5/5] tests/tcg: Check that shmat() does not break
/proc/self/maps
Add a regression test for a recently fixed issue, where shmat()
desynced the guest and the host view of the address space and caused
open("/proc/self/maps") to SEGV.
Upstream-Status: Submitted [https://www.mail-archive.com/qemu-devel@nongnu.org/msg1026793.html]
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
Message-Id: <jwyuvao4apydvykmsnvacwshdgy3ixv7qvkh4dbxm3jkwgnttw@k4wpaayou7oq>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
---
tests/tcg/multiarch/linux/linux-shmat-maps.c | 55 ++++++++++++++++++++
1 file changed, 55 insertions(+)
create mode 100644 tests/tcg/multiarch/linux/linux-shmat-maps.c
diff --git a/tests/tcg/multiarch/linux/linux-shmat-maps.c b/tests/tcg/multiarch/linux/linux-shmat-maps.c
new file mode 100644
index 000000000..0ccf7a973
--- /dev/null
+++ b/tests/tcg/multiarch/linux/linux-shmat-maps.c
@@ -0,0 +1,55 @@
+/*
+ * Test that shmat() does not break /proc/self/maps.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#include <assert.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <unistd.h>
+
+int main(void)
+{
+ char buf[128];
+ int err, fd;
+ int shmid;
+ ssize_t n;
+ void *p;
+
+ shmid = shmget(IPC_PRIVATE, 1, IPC_CREAT | 0600);
+ assert(shmid != -1);
+
+ /*
+ * The original bug required a non-NULL address, which skipped the
+ * mmap_find_vma step, which could result in a host mapping smaller
+ * than the target mapping. Choose an address at random.
+ */
+ p = shmat(shmid, (void *)0x800000, SHM_RND);
+ if (p == (void *)-1) {
+ /*
+ * Because we are now running the testcase for all guests for which
+ * we have a cross-compiler, the above random address might conflict
+ * with the guest executable in some way. Rather than stopping,
+ * continue with a system supplied address, which should never fail.
+ */
+ p = shmat(shmid, NULL, 0);
+ assert(p != (void *)-1);
+ }
+
+ fd = open("/proc/self/maps", O_RDONLY);
+ assert(fd != -1);
+ do {
+ n = read(fd, buf, sizeof(buf));
+ assert(n >= 0);
+ } while (n != 0);
+ close(fd);
+
+ err = shmdt(p);
+ assert(err == 0);
+ err = shmctl(shmid, IPC_RMID, NULL);
+ assert(err == 0);
+
+ return EXIT_SUCCESS;
+}
--
2.34.1

View File

@@ -40,10 +40,10 @@ Signed-off-by: Mark Hatle <mark.hatle@amd.com>
create mode 100644 linux-user/mmap-fixed.c
create mode 100644 linux-user/mmap-fixed.h
Index: qemu-8.2.0/linux-user/elfload.c
Index: qemu-8.2.1/linux-user/elfload.c
===================================================================
--- qemu-8.2.0.orig/linux-user/elfload.c
+++ qemu-8.2.0/linux-user/elfload.c
--- qemu-8.2.1.orig/linux-user/elfload.c
+++ qemu-8.2.1/linux-user/elfload.c
@@ -22,6 +22,7 @@
#include "qemu/error-report.h"
#include "target_signal.h"
@@ -65,10 +65,10 @@ Index: qemu-8.2.0/linux-user/elfload.c
int ret;
if (p == MAP_FAILED) {
Index: qemu-8.2.0/linux-user/meson.build
Index: qemu-8.2.1/linux-user/meson.build
===================================================================
--- qemu-8.2.0.orig/linux-user/meson.build
+++ qemu-8.2.0/linux-user/meson.build
--- qemu-8.2.1.orig/linux-user/meson.build
+++ qemu-8.2.1/linux-user/meson.build
@@ -14,6 +14,7 @@ linux_user_ss.add(files(
'linuxload.c',
'main.c',
@@ -77,10 +77,10 @@ Index: qemu-8.2.0/linux-user/meson.build
'signal.c',
'strace.c',
'syscall.c',
Index: qemu-8.2.0/linux-user/mmap-fixed.c
Index: qemu-8.2.1/linux-user/mmap-fixed.c
===================================================================
--- /dev/null
+++ qemu-8.2.0/linux-user/mmap-fixed.c
+++ qemu-8.2.1/linux-user/mmap-fixed.c
@@ -0,0 +1,63 @@
+/*
+ * Workaround for MAP_FIXED_NOREPLACE
@@ -145,10 +145,10 @@ Index: qemu-8.2.0/linux-user/mmap-fixed.c
+}
+
+#endif
Index: qemu-8.2.0/linux-user/mmap-fixed.h
Index: qemu-8.2.1/linux-user/mmap-fixed.h
===================================================================
--- /dev/null
+++ qemu-8.2.0/linux-user/mmap-fixed.h
+++ qemu-8.2.1/linux-user/mmap-fixed.h
@@ -0,0 +1,39 @@
+/*
+ * Workaround for MAP_FIXED_NOREPLACE
@@ -189,10 +189,10 @@ Index: qemu-8.2.0/linux-user/mmap-fixed.h
+#endif /* MAP_FIXED_NOREPLACE */
+
+#endif /* MMAP_FIXED_H */
Index: qemu-8.2.0/linux-user/mmap.c
Index: qemu-8.2.1/linux-user/mmap.c
===================================================================
--- qemu-8.2.0.orig/linux-user/mmap.c
+++ qemu-8.2.0/linux-user/mmap.c
--- qemu-8.2.1.orig/linux-user/mmap.c
+++ qemu-8.2.1/linux-user/mmap.c
@@ -25,6 +25,7 @@
#include "user-mmap.h"
#include "target_mman.h"
@@ -201,7 +201,16 @@ Index: qemu-8.2.0/linux-user/mmap.c
#ifdef TARGET_ARM
#include "target/arm/cpu-features.h"
@@ -304,9 +305,9 @@ static bool mmap_frag(abi_ulong real_sta
@@ -273,7 +274,7 @@ int target_mprotect(abi_ulong start, abi
static int do_munmap(void *addr, size_t len)
{
if (reserved_va) {
- void *ptr = mmap(addr, len, PROT_NONE,
+ void *ptr = mmap_fixed_noreplace(addr, len, PROT_NONE,
MAP_FIXED | MAP_ANONYMOUS
| MAP_PRIVATE | MAP_NORESERVE, -1, 0);
return ptr == addr ? 0 : -1;
@@ -319,9 +320,9 @@ static bool mmap_frag(abi_ulong real_sta
* outside of the fragment we need to map. Allocate a new host
* page to cover, discarding whatever else may have been present.
*/
@@ -214,7 +223,7 @@ Index: qemu-8.2.0/linux-user/mmap.c
if (p != host_start) {
if (p != MAP_FAILED) {
munmap(p, qemu_host_page_size);
@@ -405,8 +406,9 @@ abi_ulong mmap_find_vma(abi_ulong start,
@@ -420,8 +421,9 @@ abi_ulong mmap_find_vma(abi_ulong start,
* - mremap() with MREMAP_FIXED flag
* - shmat() with SHM_REMAP flag
*/
@@ -226,7 +235,7 @@ Index: qemu-8.2.0/linux-user/mmap.c
/* ENOMEM, if host address space has no memory */
if (ptr == MAP_FAILED) {
@@ -600,16 +602,16 @@ abi_long target_mmap(abi_ulong start, ab
@@ -615,16 +617,16 @@ abi_long target_mmap(abi_ulong start, ab
* especially important if qemu_host_page_size >
* qemu_real_host_page_size.
*/
@@ -247,7 +256,7 @@ Index: qemu-8.2.0/linux-user/mmap.c
if (p == MAP_FAILED) {
munmap(g2h_untagged(start), host_len);
goto fail;
@@ -734,8 +736,9 @@ abi_long target_mmap(abi_ulong start, ab
@@ -749,8 +751,9 @@ abi_long target_mmap(abi_ulong start, ab
len1 = real_last - real_start + 1;
want_p = g2h_untagged(real_start);
@@ -259,23 +268,10 @@ Index: qemu-8.2.0/linux-user/mmap.c
if (p != want_p) {
if (p != MAP_FAILED) {
munmap(p, len1);
@@ -837,9 +840,9 @@ static int mmap_reserve_or_unmap(abi_ulo
host_start = g2h_untagged(real_start);
if (reserved_va) {
- void *ptr = mmap(host_start, real_len, PROT_NONE,
- MAP_FIXED | MAP_ANONYMOUS
- | MAP_PRIVATE | MAP_NORESERVE, -1, 0);
+ void *ptr = mmap_fixed_noreplace(host_start, real_len, PROT_NONE,
+ MAP_FIXED | MAP_ANONYMOUS
+ | MAP_PRIVATE | MAP_NORESERVE, -1, 0);
return ptr == host_start ? 0 : -1;
}
return munmap(host_start, real_len);
Index: qemu-8.2.0/linux-user/syscall.c
Index: qemu-8.2.1/linux-user/syscall.c
===================================================================
--- qemu-8.2.0.orig/linux-user/syscall.c
+++ qemu-8.2.0/linux-user/syscall.c
--- qemu-8.2.1.orig/linux-user/syscall.c
+++ qemu-8.2.1/linux-user/syscall.c
@@ -145,6 +145,7 @@
#include "qapi/error.h"
#include "fd-trans.h"

View File

@@ -0,0 +1,60 @@
From 4a8579ad8629b57a43daa62e46cc7af6e1078116 Mon Sep 17 00:00:00 2001
From: Richard Henderson <richard.henderson@linaro.org>
Date: Tue, 13 Feb 2024 10:20:27 -1000
Subject: [PATCH] linux-user: Split out do_munmap
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Upstream-Status: Submitted [https://gitlab.com/rth7680/qemu/-/commit/4a8579ad8629b57a43daa62e46cc7af6e1078116]
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/mmap.c | 23 ++++++++++++++++-------
1 file changed, 16 insertions(+), 7 deletions(-)
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 1bbfeb25b14..8ebcca44444 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -267,6 +267,21 @@ int target_mprotect(abi_ulong start, abi_ulong len, int target_prot)
return ret;
}
+/*
+ * Perform munmap on behalf of the target, with host parameters.
+ * If reserved_va, we must replace the memory reservation.
+ */
+static int do_munmap(void *addr, size_t len)
+{
+ if (reserved_va) {
+ void *ptr = mmap(addr, len, PROT_NONE,
+ MAP_FIXED | MAP_ANONYMOUS
+ | MAP_PRIVATE | MAP_NORESERVE, -1, 0);
+ return ptr == addr ? 0 : -1;
+ }
+ return munmap(addr, len);
+}
+
/* map an incomplete host page */
static bool mmap_frag(abi_ulong real_start, abi_ulong start, abi_ulong last,
int prot, int flags, int fd, off_t offset)
@@ -854,13 +869,7 @@ static int mmap_reserve_or_unmap(abi_ulong start, abi_ulong len)
real_len = real_last - real_start + 1;
host_start = g2h_untagged(real_start);
- if (reserved_va) {
- void *ptr = mmap(host_start, real_len, PROT_NONE,
- MAP_FIXED | MAP_ANONYMOUS
- | MAP_PRIVATE | MAP_NORESERVE, -1, 0);
- return ptr == host_start ? 0 : -1;
- }
- return munmap(host_start, real_len);
+ return do_munmap(host_start, real_len);
}
int target_munmap(abi_ulong start, abi_ulong len)
--
GitLab

View File

@@ -1,47 +0,0 @@
With qemu 8.2.0 we started seeing SEGV errors when compiling webkitgtk from
usermode qemu:
qemu-x86_64: QEMU internal SIGSEGV {code=MAPERR, addr=0x20}
Segmentation fault
By bisection, this was tracked down to:
commit 7b7a3366e142d3baeb3fd1d3660a50e7956c19eb
Author: Richard Henderson <richard.henderson@linaro.org>
Date: Tue Aug 8 20:02:19 2023 -0700
linux-user: Use walk_memory_regions for open_self_maps
Replace the by-hand method of region identification with
the official user-exec interface. Cross-check the region
provided to the callback with the interval tree from
read_self_maps().
Tested-by: Helge Deller <deller@gmx.de>
Reviewed-by: Ilya Leoshkevich <iii@linux.ibm.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
and specifically to 'n' being NULL. For now, just skip in that case
until a proper fix can be identified.
Reported upstream: https://www.mail-archive.com/qemu-devel@nongnu.org/msg1018813.html
YOCTO #15367
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Upstream-Status: Pending
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index e384e14248..2577fb770d 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -8085,6 +8085,9 @@ static int open_self_maps_2(void *opaque, target_ulong guest_start,
while (1) {
IntervalTreeNode *n =
interval_tree_iter_first(d->host_maps, host_start, host_start);
+ if (!n) {
+ return 0;
+ }
MapInfo *mi = container_of(n, MapInfo, itree);
uintptr_t this_hlast = MIN(host_last, n->last);
target_ulong this_gend = h2g(this_hlast) + 1;