diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2023-08-20 12:38:49 -0700 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2023-09-01 13:35:27 -0700 |
commit | ceda5688b650646248f269a992c06b11148c5759 (patch) | |
tree | 21189e4e130433246adfb66243200abb36758f0b | |
parent | 69fa2708a216df715ba5102a0f98468b540a464e (diff) | |
download | qemu-ceda5688b650646248f269a992c06b11148c5759.zip qemu-ceda5688b650646248f269a992c06b11148c5759.tar.gz qemu-ceda5688b650646248f269a992c06b11148c5759.tar.bz2 |
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>
-rw-r--r-- | linux-user/mmap.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/linux-user/mmap.c b/linux-user/mmap.c index f45b2d3..44116c0 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; } |