Message ID | 20210622161533.1214662-3-dwmw2@infradead.org (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | net: tun: fix tun_xdp_one() for IFF_TUN mode | expand |
在 2021/6/23 上午12:15, David Woodhouse 写道: > From: David Woodhouse <dwmw@amazon.co.uk> > > When the underlying socket doesn't handle the virtio_net_hdr, the > existing code in vhost_net_build_xdp() would attempt to validate stack > noise, by copying zero bytes into the local copy of the header and then > validating that. Skip the whole pointless pointer arithmetic and partial > copy (of zero bytes) in this case. > > Fixes: 0a0be13b8fe2 ("vhost_net: batch submitting XDP buffers to underlayer sockets") > Signed-off-by: David Woodhouse <dwmw@amazon.co.uk> Acked-by: Jason Wang <jasowang@redhat.com> > --- > drivers/vhost/net.c | 43 ++++++++++++++++++++++--------------------- > 1 file changed, 22 insertions(+), 21 deletions(-) > > diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c > index df82b124170e..1e3652eb53af 100644 > --- a/drivers/vhost/net.c > +++ b/drivers/vhost/net.c > @@ -690,7 +690,6 @@ static int vhost_net_build_xdp(struct vhost_net_virtqueue *nvq, > dev); > struct socket *sock = vhost_vq_get_backend(vq); > struct page_frag *alloc_frag = &net->page_frag; > - struct virtio_net_hdr *gso; > struct xdp_buff *xdp = &nvq->xdp[nvq->batched_xdp]; > struct tun_xdp_hdr *hdr; > size_t len = iov_iter_count(from); > @@ -715,29 +714,31 @@ static int vhost_net_build_xdp(struct vhost_net_virtqueue *nvq, > return -ENOMEM; > > buf = (char *)page_address(alloc_frag->page) + alloc_frag->offset; > - copied = copy_page_from_iter(alloc_frag->page, > - alloc_frag->offset + > - offsetof(struct tun_xdp_hdr, gso), > - sock_hlen, from); > - if (copied != sock_hlen) > - return -EFAULT; > - > hdr = buf; > - gso = &hdr->gso; > - > - if ((gso->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && > - vhost16_to_cpu(vq, gso->csum_start) + > - vhost16_to_cpu(vq, gso->csum_offset) + 2 > > - vhost16_to_cpu(vq, gso->hdr_len)) { > - gso->hdr_len = cpu_to_vhost16(vq, > - vhost16_to_cpu(vq, gso->csum_start) + > - vhost16_to_cpu(vq, gso->csum_offset) + 2); > - > - if (vhost16_to_cpu(vq, gso->hdr_len) > len) > - return -EINVAL; > + if (sock_hlen) { > + struct virtio_net_hdr *gso = &hdr->gso; > + > + copied = copy_page_from_iter(alloc_frag->page, > + alloc_frag->offset + > + offsetof(struct tun_xdp_hdr, gso), > + sock_hlen, from); > + if (copied != sock_hlen) > + return -EFAULT; > + > + if ((gso->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && > + vhost16_to_cpu(vq, gso->csum_start) + > + vhost16_to_cpu(vq, gso->csum_offset) + 2 > > + vhost16_to_cpu(vq, gso->hdr_len)) { > + gso->hdr_len = cpu_to_vhost16(vq, > + vhost16_to_cpu(vq, gso->csum_start) + > + vhost16_to_cpu(vq, gso->csum_offset) + 2); > + > + if (vhost16_to_cpu(vq, gso->hdr_len) > len) > + return -EINVAL; > + } > + len -= sock_hlen; > } > > - len -= sock_hlen; > copied = copy_page_from_iter(alloc_frag->page, > alloc_frag->offset + pad, > len, from);
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index df82b124170e..1e3652eb53af 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -690,7 +690,6 @@ static int vhost_net_build_xdp(struct vhost_net_virtqueue *nvq, dev); struct socket *sock = vhost_vq_get_backend(vq); struct page_frag *alloc_frag = &net->page_frag; - struct virtio_net_hdr *gso; struct xdp_buff *xdp = &nvq->xdp[nvq->batched_xdp]; struct tun_xdp_hdr *hdr; size_t len = iov_iter_count(from); @@ -715,29 +714,31 @@ static int vhost_net_build_xdp(struct vhost_net_virtqueue *nvq, return -ENOMEM; buf = (char *)page_address(alloc_frag->page) + alloc_frag->offset; - copied = copy_page_from_iter(alloc_frag->page, - alloc_frag->offset + - offsetof(struct tun_xdp_hdr, gso), - sock_hlen, from); - if (copied != sock_hlen) - return -EFAULT; - hdr = buf; - gso = &hdr->gso; - - if ((gso->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && - vhost16_to_cpu(vq, gso->csum_start) + - vhost16_to_cpu(vq, gso->csum_offset) + 2 > - vhost16_to_cpu(vq, gso->hdr_len)) { - gso->hdr_len = cpu_to_vhost16(vq, - vhost16_to_cpu(vq, gso->csum_start) + - vhost16_to_cpu(vq, gso->csum_offset) + 2); - - if (vhost16_to_cpu(vq, gso->hdr_len) > len) - return -EINVAL; + if (sock_hlen) { + struct virtio_net_hdr *gso = &hdr->gso; + + copied = copy_page_from_iter(alloc_frag->page, + alloc_frag->offset + + offsetof(struct tun_xdp_hdr, gso), + sock_hlen, from); + if (copied != sock_hlen) + return -EFAULT; + + if ((gso->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && + vhost16_to_cpu(vq, gso->csum_start) + + vhost16_to_cpu(vq, gso->csum_offset) + 2 > + vhost16_to_cpu(vq, gso->hdr_len)) { + gso->hdr_len = cpu_to_vhost16(vq, + vhost16_to_cpu(vq, gso->csum_start) + + vhost16_to_cpu(vq, gso->csum_offset) + 2); + + if (vhost16_to_cpu(vq, gso->hdr_len) > len) + return -EINVAL; + } + len -= sock_hlen; } - len -= sock_hlen; copied = copy_page_from_iter(alloc_frag->page, alloc_frag->offset + pad, len, from);