The mmap2() syscall allows 32-bit guests to specify the offset into a
file in page units (instead of bytes, as done by mmap(2)).
On physical machines this allows 32-bit applications to map such parts
of large files which are stored beyond the 4GB limit.
Allow the same behaviour when emulating 32-bit guests with qemu.
For that switch the mmap2() function to always take an abi_ullong
(64-bit) offset parameter for target_mmap() and mmap_frag() to avoid an
arithmetical overflow when shifing a 32-bit offset parameter by
12 bits (=PAGE_SHIFT) and thus possibly overflow the abi_ulong (32-bit)
type.
Signed-off-by: Helge Deller <deller@gmx.de>
---
linux-user/mmap.c | 9 +++++----
linux-user/syscall.c | 2 +-
linux-user/user-mmap.h | 2 +-
3 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 2692936773..2750146758 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -192,7 +192,7 @@ error:
/* map an incomplete host page */
static int mmap_frag(abi_ulong real_start,
abi_ulong start, abi_ulong end,
- int prot, int flags, int fd, abi_ulong offset)
+ int prot, int flags, int fd, abi_ullong offset)
{
abi_ulong real_end, addr;
void *host_start;
@@ -436,10 +436,11 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size, abi_ulong align)
/* NOTE: all the constants are the HOST ones */
abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot,
- int flags, int fd, abi_ulong offset)
+ int flags, int fd, abi_ullong offset)
{
- abi_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len,
+ abi_ulong ret, end, real_start, real_end, retaddr, host_len,
passthrough_start = -1, passthrough_end = -1;
+ abi_ullong host_offset;
int page_flags, host_prot;
mmap_lock();
@@ -627,7 +628,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot,
/* map the middle (easier) */
if (real_start < real_end) {
void *p;
- unsigned long offset1;
+ off_t offset1;
if (flags & MAP_ANONYMOUS)
offset1 = 0;
else
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 9e9317237d..5ebc502f71 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -10427,7 +10427,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
#endif
ret = target_mmap(arg1, arg2, arg3,
target_to_host_bitmask(arg4, mmap_flags_tbl),
- arg5, arg6 << MMAP_SHIFT);
+ arg5, ((abi_ullong)arg6) << MMAP_SHIFT);
return get_errno(ret);
#endif
case TARGET_NR_munmap:
diff --git a/linux-user/user-mmap.h b/linux-user/user-mmap.h
index 480ce1c114..72e99000d9 100644
--- a/linux-user/user-mmap.h
+++ b/linux-user/user-mmap.h
@@ -20,7 +20,7 @@
int target_mprotect(abi_ulong start, abi_ulong len, int prot);
abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
- int flags, int fd, abi_ulong offset);
+ int flags, int fd, abi_ullong offset);
int target_munmap(abi_ulong start, abi_ulong len);
abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
abi_ulong new_size, unsigned long flags,
--
2.41.0
On 7/7/23 14:19, Helge Deller wrote: > The mmap2() syscall allows 32-bit guests to specify the offset into a > file in page units (instead of bytes, as done by mmap(2)). > On physical machines this allows 32-bit applications to map such parts > of large files which are stored beyond the 4GB limit. > > Allow the same behaviour when emulating 32-bit guests with qemu. > > For that switch the mmap2() function to always take an abi_ullong > (64-bit) offset parameter for target_mmap() and mmap_frag() to avoid an > arithmetical overflow when shifing a 32-bit offset parameter by > 12 bits (=PAGE_SHIFT) and thus possibly overflow the abi_ulong (32-bit) > type. > > Signed-off-by: Helge Deller<deller@gmx.de> > --- > linux-user/mmap.c | 9 +++++---- > linux-user/syscall.c | 2 +- > linux-user/user-mmap.h | 2 +- > 3 files changed, 7 insertions(+), 6 deletions(-) https://patchew.org/QEMU/20230630132159.376995-1-richard.henderson@linaro.org/20230630132159.376995-12-richard.henderson@linaro.org/ Wherein I use the host off_t (which must be 64-bits). (I'm pretty sure there's an older similar patch, but I couldn't find it.) r~
© 2016 - 2026 Red Hat, Inc.