[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 02/42] linux-user: Fix getdents emulation for 64 bit
From: |
Laurent Vivier |
Subject: |
[Qemu-devel] [PULL 02/42] linux-user: Fix getdents emulation for 64 bit guest on 32 bit host |
Date: |
Mon, 30 Apr 2018 11:09:57 +0200 |
From: Peter Maydell <address@hidden>
Currently we mishandle emulation of the getdents syscall for the
case of a 64 bit guest on a 32 bit host -- it defaults into
the 'host and guest same size' codepath and generates incorrect
structures in the guest buffer.
We can't easily handle the 64-on-32 case using the host getdents
syscall, because the guest struct dirent is bigger than the
host struct dirent, and we might find the host syscall has handed
us back more records than we can fit in the guest buffer after
conversion. Instead, always emulate 64-on-32 getdents with
the host getdents64. This avoids the buffer-overrun problem
because a dirent64 struct is always the same size on any host
and always larger than any architecture's dirent struct.
Reported-by: Henry Wertz <address@hidden>
Signed-off-by: Peter Maydell <address@hidden>
Message-Id: <address@hidden>
Signed-off-by: Laurent Vivier <address@hidden>
---
linux-user/syscall.c | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 643b8833de..404be44ad5 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -259,10 +259,22 @@ static int gettid(void) {
return -ENOSYS;
}
#endif
-#if defined(TARGET_NR_getdents) && defined(__NR_getdents)
+
+/* For the 64-bit guest on 32-bit host case we must emulate
+ * getdents using getdents64, because otherwise the host
+ * might hand us back more dirent records than we can fit
+ * into the guest buffer after structure format conversion.
+ * Otherwise we emulate getdents with getdents if the host has it.
+ */
+#if defined(__NR_getdents) && HOST_LONG_BITS >= TARGET_ABI_BITS
+#define EMULATE_GETDENTS_WITH_GETDENTS
+#endif
+
+#if defined(TARGET_NR_getdents) && defined(EMULATE_GETDENTS_WITH_GETDENTS)
_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint,
count);
#endif
-#if !defined(__NR_getdents) || \
+#if (defined(TARGET_NR_getdents) && \
+ !defined(EMULATE_GETDENTS_WITH_GETDENTS)) || \
(defined(TARGET_NR_getdents64) && defined(__NR_getdents64))
_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint,
count);
#endif
@@ -10163,7 +10175,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long
arg1,
#endif
#ifdef TARGET_NR_getdents
case TARGET_NR_getdents:
-#ifdef __NR_getdents
+#ifdef EMULATE_GETDENTS_WITH_GETDENTS
#if TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
{
struct target_dirent *target_dirp;
--
2.14.3
- [Qemu-devel] [PULL 00/42] Linux user for 2.13 patches, Laurent Vivier, 2018/04/30
- [Qemu-devel] [PULL 02/42] linux-user: Fix getdents emulation for 64 bit guest on 32 bit host,
Laurent Vivier <=
- [Qemu-devel] [PULL 09/42] linux-user: move nios2 signal.c parts to nios2 directory, Laurent Vivier, 2018/04/30
- [Qemu-devel] [PULL 06/42] linux-user: move sh4 signal.c parts to sh4 directory, Laurent Vivier, 2018/04/30
- [Qemu-devel] [PULL 08/42] linux-user: move cris signal.c parts to cris directory, Laurent Vivier, 2018/04/30
- [Qemu-devel] [PULL 03/42] linux-user: create a dummy per arch signal.c, Laurent Vivier, 2018/04/30
- [Qemu-devel] [PULL 07/42] linux-user: move microblaze signal.c parts to microblaze directory, Laurent Vivier, 2018/04/30
- [Qemu-devel] [PULL 01/42] linux-user: set minimum uname for RISC-V, Laurent Vivier, 2018/04/30
- [Qemu-devel] [PULL 04/42] linux-user: move aarch64 signal.c parts to aarch64 directory, Laurent Vivier, 2018/04/30
- [Qemu-devel] [PULL 05/42] linux-user: move arm signal.c parts to arm directory, Laurent Vivier, 2018/04/30
- [Qemu-devel] [PULL 17/42] linux-user: move xtensa signal.c parts to xtensa directory, Laurent Vivier, 2018/04/30
- [Qemu-devel] [PULL 22/42] linux-user: define TARGET_ARCH_HAS_SETUP_FRAME, Laurent Vivier, 2018/04/30