Skip to content
Snippets Groups Projects
Commit 923347bb authored by Jason Wang's avatar Jason Wang Committed by David S. Miller
Browse files

tun: unbreak truncated packet signalling


Commit 6680ec68
(tuntap: hardware vlan tx support) breaks the truncated packet signal by never
return a length greater than iov length in tun_put_user(). This patch fixes this
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 iov
length.

Reported-by: default avatarVlad Yasevich <vyasevich@gmail.com>
Cc: Vlad Yasevich <vyasevich@gmail.com>
Cc: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>
Signed-off-by: default avatarJason Wang <jasowang@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent fffc15a5
No related branches found
No related tags found
No related merge requests found
...@@ -1183,7 +1183,11 @@ static ssize_t tun_put_user(struct tun_struct *tun, ...@@ -1183,7 +1183,11 @@ static ssize_t tun_put_user(struct tun_struct *tun,
const struct iovec *iv, int len) const struct iovec *iv, int len)
{ {
struct tun_pi pi = { 0, skb->protocol }; struct tun_pi pi = { 0, skb->protocol };
ssize_t total = 0; struct {
__be16 h_vlan_proto;
__be16 h_vlan_TCI;
} veth;
ssize_t total = 0, off = 0;
int vlan_offset = 0; int vlan_offset = 0;
if (!(tun->flags & TUN_NO_PI)) { if (!(tun->flags & TUN_NO_PI)) {
...@@ -1248,14 +1252,11 @@ static ssize_t tun_put_user(struct tun_struct *tun, ...@@ -1248,14 +1252,11 @@ static ssize_t tun_put_user(struct tun_struct *tun,
total += tun->vnet_hdr_sz; total += tun->vnet_hdr_sz;
} }
off = total;
if (!vlan_tx_tag_present(skb)) { if (!vlan_tx_tag_present(skb)) {
len = min_t(int, skb->len, len); len = min_t(int, skb->len, len);
} else { } else {
int copy, ret; int copy, ret;
struct {
__be16 h_vlan_proto;
__be16 h_vlan_TCI;
} veth;
veth.h_vlan_proto = skb->vlan_proto; veth.h_vlan_proto = skb->vlan_proto;
veth.h_vlan_TCI = htons(vlan_tx_tag_get(skb)); veth.h_vlan_TCI = htons(vlan_tx_tag_get(skb));
...@@ -1264,22 +1265,22 @@ static ssize_t tun_put_user(struct tun_struct *tun, ...@@ -1264,22 +1265,22 @@ static ssize_t tun_put_user(struct tun_struct *tun,
len = min_t(int, skb->len + VLAN_HLEN, len); len = min_t(int, skb->len + VLAN_HLEN, len);
copy = min_t(int, vlan_offset, len); 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, off, copy);
len -= copy; len -= copy;
total += copy; off += copy;
if (ret || !len) if (ret || !len)
goto done; goto done;
copy = min_t(int, sizeof(veth), len); copy = min_t(int, sizeof(veth), len);
ret = memcpy_toiovecend(iv, (void *)&veth, total, copy); ret = memcpy_toiovecend(iv, (void *)&veth, off, copy);
len -= copy; len -= copy;
total += copy; off += copy;
if (ret || !len) if (ret || !len)
goto done; goto done;
} }
skb_copy_datagram_const_iovec(skb, vlan_offset, iv, total, len); skb_copy_datagram_const_iovec(skb, vlan_offset, iv, off, len);
total += len; total += skb->len + (vlan_offset ? sizeof(veth) : 0);
done: done:
tun->dev->stats.tx_packets++; tun->dev->stats.tx_packets++;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment