Skip to content

Commit 923347b

Browse files
jasowangdavem330
authored andcommitted
tun: unbreak truncated packet signalling
Commit 6680ec6 (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: Vlad Yasevich <vyasevich@gmail.com> Cc: Vlad Yasevich <vyasevich@gmail.com> Cc: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com> Signed-off-by: Jason Wang <jasowang@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent fffc15a commit 923347b

File tree

1 file changed

+12
-11
lines changed

1 file changed

+12
-11
lines changed

drivers/net/tun.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,7 +1183,11 @@ static ssize_t tun_put_user(struct tun_struct *tun,
11831183
const struct iovec *iv, int len)
11841184
{
11851185
struct tun_pi pi = { 0, skb->protocol };
1186-
ssize_t total = 0;
1186+
struct {
1187+
__be16 h_vlan_proto;
1188+
__be16 h_vlan_TCI;
1189+
} veth;
1190+
ssize_t total = 0, off = 0;
11871191
int vlan_offset = 0;
11881192

11891193
if (!(tun->flags & TUN_NO_PI)) {
@@ -1248,14 +1252,11 @@ static ssize_t tun_put_user(struct tun_struct *tun,
12481252
total += tun->vnet_hdr_sz;
12491253
}
12501254

1255+
off = total;
12511256
if (!vlan_tx_tag_present(skb)) {
12521257
len = min_t(int, skb->len, len);
12531258
} else {
12541259
int copy, ret;
1255-
struct {
1256-
__be16 h_vlan_proto;
1257-
__be16 h_vlan_TCI;
1258-
} veth;
12591260

12601261
veth.h_vlan_proto = skb->vlan_proto;
12611262
veth.h_vlan_TCI = htons(vlan_tx_tag_get(skb));
@@ -1264,22 +1265,22 @@ static ssize_t tun_put_user(struct tun_struct *tun,
12641265
len = min_t(int, skb->len + VLAN_HLEN, len);
12651266

12661267
copy = min_t(int, vlan_offset, len);
1267-
ret = skb_copy_datagram_const_iovec(skb, 0, iv, total, copy);
1268+
ret = skb_copy_datagram_const_iovec(skb, 0, iv, off, copy);
12681269
len -= copy;
1269-
total += copy;
1270+
off += copy;
12701271
if (ret || !len)
12711272
goto done;
12721273

12731274
copy = min_t(int, sizeof(veth), len);
1274-
ret = memcpy_toiovecend(iv, (void *)&veth, total, copy);
1275+
ret = memcpy_toiovecend(iv, (void *)&veth, off, copy);
12751276
len -= copy;
1276-
total += copy;
1277+
off += copy;
12771278
if (ret || !len)
12781279
goto done;
12791280
}
12801281

1281-
skb_copy_datagram_const_iovec(skb, vlan_offset, iv, total, len);
1282-
total += len;
1282+
skb_copy_datagram_const_iovec(skb, vlan_offset, iv, off, len);
1283+
total += skb->len + (vlan_offset ? sizeof(veth) : 0);
12831284

12841285
done:
12851286
tun->dev->stats.tx_packets++;

0 commit comments

Comments
 (0)