net/tap: add buffer overflow checks before checksum
authorBruce Richardson <bruce.richardson@intel.com>
Mon, 17 Dec 2018 15:50:05 +0000 (15:50 +0000)
committerFerruh Yigit <ferruh.yigit@intel.com>
Fri, 21 Dec 2018 15:22:41 +0000 (16:22 +0100)
The checksum calculation APIs take only the packet headers pointers as
parameters, so they assume that the lengths reported in those headers
are correct. However, a malicious packet could claim to be far larger
than it is, so we need to check the header lengths in the driver before
calling the checksum API.

A better fix would be to allow the lengths to be passed into the API
function, but that would be an API break, so fixing in TAP driver for
now.

Fixes: 8ae3023387e9 ("net/tap: add Rx/Tx checksum offload support")
Cc: stable@dpdk.org
Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
Acked-by: Keith Wiles <keith.wiles@intel.com>
drivers/net/tap/rte_eth_tap.c

index 49afd38..0ec030b 100644 (file)
@@ -281,13 +281,27 @@ tap_verify_csum(struct rte_mbuf *mbuf)
                l3_len = 4 * (iph->version_ihl & 0xf);
                if (unlikely(l2_len + l3_len > rte_pktmbuf_data_len(mbuf)))
                        return;
+               /* check that the total length reported by header is not
+                * greater than the total received size
+                */
+               if (l2_len + rte_be_to_cpu_16(iph->total_length) >
+                               rte_pktmbuf_data_len(mbuf))
+                       return;
 
                cksum = ~rte_raw_cksum(iph, l3_len);
                mbuf->ol_flags |= cksum ?
                        PKT_RX_IP_CKSUM_BAD :
                        PKT_RX_IP_CKSUM_GOOD;
        } else if (l3 == RTE_PTYPE_L3_IPV6) {
+               struct ipv6_hdr *iph = l3_hdr;
+
                l3_len = sizeof(struct ipv6_hdr);
+               /* check that the total length reported by header is not
+                * greater than the total received size
+                */
+               if (l2_len + l3_len + rte_be_to_cpu_16(iph->payload_len) >
+                               rte_pktmbuf_data_len(mbuf))
+                       return;
        } else {
                /* IPv6 extensions are not supported */
                return;