From nobody Mon Apr 29 00:35:25 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1524143477600763.1296729103177; Thu, 19 Apr 2018 06:11:17 -0700 (PDT) Received: from localhost ([::1]:45436 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f99LI-0004a0-LR for importer@patchew.org; Thu, 19 Apr 2018 09:11:16 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35518) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f998K-0002La-0L for qemu-devel@nongnu.org; Thu, 19 Apr 2018 08:57:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f998J-00013S-Af for qemu-devel@nongnu.org; Thu, 19 Apr 2018 08:57:52 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:40904) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f998J-00010e-3S for qemu-devel@nongnu.org; Thu, 19 Apr 2018 08:57:51 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1f9989-00027f-TQ; Thu, 19 Apr 2018 13:57:41 +0100 From: Peter Maydell To: qemu-devel@nongnu.org Date: Thu, 19 Apr 2018 13:57:40 +0100 Message-Id: <20180419125740.2695-1-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:8b0:1d0::2 Subject: [Qemu-devel] [PATCH] linux-user: Fix getdents emulation for 64 bit guest on 32 bit host X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Henry Wertz , Riku Voipio , Laurent Vivier , patches@linaro.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" 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 Signed-off-by: Peter Maydell --- The "only generate the syscall wrapper functions in exactly the cases where we're using them" part of the code is a little awkward... 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 >=3D 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, ui= nt, count); #endif @@ -10163,7 +10175,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_lon= g arg1, #endif #ifdef TARGET_NR_getdents case TARGET_NR_getdents: -#ifdef __NR_getdents +#ifdef EMULATE_GETDENTS_WITH_GETDENTS #if TARGET_ABI_BITS =3D=3D 32 && HOST_LONG_BITS =3D=3D 64 { struct target_dirent *target_dirp; --=20 2.17.0