From patchwork Wed Jul 17 00:30:41 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matthew Ruffell X-Patchwork-Id: 1133019 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=canonical.com Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45pJ8j5wwZz9sMr; Wed, 17 Jul 2019 10:31:01 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1hnXqT-0003Os-90; Wed, 17 Jul 2019 00:30:57 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.86_2) (envelope-from ) id 1hnXqQ-0003No-QH for kernel-team@lists.ubuntu.com; Wed, 17 Jul 2019 00:30:54 +0000 Received: from mail-pf1-f197.google.com ([209.85.210.197]) by youngberry.canonical.com with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.76) (envelope-from ) id 1hnXqQ-0005v2-BH for kernel-team@lists.ubuntu.com; Wed, 17 Jul 2019 00:30:54 +0000 Received: by mail-pf1-f197.google.com with SMTP id r142so13351820pfc.2 for ; Tue, 16 Jul 2019 17:30:54 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=N0Mw9Azpv6wq27ikpLieOBClvfKd0OnJdi9m9G+shUA=; b=gZ6d89rDaLCHHxId+iKnKGnmZ77RVRNmQky3h0mnqrrheQ5xlcbhywnyB4Ip3meumB EBdZR1MF+H0LrOEaEWkUJGZTq5IMJI7El9HN6JQ6lkMTpHL7M6N9X/SKCsPQB9UUbaHN dwGZTEg0INLOgvSRT0bqyUqkYfUvEg8lkEXJUSKruv0ZTx9y0/I1m7rXpDYrOvKRIzKX d0YNuZ/36/ipbLR4kTMFOUgx2cP93bglgdSAzOJ/6ImzKtrRSDL9YrS969UzyS71skyd RbXmtDMxRXJKOFku/gk2QAKQGowJEoe01t3gU4Py8xn7ljIVJPlzALuM9KQ179QkPMSn Rtxw== X-Gm-Message-State: APjAAAVJ5aHPGQjAYX+U4Mq575O9m5QVS/G+b2pvMkoN20Q+yOyFChOl i229mtXv31gtvGt6cbPuwdZ4O2zt6JtdtPisPsC2IGv7ZsnxpmLvv2UE0/CI8rTWXe5ISZIO4TA sVWhEdt9X1QFGPeOgXkzgNtlnjA8Ja3TVoHuDnsmUSQ== X-Received: by 2002:a63:3d0f:: with SMTP id k15mr37526032pga.343.1563323452809; Tue, 16 Jul 2019 17:30:52 -0700 (PDT) X-Google-Smtp-Source: APXvYqxxrbCA5/8NkhXPpwFzAgSMduW75dvBYy/gGhI4bKL0l4Daus+QTEbVTjXtgEI26W2kqgWz3g== X-Received: by 2002:a63:3d0f:: with SMTP id k15mr37526015pga.343.1563323452582; Tue, 16 Jul 2019 17:30:52 -0700 (PDT) Received: from localhost.localdomain (125-238-115-161-fibre.sparkbb.co.nz. [125.238.115.161]) by smtp.gmail.com with ESMTPSA id i74sm23814103pje.16.2019.07.16.17.30.51 for (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Tue, 16 Jul 2019 17:30:52 -0700 (PDT) From: Matthew Ruffell To: kernel-team@lists.ubuntu.com Subject: [SRU][Bionic][PATCH 2/2] netfilter: nf_nat: skip nat clash resolution for same-origin entries Date: Wed, 17 Jul 2019 12:30:41 +1200 Message-Id: <20190717003041.9775-3-matthew.ruffell@canonical.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190717003041.9775-1-matthew.ruffell@canonical.com> References: <20190717003041.9775-1-matthew.ruffell@canonical.com> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Martynas Pumputis BugLink: https://bugs.launchpad.net/bugs/1836816 It is possible that two concurrent packets originating from the same socket of a connection-less protocol (e.g. UDP) can end up having different IP_CT_DIR_REPLY tuples which results in one of the packets being dropped. To illustrate this, consider the following simplified scenario: 1. Packet A and B are sent at the same time from two different threads by same UDP socket. No matching conntrack entry exists yet. Both packets cause allocation of a new conntrack entry. 2. get_unique_tuple gets called for A. No clashing entry found. conntrack entry for A is added to main conntrack table. 3. get_unique_tuple is called for B and will find that the reply tuple of B is already taken by A. It will allocate a new UDP source port for B to resolve the clash. 4. conntrack entry for B cannot be added to main conntrack table because its ORIGINAL direction is clashing with A and the REPLY directions of A and B are not the same anymore due to UDP source port reallocation done in step 3. This patch modifies nf_conntrack_tuple_taken so it doesn't consider colliding reply tuples if the IP_CT_DIR_ORIGINAL tuples are equal. [ Florian: simplify patch to not use .allow_clash setting and always ignore identical flows ] Signed-off-by: Martynas Pumputis Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso (cherry picked from commit 4e35c1cb9460240e983a01745b5f29fe3a4d8e39) Signed-off-by: Matthew Ruffell --- net/netfilter/nf_conntrack_core.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index dd7c06c1c1e5..711364dc2742 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -883,6 +883,22 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple, } if (nf_ct_key_equal(h, tuple, zone, net)) { + /* Tuple is taken already, so caller will need to find + * a new source port to use. + * + * Only exception: + * If the *original tuples* are identical, then both + * conntracks refer to the same flow. + * This is a rare situation, it can occur e.g. when + * more than one UDP packet is sent from same socket + * in different threads. + * + * Let nf_ct_resolve_clash() deal with this later. + */ + if (nf_ct_tuple_equal(&ignored_conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple, + &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple)) + continue; + NF_CT_STAT_INC_ATOMIC(net, found); rcu_read_unlock(); return 1;