aboutsummaryrefslogtreecommitdiffstats
path: root/linux-user
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2023-08-20 12:38:49 -0700
committerRichard Henderson <richard.henderson@linaro.org>2023-09-01 13:35:27 -0700
commitceda5688b650646248f269a992c06b11148c5759 (patch)
tree21189e4e130433246adfb66243200abb36758f0b /linux-user
parentlinux-user: Use WITH_MMAP_LOCK_GUARD in target_{shmat,shmdt} (diff)
downloadqemu-ceda5688b650646248f269a992c06b11148c5759.tar.xz
qemu-ceda5688b650646248f269a992c06b11148c5759.zip
linux-user: Fix shmdt
If the shm region is not mapped at shmaddr, EINVAL. Do not unmap the region until the syscall succeeds. Use mmap_reserve_or_unmap to preserve reserved_va semantics. Tested-by: Helge Deller <deller@gmx.de> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'linux-user')
-rw-r--r--linux-user/mmap.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index f45b2d307c..44116c014b 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -1102,14 +1102,25 @@ abi_long target_shmdt(abi_ulong shmaddr)
/* shmdt pointers are always untagged */
WITH_MMAP_LOCK_GUARD() {
- for (int i = 0; i < N_SHM_REGIONS; ++i) {
+ int i;
+
+ for (i = 0; i < N_SHM_REGIONS; ++i) {
if (shm_regions[i].in_use && shm_regions[i].start == shmaddr) {
- shm_regions[i].in_use = false;
- page_set_flags(shmaddr, shmaddr + shm_regions[i].size - 1, 0);
break;
}
}
+ if (i == N_SHM_REGIONS) {
+ return -TARGET_EINVAL;
+ }
+
rv = get_errno(shmdt(g2h_untagged(shmaddr)));
+ if (rv == 0) {
+ abi_ulong size = shm_regions[i].size;
+
+ shm_regions[i].in_use = false;
+ page_set_flags(shmaddr, shmaddr + size - 1, 0);
+ mmap_reserve_or_unmap(shmaddr, size);
+ }
}
return rv;
}