Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp1039400imu; Thu, 13 Dec 2018 08:26:08 -0800 (PST) X-Google-Smtp-Source: AFSGD/VVGREZVGxNyLprco7yjwAWSGnWH8BnsS3HSVwpqrdSxCMHqEibyv3OtZQwQBJ1oMg/xHzw X-Received: by 2002:a17:902:2c83:: with SMTP id n3mr24406043plb.104.1544718368806; Thu, 13 Dec 2018 08:26:08 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1544718368; cv=none; d=google.com; s=arc-20160816; b=ICI8YfArv0ooeWhOOrXY/1DQUicG5JQTel2Kcd/FzUSPL0YhC7aCm+1Q9/4tDlBamR o3iAB28Tmt7SHS9ZRHiPZuBSUcgL6GkX9ghInjf4SB+Kq7ozKyU9laWWMfy/3QXfhFhj 9mCvpeZNrUnsE4szYNRtZ2avl2OoLeEkVwAulr2gic0MFfKBwOM6j0PUxuGRtriu+7Mh VyTq4HMUp1JdzMp9VetYxfRxSoYGQp1DlaoUfSFUk6JrnixaRx/fjZeSsbUxmW7N/zW9 PKyOGeAzr8ioSRKyn7B8m+TGbLjv+MqnJ0zwZCtCRutvIjQD5Qv/qEzcmkW1Hf3RRNHP il/g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:date:message-id:cc:to:subject:from; bh=ZNqAfkdIXJCx39HpGIwOAxgNGuQJsqfQ0EuW3gmH4Ho=; b=tvffZTQn4Ou5ToPr0dOcB3Kb1+XUm1QDNi9iyOz+yirwFO103vYA433M3bmHVxHicg pCOyi84Q6jxNuRDYYWppPgwlWWudAQsSJgeF63EvDAaFmc7dHsTo85HCRq5vkhdZukRc KBQh/9ldA7qpUb81E9bSqaOGMM2ZyhzPTBju/ara5c0S9ZtRDXvijus7gabTAPEAEvku pqCa8G9KrLMXXD87u1Qz+UBUsloJBZCItux1cqyO0LAJ72dit2XT3aKOrGlhKbe2DX3M 20kQZCz62rrOKvDlak4f9nZNwygXLKoy4g1axnys1AvNKsP2SBBjtD01Ld6raH969pvd Faow== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id s71si1912959pfk.105.2018.12.13.08.25.44; Thu, 13 Dec 2018 08:26:08 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729510AbeLMQXf (ORCPT + 99 others); Thu, 13 Dec 2018 11:23:35 -0500 Received: from mx2.suse.de ([195.135.220.15]:37384 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728059AbeLMQXf (ORCPT ); Thu, 13 Dec 2018 11:23:35 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 939E3AF0D; Thu, 13 Dec 2018 16:23:33 +0000 (UTC) Received: by unicorn.suse.cz (Postfix, from userid 1000) id E426FE1116; Thu, 13 Dec 2018 17:23:32 +0100 (CET) From: Michal Kubecek Subject: [PATCH net v2] net: ipv4: do not handle duplicate fragments as overlapping To: "David S. Miller" Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Peter Oskolkov , Eric Dumazet , Gustavo Figueira Message-Id: <20181213162332.E426FE1116@unicorn.suse.cz> Date: Thu, 13 Dec 2018 17:23:32 +0100 (CET) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Since commit 7969e5c40dfd ("ip: discard IPv4 datagrams with overlapping segments.") IPv4 reassembly code drops the whole queue whenever an overlapping fragment is received. However, the test is written in a way which detects duplicate fragments as overlapping so that in environments with many duplicate packets, fragmented packets may be undeliverable. Add an extra test and for (potentially) duplicate fragment, only drop the new fragment rather than the whole queue. Only starting offset and length are checked, not the contents of the fragments as that would be too expensive. For similar reason, linear list ("run") of a rbtree node is not iterated, we only check if the new fragment is a subset of the interval covered by existing consecutive fragments. Fixes: 7969e5c40dfd ("ip: discard IPv4 datagrams with overlapping segments.") Signed-off-by: Michal Kubecek v2: instead of an exact check iterating through linear list of an rbtree node, only check if the new fragment is subset of the "run" (suggested by Eric Dumazet) --- net/ipv4/ip_fragment.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index aa0b22697998..867be8f7f1fa 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -346,10 +346,10 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb) struct net *net = container_of(qp->q.net, struct net, ipv4.frags); struct rb_node **rbn, *parent; struct sk_buff *skb1, *prev_tail; + int ihl, end, skb1_run_end; struct net_device *dev; unsigned int fragsize; int flags, offset; - int ihl, end; int err = -ENOENT; u8 ecn; @@ -419,7 +419,9 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb) * overlapping fragment, the entire datagram (and any constituent * fragments) MUST be silently discarded. * - * We do the same here for IPv4 (and increment an snmp counter). + * We do the same here for IPv4 (and increment an snmp counter) but + * we do not want to drop the whole queue in response to a duplicate + * fragment. */ err = -EINVAL; @@ -444,13 +446,17 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb) do { parent = *rbn; skb1 = rb_to_skb(parent); + skb1_run_end = skb1->ip_defrag_offset + + FRAG_CB(skb1)->frag_run_len; if (end <= skb1->ip_defrag_offset) rbn = &parent->rb_left; - else if (offset >= skb1->ip_defrag_offset + - FRAG_CB(skb1)->frag_run_len) + else if (offset >= skb1_run_end) rbn = &parent->rb_right; - else /* Found an overlap with skb1. */ - goto overlap; + else if (offset >= skb1->ip_defrag_offset && + end <= skb1_run_end) + goto err; /* No new data, potential duplicate */ + else + goto overlap; /* Found an overlap */ } while (*rbn); /* Here we have parent properly set, and rbn pointing to * one of its NULL left/right children. Insert skb. -- 2.19.2