gro: check invalid TCP header length
authorJiayu Hu <jiayu.hu@intel.com>
Wed, 16 Jan 2019 00:45:33 +0000 (08:45 +0800)
committerThomas Monjalon <thomas@monjalon.net>
Thu, 17 Jan 2019 21:38:54 +0000 (22:38 +0100)
When the TCP header length of input packets is invalid (i.e., less
than 20 bytes or greater than 60 bytes), check_seq_option() will
access illegal memory area when compare TCP Options, which may
cause a segmentation fault.

This patch adds missing invalid TCP header length check to avoid
illegal memory accesses.

Fixes: 0d2cbe59b719 ("lib/gro: support TCP/IPv4")
Fixes: 9e0b9d2ec0f4 ("gro: support VxLAN GRO")
Cc: stable@dpdk.org
Signed-off-by: Jiayu Hu <jiayu.hu@intel.com>
Tested-by: Yinan Wang <yinan.wang@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
lib/librte_gro/gro_tcp4.c
lib/librte_gro/gro_tcp4.h
lib/librte_gro/gro_vxlan_tcp4.c

index 2fe9aab..7d128a4 100644 (file)
@@ -208,6 +208,13 @@ gro_tcp4_reassemble(struct rte_mbuf *pkt,
        int cmp;
        uint8_t find;
 
+       /*
+        * Don't process the packet whose TCP header length is greater
+        * than 60 bytes or less than 20 bytes.
+        */
+       if (unlikely(INVALID_TCP_HDRLEN(pkt->l4_len)))
+               return -1;
+
        eth_hdr = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
        ipv4_hdr = (struct ipv4_hdr *)((char *)eth_hdr + pkt->l2_len);
        tcp_hdr = (struct tcp_hdr *)((char *)ipv4_hdr + pkt->l3_len);
index 6bb30cd..d979248 100644 (file)
  */
 #define MAX_IPV4_PKT_LENGTH UINT16_MAX
 
+/* The maximum TCP header length */
+#define MAX_TCP_HLEN 60
+#define INVALID_TCP_HDRLEN(len) \
+       (((len) < sizeof(struct tcp_hdr)) || ((len) > MAX_TCP_HLEN))
+
 /* Header fields representing a TCP/IPv4 flow */
 struct tcp4_flow_key {
        struct ether_addr eth_saddr;
index 955ae4b..acb9bc9 100644 (file)
@@ -306,6 +306,13 @@ gro_vxlan_tcp4_reassemble(struct rte_mbuf *pkt,
        uint16_t hdr_len;
        uint8_t find;
 
+       /*
+        * Don't process the packet whose TCP header length is greater
+        * than 60 bytes or less than 20 bytes.
+        */
+       if (unlikely(INVALID_TCP_HDRLEN(pkt->l4_len)))
+               return -1;
+
        outer_eth_hdr = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
        outer_ipv4_hdr = (struct ipv4_hdr *)((char *)outer_eth_hdr +
                        pkt->outer_l2_len);