Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752961AbdCFJNj (ORCPT ); Mon, 6 Mar 2017 04:13:39 -0500 Received: from mx2.suse.de ([195.135.220.15]:37303 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753184AbdCFJNF (ORCPT ); Mon, 6 Mar 2017 04:13:05 -0500 X-Amavis-Alert: BAD HEADER SECTION, Duplicate header field: "References" From: Jiri Slaby To: stable@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Herbert Xu , "David S . Miller" , Jiri Slaby Subject: [PATCH 3.12 048/113] tun: Fix TUN_PKT_STRIP setting Date: Mon, 6 Mar 2017 10:11:12 +0100 Message-Id: <935eb89624c27a707a47dae7b465bbff5543febe.1488791430.git.jslaby@suse.cz> X-Mailer: git-send-email 2.12.0 In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2224 Lines: 75 From: Herbert Xu 3.12-stable review patch. If anyone has any objections, please let me know. =============== commit 2eb783c43e7cf807a45899c10ed556b6dc116625 upstream. We set the flag TUN_PKT_STRIP if the user buffer provided is too small to contain the entire packet plus meta-data. However, this has been broken ever since we added GSO meta-data. VLAN acceleration also has the same problem. This patch fixes this by taking both into account when setting the TUN_PKT_STRIP flag. The fact that this has been broken for six years without anyone realising means that nobody actually uses this flag. Fixes: f43798c27684 ("tun: Allow GSO using virtio_net_hdr") Signed-off-by: Herbert Xu Signed-off-by: David S. Miller Signed-off-by: Jiri Slaby --- drivers/net/tun.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 813750d09680..575e85df9296 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1187,15 +1187,19 @@ static ssize_t tun_put_user(struct tun_struct *tun, ssize_t total = 0; int vlan_offset = 0, copied; int vlan_hlen = 0; + int vnet_hdr_sz = 0; if (vlan_tx_tag_present(skb)) vlan_hlen = VLAN_HLEN; + if (tun->flags & TUN_VNET_HDR) + vnet_hdr_sz = tun->vnet_hdr_sz; + if (!(tun->flags & TUN_NO_PI)) { if ((len -= sizeof(pi)) < 0) return -EINVAL; - if (len < skb->len) { + if (len < skb->len + vlan_hlen + vnet_hdr_sz) { /* Packet will be striped */ pi.flags |= TUN_PKT_STRIP; } @@ -1205,9 +1209,9 @@ static ssize_t tun_put_user(struct tun_struct *tun, total += sizeof(pi); } - if (tun->flags & TUN_VNET_HDR) { + if (vnet_hdr_sz) { struct virtio_net_hdr gso = { 0 }; /* no info leak */ - if ((len -= tun->vnet_hdr_sz) < 0) + if ((len -= vnet_hdr_sz) < 0) return -EINVAL; if (skb_is_gso(skb)) { @@ -1251,7 +1255,7 @@ static ssize_t tun_put_user(struct tun_struct *tun, if (unlikely(memcpy_toiovecend(iv, (void *)&gso, total, sizeof(gso)))) return -EFAULT; - total += tun->vnet_hdr_sz; + total += vnet_hdr_sz; } copied = total; -- 2.12.0