3.2.87-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx> 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 <herbert@xxxxxxxxxxxxxxxxxxx> Signed-off-by: David S. Miller <davem@xxxxxxxxxxxxx> [bwh: Backported to 3.2: - No VLAN acceleration support - Adjust context] Signed-off-by: Ben Hutchings <ben@xxxxxxxxxxxxxxx> --- drivers/net/tun.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -767,12 +767,16 @@ static ssize_t tun_put_user(struct tun_s { struct tun_pi pi = { 0, skb->protocol }; ssize_t total = 0; + int vnet_hdr_sz = 0; + + 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 + vnet_hdr_sz) { /* Packet will be striped */ pi.flags |= TUN_PKT_STRIP; } @@ -782,9 +786,9 @@ static ssize_t tun_put_user(struct tun_s 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)) { @@ -827,7 +831,7 @@ static ssize_t tun_put_user(struct tun_s if (unlikely(memcpy_toiovecend(iv, (void *)&gso, total, sizeof(gso)))) return -EFAULT; - total += tun->vnet_hdr_sz; + total += vnet_hdr_sz; } len = min_t(int, skb->len, len);