From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wr1-f45.google.com (mail-wr1-f45.google.com [209.85.221.45]) by dpdk.org (Postfix) with ESMTP id 1268528FD for ; Thu, 8 Nov 2018 19:01:40 +0100 (CET) Received: by mail-wr1-f45.google.com with SMTP id e3-v6so24188wrs.5 for ; Thu, 08 Nov 2018 10:01:40 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=e5hiAlx0u6BuQ3UGQUWJLLVQsEf/HTnz0mEmNbh8BUw=; b=F+a74vFnko1Ql49PmNzazJp3FtXuBO00PNXnpQnZwznc2nKgydbBvcCbhMxLEtsSNZ BvVf7WskLksYD8tKP2y5L9DbyLTdGqgY4ltM6656o051TpvXLkuDVuxDugPmxq2AacHV GlpDD5raqF8tP0yZBEf8oOXj4v/xXWmbL6JR3IgjSZlPGWc+d6hQOIj8GEeQFGJnR62O 1pfdAnG1YV3b7EB+Q7oyIIr/VufUO0vjgiTPN07VkjBxf2b53iAu9W5pSXjhj9Ncbu3j NKZjTZrY4MCqiKdWlAKU7eFvafsEhoDal6A120m5QLJIE8PnVpeu5PswP54onIEvyVFj SAbQ== X-Gm-Message-State: AGRZ1gIp9zQfc44B01SKMNLhYd5hUO7V2EH9Pg02EtWoDLAN+h0n7gS8 AJ1pqr9MsdNG/1knMmtIwNUSQiTf X-Google-Smtp-Source: AJdET5fdAtWtcm19mUG+24bBpjf2Anw253MxRoG1C/agnwbN7O855DKwXi/czj6Q8L2EE+0Yz5prEw== X-Received: by 2002:adf:fdc8:: with SMTP id i8-v6mr5435624wrs.276.1541700099597; Thu, 08 Nov 2018 10:01:39 -0800 (PST) Received: from localhost ([2a01:4b00:f419:6f00:8361:8946:ba2b:d556]) by smtp.gmail.com with ESMTPSA id l5-v6sm5680181wrv.84.2018.11.08.10.01.38 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 08 Nov 2018 10:01:38 -0800 (PST) From: Luca Boccassi To: Konstantin Ananyev Cc: Ryan E Hall , Alexander V Gutkin , dpdk stable Date: Thu, 8 Nov 2018 18:01:05 +0000 Message-Id: <20181108180111.25873-9-bluca@debian.org> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181108180111.25873-1-bluca@debian.org> References: <20181029125329.17729-20-bluca@debian.org> <20181108180111.25873-1-bluca@debian.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [dpdk-stable] patch 'ip_frag: check fragment length of incoming packet' has been queued to LTS release 16.11.9 X-BeenThere: stable@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches for DPDK stable branches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 08 Nov 2018 18:01:40 -0000 Hi, FYI, your patch has been queued to LTS release 16.11.9 Note it hasn't been pushed to http://dpdk.org/browse/dpdk-stable yet. It will be pushed if I get no objections before 11/10/18. So please shout if anyone has objections. Also note that after the patch there's a diff of the upstream commit vs the patch applied to the branch. If the code is different (ie: not only metadata diffs), due for example to a change in context or macro names, please double check it. Thanks. Luca Boccassi --- >>From 98b8b5d86b13e3b54c5145a3355acf68967fe954 Mon Sep 17 00:00:00 2001 From: Konstantin Ananyev Date: Mon, 5 Nov 2018 12:18:57 +0000 Subject: [PATCH] ip_frag: check fragment length of incoming packet [ upstream commit 7f0983ee331c9f08dabdb5b7f555ddf399003dcf ] Under some conditions ill-formed fragments might cause reassembly code to corrupt mbufs and/or crash. Let say the following fragments sequence: can trigger the problem. To overcome such situation, added check that fragment length of incoming value is greater than zero. Fixes: 601e279df074 ("ip_frag: move fragmentation/reassembly headers into a library") Fixes: 4f1a8f633862 ("ip_frag: add IPv6 reassembly") Reported-by: Ryan E Hall Reported-by: Alexander V Gutkin Signed-off-by: Konstantin Ananyev --- lib/librte_ip_frag/rte_ipv4_reassembly.c | 22 +++++++++++++------ lib/librte_ip_frag/rte_ipv6_reassembly.c | 28 +++++++++++++++++------- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/lib/librte_ip_frag/rte_ipv4_reassembly.c b/lib/librte_ip_frag/rte_ipv4_reassembly.c index 847ea0d63..ede2ae090 100644 --- a/lib/librte_ip_frag/rte_ipv4_reassembly.c +++ b/lib/librte_ip_frag/rte_ipv4_reassembly.c @@ -65,8 +65,11 @@ ipv4_frag_reassemble(struct ip_frag_pkt *fp) /* previous fragment found. */ if(fp->frags[i].ofs + fp->frags[i].len == ofs) { + RTE_ASSERT(curr_idx != i); + /* adjust start of the last fragment data. */ - rte_pktmbuf_adj(m, (uint16_t)(m->l2_len + m->l3_len)); + rte_pktmbuf_adj(m, + (uint16_t)(m->l2_len + m->l3_len)); rte_pktmbuf_chain(fp->frags[i].mb, m); /* this mbuf should not be accessed directly */ @@ -125,14 +128,14 @@ ipv4_frag_reassemble(struct ip_frag_pkt *fp) */ struct rte_mbuf * rte_ipv4_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl, - struct rte_ip_frag_death_row *dr, struct rte_mbuf *mb, uint64_t tms, - struct ipv4_hdr *ip_hdr) + struct rte_ip_frag_death_row *dr, struct rte_mbuf *mb, uint64_t tms, + struct ipv4_hdr *ip_hdr) { struct ip_frag_pkt *fp; struct ip_frag_key key; const unaligned_uint64_t *psd; - uint16_t ip_len; uint16_t flag_offset, ip_ofs, ip_flag; + int32_t ip_len; flag_offset = rte_be_to_cpu_16(ip_hdr->fragment_offset); ip_ofs = (uint16_t)(flag_offset & IPV4_HDR_OFFSET_MASK); @@ -145,12 +148,11 @@ rte_ipv4_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl, key.key_len = IPV4_KEYLEN; ip_ofs *= IPV4_HDR_OFFSET_UNITS; - ip_len = (uint16_t)(rte_be_to_cpu_16(ip_hdr->total_length) - - mb->l3_len); + ip_len = rte_be_to_cpu_16(ip_hdr->total_length) - mb->l3_len; IP_FRAG_LOG(DEBUG, "%s:%d:\n" "mbuf: %p, tms: %" PRIu64 - ", key: <%" PRIx64 ", %#x>, ofs: %u, len: %u, flags: %#x\n" + ", key: <%" PRIx64 ", %#x>, ofs: %u, len: %d, flags: %#x\n" "tbl: %p, max_cycles: %" PRIu64 ", entry_mask: %#x, " "max_entries: %u, use_entries: %u\n\n", __func__, __LINE__, @@ -158,6 +160,12 @@ rte_ipv4_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl, tbl, tbl->max_cycles, tbl->entry_mask, tbl->max_entries, tbl->use_entries); + /* check that fragment length is greater then zero. */ + if (ip_len <= 0) { + IP_FRAG_MBUF2DR(dr, mb); + return NULL; + } + /* try to find/add entry into the fragment's table. */ if ((fp = ip_frag_find(tbl, dr, &key, tms)) == NULL) { IP_FRAG_MBUF2DR(dr, mb); diff --git a/lib/librte_ip_frag/rte_ipv6_reassembly.c b/lib/librte_ip_frag/rte_ipv6_reassembly.c index d9b5d6903..9f080d6e9 100644 --- a/lib/librte_ip_frag/rte_ipv6_reassembly.c +++ b/lib/librte_ip_frag/rte_ipv6_reassembly.c @@ -88,8 +88,11 @@ ipv6_frag_reassemble(struct ip_frag_pkt *fp) /* previous fragment found. */ if (fp->frags[i].ofs + fp->frags[i].len == ofs) { + RTE_ASSERT(curr_idx != i); + /* adjust start of the last fragment data. */ - rte_pktmbuf_adj(m, (uint16_t)(m->l2_len + m->l3_len)); + rte_pktmbuf_adj(m, + (uint16_t)(m->l2_len + m->l3_len)); rte_pktmbuf_chain(fp->frags[i].mb, m); /* this mbuf should not be accessed directly */ @@ -164,12 +167,13 @@ ipv6_frag_reassemble(struct ip_frag_pkt *fp) #define FRAG_OFFSET(x) (rte_cpu_to_be_16(x) >> 3) struct rte_mbuf * rte_ipv6_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl, - struct rte_ip_frag_death_row *dr, struct rte_mbuf *mb, uint64_t tms, - struct ipv6_hdr *ip_hdr, struct ipv6_extension_fragment *frag_hdr) + struct rte_ip_frag_death_row *dr, struct rte_mbuf *mb, uint64_t tms, + struct ipv6_hdr *ip_hdr, struct ipv6_extension_fragment *frag_hdr) { struct ip_frag_pkt *fp; struct ip_frag_key key; - uint16_t ip_len, ip_ofs; + uint16_t ip_ofs; + int32_t ip_len; rte_memcpy(&key.src_dst[0], ip_hdr->src_addr, 16); rte_memcpy(&key.src_dst[2], ip_hdr->dst_addr, 16); @@ -180,15 +184,17 @@ rte_ipv6_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl, ip_ofs = FRAG_OFFSET(frag_hdr->frag_data) * 8; /* - * as per RFC2460, payload length contains all extension headers as well. - * since we don't support anything but frag headers, this is what we remove - * from the payload len. + * as per RFC2460, payload length contains all extension headers + * as well. + * since we don't support anything but frag headers, + * this is what we remove from the payload len. */ ip_len = rte_be_to_cpu_16(ip_hdr->payload_len) - sizeof(*frag_hdr); IP_FRAG_LOG(DEBUG, "%s:%d:\n" "mbuf: %p, tms: %" PRIu64 - ", key: <" IPv6_KEY_BYTES_FMT ", %#x>, ofs: %u, len: %u, flags: %#x\n" + ", key: <" IPv6_KEY_BYTES_FMT ", %#x>, " + "ofs: %u, len: %d, flags: %#x\n" "tbl: %p, max_cycles: %" PRIu64 ", entry_mask: %#x, " "max_entries: %u, use_entries: %u\n\n", __func__, __LINE__, @@ -197,6 +203,12 @@ rte_ipv6_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl, tbl, tbl->max_cycles, tbl->entry_mask, tbl->max_entries, tbl->use_entries); + /* check that fragment length is greater then zero. */ + if (ip_len <= 0) { + IP_FRAG_MBUF2DR(dr, mb); + return NULL; + } + /* try to find/add entry into the fragment's table. */ fp = ip_frag_find(tbl, dr, &key, tms); if (fp == NULL) { -- 2.19.1 --- Diff of the applied patch vs upstream commit (please double-check if non-empty: --- --- - 2018-11-08 17:59:30.232489867 +0000 +++ 0009-ip_frag-check-fragment-length-of-incoming-packet.patch 2018-11-08 17:59:30.056751011 +0000 @@ -1,8 +1,10 @@ -From 7f0983ee331c9f08dabdb5b7f555ddf399003dcf Mon Sep 17 00:00:00 2001 +From 98b8b5d86b13e3b54c5145a3355acf68967fe954 Mon Sep 17 00:00:00 2001 From: Konstantin Ananyev Date: Mon, 5 Nov 2018 12:18:57 +0000 Subject: [PATCH] ip_frag: check fragment length of incoming packet +[ upstream commit 7f0983ee331c9f08dabdb5b7f555ddf399003dcf ] + Under some conditions ill-formed fragments might cause reassembly code to corrupt mbufs and/or crash. Let say the following fragments sequence: @@ -16,7 +18,6 @@ Fixes: 601e279df074 ("ip_frag: move fragmentation/reassembly headers into a library") Fixes: 4f1a8f633862 ("ip_frag: add IPv6 reassembly") -Cc: stable@dpdk.org Reported-by: Ryan E Hall Reported-by: Alexander V Gutkin @@ -27,10 +28,10 @@ 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/lib/librte_ip_frag/rte_ipv4_reassembly.c b/lib/librte_ip_frag/rte_ipv4_reassembly.c -index 4956b99ea..1029b7abc 100644 +index 847ea0d63..ede2ae090 100644 --- a/lib/librte_ip_frag/rte_ipv4_reassembly.c +++ b/lib/librte_ip_frag/rte_ipv4_reassembly.c -@@ -36,8 +36,11 @@ ipv4_frag_reassemble(struct ip_frag_pkt *fp) +@@ -65,8 +65,11 @@ ipv4_frag_reassemble(struct ip_frag_pkt *fp) /* previous fragment found. */ if(fp->frags[i].ofs + fp->frags[i].len == ofs) { @@ -43,7 +44,7 @@ rte_pktmbuf_chain(fp->frags[i].mb, m); /* this mbuf should not be accessed directly */ -@@ -96,14 +99,14 @@ ipv4_frag_reassemble(struct ip_frag_pkt *fp) +@@ -125,14 +128,14 @@ ipv4_frag_reassemble(struct ip_frag_pkt *fp) */ struct rte_mbuf * rte_ipv4_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl, @@ -61,7 +62,7 @@ flag_offset = rte_be_to_cpu_16(ip_hdr->fragment_offset); ip_ofs = (uint16_t)(flag_offset & IPV4_HDR_OFFSET_MASK); -@@ -116,12 +119,11 @@ rte_ipv4_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl, +@@ -145,12 +148,11 @@ rte_ipv4_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl, key.key_len = IPV4_KEYLEN; ip_ofs *= IPV4_HDR_OFFSET_UNITS; @@ -76,7 +77,7 @@ "tbl: %p, max_cycles: %" PRIu64 ", entry_mask: %#x, " "max_entries: %u, use_entries: %u\n\n", __func__, __LINE__, -@@ -129,6 +131,12 @@ rte_ipv4_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl, +@@ -158,6 +160,12 @@ rte_ipv4_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl, tbl, tbl->max_cycles, tbl->entry_mask, tbl->max_entries, tbl->use_entries); @@ -90,10 +91,10 @@ if ((fp = ip_frag_find(tbl, dr, &key, tms)) == NULL) { IP_FRAG_MBUF2DR(dr, mb); diff --git a/lib/librte_ip_frag/rte_ipv6_reassembly.c b/lib/librte_ip_frag/rte_ipv6_reassembly.c -index db249fe60..855e3f740 100644 +index d9b5d6903..9f080d6e9 100644 --- a/lib/librte_ip_frag/rte_ipv6_reassembly.c +++ b/lib/librte_ip_frag/rte_ipv6_reassembly.c -@@ -59,8 +59,11 @@ ipv6_frag_reassemble(struct ip_frag_pkt *fp) +@@ -88,8 +88,11 @@ ipv6_frag_reassemble(struct ip_frag_pkt *fp) /* previous fragment found. */ if (fp->frags[i].ofs + fp->frags[i].len == ofs) { @@ -106,7 +107,7 @@ rte_pktmbuf_chain(fp->frags[i].mb, m); /* this mbuf should not be accessed directly */ -@@ -135,12 +138,13 @@ ipv6_frag_reassemble(struct ip_frag_pkt *fp) +@@ -164,12 +167,13 @@ ipv6_frag_reassemble(struct ip_frag_pkt *fp) #define FRAG_OFFSET(x) (rte_cpu_to_be_16(x) >> 3) struct rte_mbuf * rte_ipv6_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl, @@ -123,7 +124,7 @@ rte_memcpy(&key.src_dst[0], ip_hdr->src_addr, 16); rte_memcpy(&key.src_dst[2], ip_hdr->dst_addr, 16); -@@ -151,15 +155,17 @@ rte_ipv6_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl, +@@ -180,15 +184,17 @@ rte_ipv6_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl, ip_ofs = FRAG_OFFSET(frag_hdr->frag_data) * 8; /* @@ -145,7 +146,7 @@ "tbl: %p, max_cycles: %" PRIu64 ", entry_mask: %#x, " "max_entries: %u, use_entries: %u\n\n", __func__, __LINE__, -@@ -168,6 +174,12 @@ rte_ipv6_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl, +@@ -197,6 +203,12 @@ rte_ipv6_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl, tbl, tbl->max_cycles, tbl->entry_mask, tbl->max_entries, tbl->use_entries);