From patchwork Thu Sep 3 05:27:26 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?J=2E_Neusch=C3=A4fer?= X-Patchwork-Id: 513837 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)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 700A3140273 for ; Thu, 3 Sep 2015 15:28:26 +1000 (AEST) Received: from localhost ([::1]:44811 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZXN4S-0002tn-HP for incoming@patchwork.ozlabs.org; Thu, 03 Sep 2015 01:28:24 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51478) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZXN3p-0001hV-LA for qemu-devel@nongnu.org; Thu, 03 Sep 2015 01:27:46 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZXN3k-0007sq-H1 for qemu-devel@nongnu.org; Thu, 03 Sep 2015 01:27:45 -0400 Received: from mout.gmx.net ([212.227.17.20]:50422) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZXN3k-0007sS-8u for qemu-devel@nongnu.org; Thu, 03 Sep 2015 01:27:40 -0400 Received: from latitude ([178.201.237.132]) by mail.gmx.com (mrgmx103) with ESMTPSA (Nemesis) id 0Lmazv-1YxD5n2iKB-00aExL; Thu, 03 Sep 2015 07:27:28 +0200 Date: Thu, 3 Sep 2015 07:27:26 +0200 From: Jonathan =?utf-8?Q?Neusch=C3=A4fer?= To: QEMU Developers Message-ID: <20150903052726.GD1761@latitude> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.23 (2014-03-12) X-Provags-ID: V03:K0:8bSua15w63kuW0+m/GrqlQWG66rOAHfSgJ9S+Z/LR4N3Fl9+ByQ qSZGmgeGJ66zGwbVYoxAUyqrQpvhGLFC8XQl2QgnG7Cw3iwz+R1LDgnB3uWhzwbNg5Hou0f FaJF9zIsqK2B6G3wCvBhRnDoDoKT+iNisVtrigp/Kkl5MkR4TK+NmgqrK6uZ+1H4U5y895Y 7Ueb5itxuUJI3FCVRYUEA== X-UI-Out-Filterresults: notjunk:1; V01:K0:OgdoT9i1fIw=:pJb+55j25kN4VDlSHoJzjc G0UIdTOPqan8b4iNYffAlPzi+E6ny3s7JUCGTYqsUWjrCOuLZxpoSFzcGBzAGlnXwqSMcf075 Sdj2IISHn6CTgNhhKVZV4uOZetCeQ5uGI7v1AgtobqhJ/snd0StKMH3tZ9cmEQCTSEXco9dQ0 LwVbxYh1YpiZ09tZDLB6iu9Cc/rJ8oS9Wpr2t6PZiplE/FWdVis7JZSqPa8FB/fTHV22rgq4K 60HIreoW7VElF/TU/gFgK2dgZgEht6sUfNwLgVyWI6hGxt00FrazuytTKI7ModFKkHWHlIGHk eJTIBCsTDoAu4Girj0ao1SCR6AWEjVxgTbADuRlevcN9U58HxVd7h4ekWeR15FX4vBvSyvFYt 99dfBm/9L/+ZXVhNZDdpbl5okU5r2QFEj2YcInx+sar337DHsPVc848daemMHM3p5OTQg2fHs vvLuuqI11vvgZjfCuLpIjVz/uPMpzSNpGuRvSDM+Kv0lplPOiitApwP+UhfkSYHnG/pWe7BJE 6LTB5IxnfYrV9DyOmZmutn7JZ38yD8vq/0JY8dzEoS/Bd6ENdk/cjCnxZ4BnQX3neVPYjUeD6 dCEB/iD6QMDbQ82/EwIEtqK2bN2oPtsu11CWB652t9QecQ1gajoo+xekg4PuGFRh0U+wCfEwF rD93+LDPNnS0IP2TaFV3wQ738mlLdWj28Uu1zVnKkJAnWOq1c60k7/4HDb362HfBHWgi9fFIM bsonFRwInqwoOGoR X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 212.227.17.20 Cc: Peter Maydell , Riku Voipio , Jonathan =?utf-8?Q?Neusch=C3=A4fer?= Subject: [Qemu-devel] [PATCH] linux-user: fix cmsg conversion in case of multiple headers 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 Currently, __target_cmsg_nxthdr compares a pointer derived from target_cmsg against the msg_control field of target_msgh (through subtraction). This failed for me when emulating i386 code under x86_64, because pointers in the host address space and pointers in the guest address space were not the same. This patch passes the initial value of target_cmsg into __target_cmsg_nxthdr. I found and fixed two more related bugs: - __target_cmsg_nxthdr now returns the new cmsg pointer instead of the old one. - tgt_space (in host_to_target_cmsg) doesn't count "sizeof (struct target_cmsghdr)" twice anymore. Signed-off-by: Jonathan Neuschäfer Reviewed-by: Peter Maydell --- Changes since v2: - The patch is now clean WRT checkpatch.pl Changes since v1: - Follow Peter Maydell's advice on how to fix the first bug - The "two more related bugs" --- linux-user/syscall.c | 14 +++++++++----- linux-user/syscall_defs.h | 14 +++++++++----- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index f62c698..12a6cd2 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1181,7 +1181,7 @@ static inline abi_long target_to_host_cmsg(struct msghdr *msgh, struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh); abi_long msg_controllen; abi_ulong target_cmsg_addr; - struct target_cmsghdr *target_cmsg; + struct target_cmsghdr *target_cmsg, *target_cmsg_start; socklen_t space = 0; msg_controllen = tswapal(target_msgh->msg_controllen); @@ -1189,6 +1189,7 @@ static inline abi_long target_to_host_cmsg(struct msghdr *msgh, goto the_end; target_cmsg_addr = tswapal(target_msgh->msg_control); target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1); + target_cmsg_start = target_cmsg; if (!target_cmsg) return -TARGET_EFAULT; @@ -1247,7 +1248,8 @@ static inline abi_long target_to_host_cmsg(struct msghdr *msgh, } cmsg = CMSG_NXTHDR(msgh, cmsg); - target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg); + target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg, + target_cmsg_start); } unlock_user(target_cmsg, target_cmsg_addr, 0); the_end: @@ -1261,7 +1263,7 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh, struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh); abi_long msg_controllen; abi_ulong target_cmsg_addr; - struct target_cmsghdr *target_cmsg; + struct target_cmsghdr *target_cmsg, *target_cmsg_start; socklen_t space = 0; msg_controllen = tswapal(target_msgh->msg_controllen); @@ -1269,6 +1271,7 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh, goto the_end; target_cmsg_addr = tswapal(target_msgh->msg_control); target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0); + target_cmsg_start = target_cmsg; if (!target_cmsg) return -TARGET_EFAULT; @@ -1382,14 +1385,15 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh, } target_cmsg->cmsg_len = tswapal(tgt_len); - tgt_space = TARGET_CMSG_SPACE(tgt_len); + tgt_space = TARGET_CMSG_SPACE(len); if (msg_controllen < tgt_space) { tgt_space = msg_controllen; } msg_controllen -= tgt_space; space += tgt_space; cmsg = CMSG_NXTHDR(msgh, cmsg); - target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg); + target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg, + target_cmsg_start); } unlock_user(target_cmsg, target_cmsg_addr, space); the_end: diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index edd5f3c..9d3c537 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -234,7 +234,8 @@ struct target_cmsghdr { }; #define TARGET_CMSG_DATA(cmsg) ((unsigned char *) ((struct target_cmsghdr *) (cmsg) + 1)) -#define TARGET_CMSG_NXTHDR(mhdr, cmsg) __target_cmsg_nxthdr (mhdr, cmsg) +#define TARGET_CMSG_NXTHDR(mhdr, cmsg, cmsg_start) \ + __target_cmsg_nxthdr(mhdr, cmsg, cmsg_start) #define TARGET_CMSG_ALIGN(len) (((len) + sizeof (abi_long) - 1) \ & (size_t) ~(sizeof (abi_long) - 1)) #define TARGET_CMSG_SPACE(len) (TARGET_CMSG_ALIGN (len) \ @@ -242,17 +243,20 @@ struct target_cmsghdr { #define TARGET_CMSG_LEN(len) (TARGET_CMSG_ALIGN (sizeof (struct target_cmsghdr)) + (len)) static __inline__ struct target_cmsghdr * -__target_cmsg_nxthdr (struct target_msghdr *__mhdr, struct target_cmsghdr *__cmsg) +__target_cmsg_nxthdr(struct target_msghdr *__mhdr, + struct target_cmsghdr *__cmsg, + struct target_cmsghdr *__cmsg_start) { struct target_cmsghdr *__ptr; __ptr = (struct target_cmsghdr *)((unsigned char *) __cmsg + TARGET_CMSG_ALIGN (tswapal(__cmsg->cmsg_len))); - if ((unsigned long)((char *)(__ptr+1) - (char *)(size_t)tswapal(__mhdr->msg_control)) - > tswapal(__mhdr->msg_controllen)) + if ((unsigned long)((char *)(__ptr+1) - (char *)__cmsg_start) + > tswapal(__mhdr->msg_controllen)) { /* No more entries. */ return (struct target_cmsghdr *)0; - return __cmsg; + } + return __ptr; } struct target_mmsghdr {