| From e2fcad58fd230f635a74e4e983c6f4ea893642d2 Mon Sep 17 00:00:00 2001 |
| From: "Jason A. Donenfeld" <Jason@zx2c4.com> |
| Date: Sun, 4 Jun 2017 04:16:26 +0200 |
| Subject: virtio_net: check return value of skb_to_sgvec always |
| |
| From: Jason A. Donenfeld <Jason@zx2c4.com> |
| |
| commit e2fcad58fd230f635a74e4e983c6f4ea893642d2 upstream. |
| |
| Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com> |
| Reviewed-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com> |
| Cc: "Michael S. Tsirkin" <mst@redhat.com> |
| Cc: Jason Wang <jasowang@redhat.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Nathan Chancellor <natechancellor@gmail.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/net/virtio_net.c | 9 +++++++-- |
| 1 file changed, 7 insertions(+), 2 deletions(-) |
| |
| --- a/drivers/net/virtio_net.c |
| +++ b/drivers/net/virtio_net.c |
| @@ -831,7 +831,7 @@ static int xmit_skb(struct send_queue *s |
| struct virtio_net_hdr_mrg_rxbuf *hdr; |
| const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; |
| struct virtnet_info *vi = sq->vq->vdev->priv; |
| - unsigned num_sg; |
| + int num_sg; |
| unsigned hdr_len = vi->hdr_len; |
| bool can_push; |
| |
| @@ -858,11 +858,16 @@ static int xmit_skb(struct send_queue *s |
| if (can_push) { |
| __skb_push(skb, hdr_len); |
| num_sg = skb_to_sgvec(skb, sq->sg, 0, skb->len); |
| + if (unlikely(num_sg < 0)) |
| + return num_sg; |
| /* Pull header back to avoid skew in tx bytes calculations. */ |
| __skb_pull(skb, hdr_len); |
| } else { |
| sg_set_buf(sq->sg, hdr, hdr_len); |
| - num_sg = skb_to_sgvec(skb, sq->sg + 1, 0, skb->len) + 1; |
| + num_sg = skb_to_sgvec(skb, sq->sg + 1, 0, skb->len); |
| + if (unlikely(num_sg < 0)) |
| + return num_sg; |
| + num_sg++; |
| } |
| return virtqueue_add_outbuf(sq->vq, sq->sg, num_sg, skb, GFP_ATOMIC); |
| } |