Skip to content

Commit

Permalink
tun: unbreak truncated packet signalling
Browse files Browse the repository at this point in the history
Commit 6680ec6
(tuntap: hardware vlan tx support) breaks the truncated packet signal by nev
return a length greater than iov length in tun_put_user(). This patch fixes
by always return the length of packet plus possible vlan header. Caller can
detect the truncated packet by comparing the return value and the size of io
length.

Cc: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>
Cc: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Vlad Yasevich <vyasevich@gmail.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Jason Wang authored and David S. Miller committed Dec 11, 2013
1 parent 1598f7c commit e6fd07c
Showing 1 changed file with 9 additions and 7 deletions.
16 changes: 9 additions & 7 deletions drivers/net/tun.c
Original file line number Diff line number Diff line change
Expand Up @@ -1184,7 +1184,7 @@ static ssize_t tun_put_user(struct tun_struct *tun,
{
struct tun_pi pi = { 0, skb->protocol };
ssize_t total = 0;
int vlan_offset = 0;
int vlan_offset = 0, copied;

if (!(tun->flags & TUN_NO_PI)) {
if ((len -= sizeof(pi)) < 0)
Expand Down Expand Up @@ -1248,6 +1248,8 @@ static ssize_t tun_put_user(struct tun_struct *tun,
total += tun->vnet_hdr_sz;
}

copied = total;
total += skb->len;
if (!vlan_tx_tag_present(skb)) {
len = min_t(int, skb->len, len);
} else {
Expand All @@ -1262,24 +1264,24 @@ static ssize_t tun_put_user(struct tun_struct *tun,

vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto);
len = min_t(int, skb->len + VLAN_HLEN, len);
total += VLAN_HLEN;

copy = min_t(int, vlan_offset, len);
ret = skb_copy_datagram_const_iovec(skb, 0, iv, total, copy);
ret = skb_copy_datagram_const_iovec(skb, 0, iv, copied, copy);
len -= copy;
total += copy;
copied += copy;
if (ret || !len)
goto done;

copy = min_t(int, sizeof(veth), len);
ret = memcpy_toiovecend(iv, (void *)&veth, total, copy);
ret = memcpy_toiovecend(iv, (void *)&veth, copied, copy);
len -= copy;
total += copy;
copied += copy;
if (ret || !len)
goto done;
}

skb_copy_datagram_const_iovec(skb, vlan_offset, iv, total, len);
total += len;
skb_copy_datagram_const_iovec(skb, vlan_offset, iv, copied, len);

done:
tun->dev->stats.tx_packets++;
Expand Down

0 comments on commit e6fd07c

Please sign in to comment.