Skip to content

Commit 1cf8b5c

Browse files
committed
net: more strict VIRTIO_NET_HDR_GSO_UDP_L4 validation
JIRA: https://issues.redhat.com/browse/RHEL-54891 CVE: CVE-2024-43817 commit fc8b2a6 Author: Willem de Bruijn <willemb@google.com> Date: Wed Oct 11 10:01:14 2023 -0400 net: more strict VIRTIO_NET_HDR_GSO_UDP_L4 validation Syzbot reported two new paths to hit an internal WARNING using the new virtio gso type VIRTIO_NET_HDR_GSO_UDP_L4. RIP: 0010:skb_checksum_help+0x4a2/0x600 net/core/dev.c:3260 skb len=64521 gso_size=344 and RIP: 0010:skb_warn_bad_offload+0x118/0x240 net/core/dev.c:3262 Older virtio types have historically had loose restrictions, leading to many entirely impractical fuzzer generated packets causing problems deep in the kernel stack. Ideally, we would have had strict validation for all types from the start. New virtio types can have tighter validation. Limit UDP GSO packets inserted via virtio to the same limits imposed by the UDP_SEGMENT socket interface: 1. must use checksum offload 2. checksum offload matches UDP header 3. no more segments than UDP_MAX_SEGMENTS 4. UDP GSO does not take modifier flags, notably SKB_GSO_TCP_ECN Fixes: 860b7f2 ("linux/virtio_net.h: Support USO offload in vnet header.") Reported-by: syzbot+01cdbc31e9c0ae9b33ac@syzkaller.appspotmail.com Closes: https://lore.kernel.org/netdev/0000000000005039270605eb0b7f@google.com/ Reported-by: syzbot+c99d835ff081ca30f986@syzkaller.appspotmail.com Closes: https://lore.kernel.org/netdev/0000000000005426680605eb0b9f@google.com/ Signed-off-by: Willem de Bruijn <willemb@google.com> Reviewed-by: Eric Dumazet <edumazet@google.com> Acked-by: Jason Wang <jasowang@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Laurent Vivier <lvivier@redhat.com>
1 parent 806f39e commit 1cf8b5c

File tree

1 file changed

+16
-3
lines changed

1 file changed

+16
-3
lines changed

include/linux/virtio_net.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
#define _LINUX_VIRTIO_NET_H
44

55
#include <linux/if_vlan.h>
6+
#include <linux/udp.h>
67
#include <uapi/linux/tcp.h>
7-
#include <uapi/linux/udp.h>
88
#include <uapi/linux/virtio_net.h>
99

1010
static inline bool virtio_net_hdr_match_proto(__be16 protocol, __u8 gso_type)
@@ -162,9 +162,22 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb,
162162
unsigned int nh_off = p_off;
163163
struct skb_shared_info *shinfo = skb_shinfo(skb);
164164

165-
/* UFO may not include transport header in gso_size. */
166-
if (gso_type & SKB_GSO_UDP)
165+
switch (gso_type & ~SKB_GSO_TCP_ECN) {
166+
case SKB_GSO_UDP:
167+
/* UFO may not include transport header in gso_size. */
167168
nh_off -= thlen;
169+
break;
170+
case SKB_GSO_UDP_L4:
171+
if (!(hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM))
172+
return -EINVAL;
173+
if (skb->csum_offset != offsetof(struct udphdr, check))
174+
return -EINVAL;
175+
if (skb->len - p_off > gso_size * UDP_MAX_SEGMENTS)
176+
return -EINVAL;
177+
if (gso_type != SKB_GSO_UDP_L4)
178+
return -EINVAL;
179+
break;
180+
}
168181

169182
/* Too small packets are not really GSO ones. */
170183
if (skb->len - nh_off > gso_size) {

0 commit comments

Comments
 (0)