From: Alice Mikityanska <redacted>
The user can specify any gso_size in a packet crafted with an AF_PACKET
PACKET_VNET_HDR socket, even smaller than TCP_MIN_GSO_SIZE = 8. At the
same time, GSO_MAX_SIZE = 8 * GSO_MAX_SEGS = 8 * 65535. When the user
crafts a packet with gso_size < 8, there is a risk for partial GSO to
overflow the 16-bit gso_segs field when dividing the SKB length by
gso_size.
While the previous commit added a generic guard to skb_segment, block
such malformed packets in this commit altogether.
Signed-off-by: Alice Mikityanska <redacted>
---
include/linux/virtio_net.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h
index f36d21b5bc19..11ac9460b16b 100644
--- a/include/linux/virtio_net.h
+++ b/include/linux/virtio_net.h
@@ -188,6 +188,10 @@ static inline int __virtio_net_hdr_to_skb(struct sk_buff *skb,
/* Too small packets are not really GSO ones. */
if (skb->len - nh_off > gso_size) {
+ /* Block packets that would cause a gso_segs overflow. */
+ if (unlikely(skb->len - nh_off > gso_size * GSO_MAX_SEGS))
+ return -EINVAL;
+
shinfo->gso_size = gso_size;
shinfo->gso_type = gso_type;
--
2.55.0