From patchwork Tue Jun 16 07:06:29 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Riku Voipio X-Patchwork-Id: 49947 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-wg0-f72.google.com (mail-wg0-f72.google.com [74.125.82.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id C16CA205DE for ; Tue, 16 Jun 2015 07:08:01 +0000 (UTC) Received: by wgbhy7 with SMTP id hy7sf2003404wgb.3 for ; Tue, 16 Jun 2015 00:08:01 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:date :message-id:in-reply-to:references:cc:subject:precedence:list-id :list-unsubscribe:list-archive:list-post:list-help:list-subscribe :errors-to:sender:x-original-sender :x-original-authentication-results:mailing-list; bh=QTnwK5y1NeM+S8VthLJAj50DMAnASscpknwAC7i+ycM=; b=TC7RX/7v6/jBOAhD847ZstXlNYP0bFTpl2vk+Jv+UySrCEoe2Krg0xKJ6j9nCtSeGC c/W7vk5y5S3hihZZhOToXFdyX5P+xO7DMXwFZ4Li+AitAy65wMyFaQ1mGU7JZR4iB6vq uZCaEgeap+HR+LRMPqG3fi5MVh8iyM2F+bIPJfASQRLeJLvgA8Ah1BuK4lLG24lzUi+D AGcryIN2IT9C4LVn9eIlew41NpyFRs1tfKmH8e2qb9DUPbzyXl9pXRl3Wj2RyLbFvWmU Nsf4gp2htMJAny9HaPJ5DL4oXFBk+os4Pu06PPlxqNkwcIU2Vhj2j5EciC09DNDSm343 Vcag== X-Gm-Message-State: ALoCoQnL5uADZaC2ncxQHtO5RV6Q5kgDAeuRCBbuzq96mjGK+VC+wNy1UZ16oX38NT3TCzb3jm7c X-Received: by 10.112.53.102 with SMTP id a6mr4193802lbp.16.1434438481003; Tue, 16 Jun 2015 00:08:01 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.27.65 with SMTP id r1ls39007lag.61.gmail; Tue, 16 Jun 2015 00:08:00 -0700 (PDT) X-Received: by 10.112.202.234 with SMTP id kl10mr4479498lbc.51.1434438480720; Tue, 16 Jun 2015 00:08:00 -0700 (PDT) Received: from mail-lb0-f170.google.com (mail-lb0-f170.google.com. [209.85.217.170]) by mx.google.com with ESMTPS id yk6si87844lbb.90.2015.06.16.00.08.00 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 16 Jun 2015 00:08:00 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.170 as permitted sender) client-ip=209.85.217.170; Received: by lbbqq2 with SMTP id qq2so4711499lbb.3 for ; Tue, 16 Jun 2015 00:08:00 -0700 (PDT) X-Received: by 10.152.44.166 with SMTP id f6mr31565511lam.86.1434438480608; Tue, 16 Jun 2015 00:08:00 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.108.230 with SMTP id hn6csp1913318lbb; Tue, 16 Jun 2015 00:07:59 -0700 (PDT) X-Received: by 10.140.102.180 with SMTP id w49mr40507840qge.82.1434438477469; Tue, 16 Jun 2015 00:07:57 -0700 (PDT) Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id u68si82431qge.89.2015.06.16.00.07.56 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Tue, 16 Jun 2015 00:07:57 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Received: from localhost ([::1]:38160 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z4kyS-0005id-Dl for patch@linaro.org; Tue, 16 Jun 2015 03:07:56 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60917) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z4kxF-0004Dc-Ft for qemu-devel@nongnu.org; Tue, 16 Jun 2015 03:06:42 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Z4kxC-0006nJ-4Y for qemu-devel@nongnu.org; Tue, 16 Jun 2015 03:06:41 -0400 Received: from mail-la0-f46.google.com ([209.85.215.46]:34222) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z4kxB-0006nE-Qc for qemu-devel@nongnu.org; Tue, 16 Jun 2015 03:06:38 -0400 Received: by labbc20 with SMTP id bc20so4818858lab.1 for ; Tue, 16 Jun 2015 00:06:37 -0700 (PDT) X-Received: by 10.152.36.65 with SMTP id o1mr32121560laj.55.1434438397135; Tue, 16 Jun 2015 00:06:37 -0700 (PDT) Received: from localhost.localdomain (91-157-196-38.elisa-laajakaista.fi. [91.157.196.38]) by mx.google.com with ESMTPSA id wc8sm27104lbb.37.2015.06.16.00.06.36 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 16 Jun 2015 00:06:36 -0700 (PDT) From: riku.voipio@linaro.org To: qemu-devel@nongnu.org Date: Tue, 16 Jun 2015 10:06:29 +0300 Message-Id: X-Mailer: git-send-email 2.1.4 In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.85.215.46 Cc: peter.maydell@linaro.org Subject: [Qemu-devel] [PULL v2 3/6] linux-user: Fix length handling in host_to_target_cmsg 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+patch=linaro.org@nongnu.org Sender: qemu-devel-bounces+patch=linaro.org@nongnu.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: riku.voipio@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.170 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 From: Peter Maydell The previous code for handling payload length when converting cmsg structures from host to target had a number of problems: * we required the msg->msg_controllen to declare the buffer to have enough space for final trailing padding (we were checking against CMSG_SPACE), whereas the kernel does not require this, and common userspace code assumes this. (In particular, glibc's "try to talk to nscd" code that it will run on startup will receive a cmsg with a 4 byte payload and only allocate 4 bytes for it, which was causing us to do the wrong thing on architectures that need 8-alignment.) * we weren't correctly handling the fact that the SO_TIMESTAMP payload may be larger for the target than the host * we weren't marking the messages with MSG_CTRUNC when we did need to truncate a message that wasn't truncated by the host, but were instead logging a QEMU message; since truncation is always the result of a guest giving us an insufficiently sized buffer, we should report it to the guest as the kernel does and don't log anything Rewrite the parts of the function that deal with length to fix these issues, and add a comment in target_to_host_cmsg to explain why the overflow logging it does is a QEMU bug, not a guest issue. Signed-off-by: Peter Maydell Signed-off-by: Riku Voipio --- linux-user/syscall.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 61 insertions(+), 8 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index f56f3e0..15b1e81 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1202,6 +1202,15 @@ static inline abi_long target_to_host_cmsg(struct msghdr *msgh, space += CMSG_SPACE(len); if (space > msgh->msg_controllen) { space -= CMSG_SPACE(len); + /* This is a QEMU bug, since we allocated the payload + * area ourselves (unlike overflow in host-to-target + * conversion, which is just the guest giving us a buffer + * that's too small). It can't happen for the payload types + * we currently support; if it becomes an issue in future + * we would need to improve our allocation strategy to + * something more intelligent than "twice the size of the + * target buffer we're reading from". + */ gemu_log("Host cmsg overflow\n"); break; } @@ -1267,11 +1276,16 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh, void *target_data = TARGET_CMSG_DATA(target_cmsg); int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof (struct cmsghdr)); + int tgt_len, tgt_space; - space += TARGET_CMSG_SPACE(len); - if (space > msg_controllen) { - space -= TARGET_CMSG_SPACE(len); - gemu_log("Target cmsg overflow\n"); + /* We never copy a half-header but may copy half-data; + * this is Linux's behaviour in put_cmsg(). Note that + * truncation here is a guest problem (which we report + * to the guest via the CTRUNC bit), unlike truncation + * in target_to_host_cmsg, which is a QEMU bug. + */ + if (msg_controllen < sizeof(struct cmsghdr)) { + target_msgh->msg_flags |= tswap32(MSG_CTRUNC); break; } @@ -1281,8 +1295,35 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh, target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level); } target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type); - target_cmsg->cmsg_len = tswapal(TARGET_CMSG_LEN(len)); + tgt_len = TARGET_CMSG_LEN(len); + + /* Payload types which need a different size of payload on + * the target must adjust tgt_len here. + */ + switch (cmsg->cmsg_level) { + case SOL_SOCKET: + switch (cmsg->cmsg_type) { + case SO_TIMESTAMP: + tgt_len = sizeof(struct target_timeval); + break; + default: + break; + } + default: + break; + } + + if (msg_controllen < tgt_len) { + target_msgh->msg_flags |= tswap32(MSG_CTRUNC); + tgt_len = msg_controllen; + } + + /* We must now copy-and-convert len bytes of payload + * into tgt_len bytes of destination space. Bear in mind + * that in both source and destination we may be dealing + * with a truncated value! + */ switch (cmsg->cmsg_level) { case SOL_SOCKET: switch (cmsg->cmsg_type) { @@ -1290,7 +1331,7 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh, { int *fd = (int *)data; int *target_fd = (int *)target_data; - int i, numfds = len / sizeof(int); + int i, numfds = tgt_len / sizeof(int); for (i = 0; i < numfds; i++) target_fd[i] = tswap32(fd[i]); @@ -1302,8 +1343,10 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh, struct target_timeval *target_tv = (struct target_timeval *)target_data; - if (len != sizeof(struct timeval)) + if (len != sizeof(struct timeval) || + tgt_len != sizeof(struct target_timeval)) { goto unimplemented; + } /* copy struct timeval to target */ target_tv->tv_sec = tswapal(tv->tv_sec); @@ -1330,9 +1373,19 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh, unimplemented: gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type); - memcpy(target_data, data, len); + memcpy(target_data, data, MIN(len, tgt_len)); + if (tgt_len > len) { + memset(target_data + len, 0, tgt_len - len); + } } + target_cmsg->cmsg_len = tswapal(tgt_len); + tgt_space = TARGET_CMSG_SPACE(tgt_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); }