Skip to content

Commit 730054d

Browse files
jasowangdavem330
authored andcommitted
macvtap: signal truncated packets
macvtap_put_user() never return a value grater than iov length, this in fact bypasses the truncated checking in macvtap_recvmsg(). Fix this by always returning the size of packet plus the possible vlan header to let the truncated checking work. 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 923347b commit 730054d

File tree

1 file changed

+14
-13
lines changed

1 file changed

+14
-13
lines changed

drivers/net/macvtap.c

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -767,10 +767,14 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
767767
const struct sk_buff *skb,
768768
const struct iovec *iv, int len)
769769
{
770-
int ret;
770+
int ret, off;
771771
int vnet_hdr_len = 0;
772772
int vlan_offset = 0;
773773
int copied;
774+
struct {
775+
__be16 h_vlan_proto;
776+
__be16 h_vlan_TCI;
777+
} veth;
774778

775779
if (q->flags & IFF_VNET_HDR) {
776780
struct virtio_net_hdr vnet_hdr;
@@ -785,39 +789,36 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
785789
if (memcpy_toiovecend(iv, (void *)&vnet_hdr, 0, sizeof(vnet_hdr)))
786790
return -EFAULT;
787791
}
788-
copied = vnet_hdr_len;
792+
off = copied = vnet_hdr_len;
789793

790794
if (!vlan_tx_tag_present(skb))
791795
len = min_t(int, skb->len, len);
792796
else {
793797
int copy;
794-
struct {
795-
__be16 h_vlan_proto;
796-
__be16 h_vlan_TCI;
797-
} veth;
798+
798799
veth.h_vlan_proto = skb->vlan_proto;
799800
veth.h_vlan_TCI = htons(vlan_tx_tag_get(skb));
800801

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

804805
copy = min_t(int, vlan_offset, len);
805-
ret = skb_copy_datagram_const_iovec(skb, 0, iv, copied, copy);
806+
ret = skb_copy_datagram_const_iovec(skb, 0, iv, off, copy);
806807
len -= copy;
807-
copied += copy;
808+
off += copy;
808809
if (ret || !len)
809810
goto done;
810811

811812
copy = min_t(int, sizeof(veth), len);
812-
ret = memcpy_toiovecend(iv, (void *)&veth, copied, copy);
813+
ret = memcpy_toiovecend(iv, (void *)&veth, off, copy);
813814
len -= copy;
814-
copied += copy;
815+
off += copy;
815816
if (ret || !len)
816817
goto done;
817818
}
818819

819-
ret = skb_copy_datagram_const_iovec(skb, vlan_offset, iv, copied, len);
820-
copied += len;
820+
ret = skb_copy_datagram_const_iovec(skb, vlan_offset, iv, off, len);
821+
copied += skb->len + (vlan_offset ? sizeof(veth) : 0);
821822

822823
done:
823824
return ret ? ret : copied;
@@ -875,7 +876,7 @@ static ssize_t macvtap_aio_read(struct kiocb *iocb, const struct iovec *iv,
875876
}
876877

877878
ret = macvtap_do_read(q, iocb, iv, len, file->f_flags & O_NONBLOCK);
878-
ret = min_t(ssize_t, ret, len); /* XXX copied from tun.c. Why? */
879+
ret = min_t(ssize_t, ret, len);
879880
if (ret > 0)
880881
iocb->ki_pos = ret;
881882
out:

0 commit comments

Comments
 (0)