From patchwork Thu Jan 3 10:02:48 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nickolai Zeldovich X-Patchwork-Id: 209204 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 2FA3F2C008C for ; Thu, 3 Jan 2013 21:02:47 +1100 (EST) Received: from localhost ([::1]:36434 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TqhdN-0004M4-CP for incoming@patchwork.ozlabs.org; Thu, 03 Jan 2013 05:02:45 -0500 Received: from eggs.gnu.org ([208.118.235.92]:57039) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TqhdD-0004Kh-38 for qemu-devel@nongnu.org; Thu, 03 Jan 2013 05:02:37 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TqhdA-0007Mg-8W for qemu-devel@nongnu.org; Thu, 03 Jan 2013 05:02:35 -0500 Received: from outgoing-v6.csail.mit.edu ([2001:470:8b2d:7d2:ea9a:8fff:feb2:a9e4]:38198 helo=outgoing.csail.mit.edu) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TqhdA-0007MU-4a for qemu-devel@nongnu.org; Thu, 03 Jan 2013 05:02:32 -0500 Received: from c-71-232-26-90.hsd1.ma.comcast.net ([71.232.26.90] helo=sahara) by outgoing.csail.mit.edu with esmtpsa (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.72) (envelope-from ) id 1Tqhd8-0006bM-KX; Thu, 03 Jan 2013 05:02:30 -0500 Received: from nickolai by sahara with local (Exim 4.80) (envelope-from ) id 1Tqhdj-0005VB-5G; Thu, 03 Jan 2013 05:03:07 -0500 From: Nickolai Zeldovich To: qemu-devel@nongnu.org Date: Thu, 3 Jan 2013 05:02:48 -0500 Message-Id: <1357207368-21116-1-git-send-email-nickolai@csail.mit.edu> X-Mailer: git-send-email 1.7.10.4 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-Received-From: 2001:470:8b2d:7d2:ea9a:8fff:feb2:a9e4 Cc: Nickolai Zeldovich , Riku Voipio Subject: [Qemu-devel] [PATCH] linux-user/syscall.c: fix copy_to_user_fdset for fds over 30 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org On a 64-bit system (e.g., x86_64), copy_to_user_fdset populates the bitmask returned to the user-space program by left-shifting the value (FD_ISSET(k, fds) != 0), which is of type int, by k bits (0 through 63). According to the C standard, left-shifting an int by 31 bits is undefined behavior because it shifts a 1 into the sign bit, and shifting an int by 32 bits or more is UB because it's equal to or greater than the type's width. The resulting behavior depends on the specific compiler, but with gcc 4.7.2 on an x86_64 host (as well as guest), select calls that were supposed to set fd 31 on return would actually set fds 31 through 63, and select calls that were supposed to set an fd above 31 (e.g., 48) would set that fd mod 32 (e.g., 16). This patch fixes the problem by casting the value (FD_ISSET(..) != 0) to a suitably long and unsigned type before doing the left-shift, and fixes select for fds above 32 on x86_64. Signed-off-by: Nickolai Zeldovich --- linux-user/syscall.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 5a81d9f..17c3dd6 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -912,7 +912,7 @@ static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr, for (i = 0; i < nw; i++) { v = 0; for (j = 0; j < TARGET_ABI_BITS; j++) { - v |= ((FD_ISSET(k, fds) != 0) << j); + v |= (((abi_ulong) (FD_ISSET(k, fds) != 0)) << j); k++; } __put_user(v, &target_fds[i]);