]> git.proxmox.com Git - pve-kernel.git/blob - patches/kernel/0007-net-packet-fix-overflow-in-tpacket_rcv.patch
backport overflow fix for net/packet receive handling
[pve-kernel.git] / patches / kernel / 0007-net-packet-fix-overflow-in-tpacket_rcv.patch
1 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 From: Or Cohen <orcohen@paloaltonetworks.com>
3 Date: Sun, 30 Aug 2020 20:04:51 +0300
4 Subject: [PATCH] net/packet: fix overflow in tpacket_rcv
5
6 Using tp_reserve to calculate netoff can overflow as
7 tp_reserve is unsigned int and netoff is unsigned short.
8
9 This may lead to macoff receving a smaller value then
10 sizeof(struct virtio_net_hdr), and if po->has_vnet_hdr
11 is set, an out-of-bounds write will occur when
12 calling virtio_net_hdr_from_skb.
13
14 The bug is fixed by converting netoff to unsigned int
15 and checking if it exceeds USHRT_MAX.
16
17 Fixes: 8913336a7e8d ("packet: add PACKET_RESERVE sockopt")
18 Signed-off-by: Or Cohen <orcohen@paloaltonetworks.com>
19 Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
20 ---
21 net/packet/af_packet.c | 7 ++++++-
22 1 file changed, 6 insertions(+), 1 deletion(-)
23
24 diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
25 index 7735340c892e..fbc2d4dfddf0 100644
26 --- a/net/packet/af_packet.c
27 +++ b/net/packet/af_packet.c
28 @@ -2169,7 +2169,8 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
29 int skb_len = skb->len;
30 unsigned int snaplen, res;
31 unsigned long status = TP_STATUS_USER;
32 - unsigned short macoff, netoff, hdrlen;
33 + unsigned short macoff, hdrlen;
34 + unsigned int netoff;
35 struct sk_buff *copy_skb = NULL;
36 struct timespec ts;
37 __u32 ts_status;
38 @@ -2238,6 +2239,10 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
39 }
40 macoff = netoff - maclen;
41 }
42 + if (netoff > USHRT_MAX) {
43 + atomic_inc(&po->tp_drops);
44 + goto drop_n_restore;
45 + }
46 if (po->tp_version <= TPACKET_V2) {
47 if (macoff + snaplen > po->rx_ring.frame_size) {
48 if (po->copy_thresh &&