From patchwork Tue Oct 2 01:07:37 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marcelo Henrique Cerri X-Patchwork-Id: 977565 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 42PLcF0mnFz9s3x; Tue, 2 Oct 2018 11:07:56 +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 1g79AC-0008NR-RA; Tue, 02 Oct 2018 01:07:48 +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 1g79AA-0008NJ-V6 for kernel-team@lists.ubuntu.com; Tue, 02 Oct 2018 01:07:46 +0000 Received: from mail-qt1-f199.google.com ([209.85.160.199]) by youngberry.canonical.com with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.76) (envelope-from ) id 1g79AA-0001Vr-LP for kernel-team@lists.ubuntu.com; Tue, 02 Oct 2018 01:07:46 +0000 Received: by mail-qt1-f199.google.com with SMTP id t17-v6so311641qtq.12 for ; Mon, 01 Oct 2018 18:07:46 -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; bh=QljyQe8xOVM+MK+Pg9x6HmIiVklA4dlLHNvUbbjjEmM=; b=aA7OB+IyzGjjpQYIILLPjCLkagLMOupJjtI7PW+BjetU72PtYCpHENQ7/Grub5s+ag wmLF9PqW/9iRp2sLxX4ySQzkvnQXdUNOzQFt1NR79/M/tqqcCjyN6Zmj5houDeaI32DE 07Ya0cu581BFEJIEKFMGUEPgsCWNbb8KwvgXJokWp5pfm57h2zp2bChcXgpOTT8KE+6/ C70M2Y6giOoQJKnjVG5egbHlZ30XqKzP8bWU3gHWo9IfqY5jTVvOWZdQfgHsrJvdWsWf n0zo3pbd1XHUfMLzncHjpJzy115IZidil9yoKNo5Kh8hWFbtx22C5h3fEPRjBL5zp7K9 35Ow== X-Gm-Message-State: ABuFfog0djOPXOIsQoDTeCHhtaGwwby7Ununj1nx/Rni/Xqp1nfcl11E d+lRYTumq3jxiwZlvJNwJ8/W3oxwzVDUEm+3e0RbqPBTu2gWPRJImTJnVKCkZv+einQyoVvupaq WE9iINYlRmA6uEV2HtiQtd/sZ4Bf6pBdeSmLXjJ4+ X-Received: by 2002:a0c:f843:: with SMTP id g3-v6mr92400qvo.221.1538442465305; Mon, 01 Oct 2018 18:07:45 -0700 (PDT) X-Google-Smtp-Source: ACcGV62/++0BI7az1RqjBE2Q0BGrIZOmxz3agy3qg34E5HLZQREWaprjcdBq8ZlPtmqB/AvYIuSsEw== X-Received: by 2002:a0c:f843:: with SMTP id g3-v6mr92390qvo.221.1538442465031; Mon, 01 Oct 2018 18:07:45 -0700 (PDT) Received: from localhost.localdomain ([191.8.86.92]) by smtp.gmail.com with ESMTPSA id t188-v6sm3019644qkc.58.2018.10.01.18.07.42 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 01 Oct 2018 18:07:43 -0700 (PDT) From: Marcelo Henrique Cerri To: kernel-team@lists.ubuntu.com Subject: [bionic/linux-azure, cosmic/linux-azure][PATCH 1/2] UBUNTU: SAUCE: netfilter: nf_conntrack: resolve clash for matching conntracks Date: Mon, 1 Oct 2018 22:07:37 -0300 Message-Id: <20181002010738.20799-2-marcelo.cerri@canonical.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181002010738.20799-1-marcelo.cerri@canonical.com> References: <20181002010738.20799-1-marcelo.cerri@canonical.com> 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: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Martynas Pumputis BugLink: http://bugs.launchpad.net/bugs/1795493 This patch enables the clash resolution for NAT (disabled in "590b52e10d41") if clashing conntracks match (i.e. both tuples are equal) and a protocol allows it. The clash might happen for a connections-less protocol (e.g. UDP) when two threads in parallel writes to the same socket and consequent calls to "get_unique_tuple" return the same tuples (incl. reply tuples). In this case it is safe to perform the resolution, as the losing CT describes the same mangling as the winning CT, so no modifications to the packet are needed, and the result of rules traversal for the loser's packet stays valid. Signed-off-by: Martynas Pumputis Signed-off-by: Pablo Neira Ayuso (cherry picked from commit ed07d9a021df6da53456663a76999189badc432a) [source: git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git] Signed-off-by: Marcelo Henrique Cerri --- net/netfilter/nf_conntrack_core.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 3d5280425027..52a4101e8814 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -502,6 +502,18 @@ nf_ct_key_equal(struct nf_conntrack_tuple_hash *h, net_eq(net, nf_ct_net(ct)); } +static inline bool +nf_ct_match(const struct nf_conn *ct1, const struct nf_conn *ct2) +{ + return nf_ct_tuple_equal(&ct1->tuplehash[IP_CT_DIR_ORIGINAL].tuple, + &ct2->tuplehash[IP_CT_DIR_ORIGINAL].tuple) && + nf_ct_tuple_equal(&ct1->tuplehash[IP_CT_DIR_REPLY].tuple, + &ct2->tuplehash[IP_CT_DIR_REPLY].tuple) && + nf_ct_zone_equal(ct1, nf_ct_zone(ct2), IP_CT_DIR_ORIGINAL) && + nf_ct_zone_equal(ct1, nf_ct_zone(ct2), IP_CT_DIR_REPLY) && + net_eq(nf_ct_net(ct1), nf_ct_net(ct2)); +} + /* caller must hold rcu readlock and none of the nf_conntrack_locks */ static void nf_ct_gc_expired(struct nf_conn *ct) { @@ -695,19 +707,21 @@ static int nf_ct_resolve_clash(struct net *net, struct sk_buff *skb, /* This is the conntrack entry already in hashes that won race. */ struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h); const struct nf_conntrack_l4proto *l4proto; + enum ip_conntrack_info oldinfo; + struct nf_conn *loser_ct = nf_ct_get(skb, &oldinfo); l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct)); if (l4proto->allow_clash && - ((ct->status & IPS_NAT_DONE_MASK) == 0) && !nf_ct_is_dying(ct) && atomic_inc_not_zero(&ct->ct_general.use)) { - enum ip_conntrack_info oldinfo; - struct nf_conn *loser_ct = nf_ct_get(skb, &oldinfo); - - nf_ct_acct_merge(ct, ctinfo, loser_ct); - nf_conntrack_put(&loser_ct->ct_general); - nf_ct_set(skb, ct, oldinfo); - return NF_ACCEPT; + if (((ct->status & IPS_NAT_DONE_MASK) == 0) || + nf_ct_match(ct, loser_ct)) { + nf_ct_acct_merge(ct, ctinfo, loser_ct); + nf_conntrack_put(&loser_ct->ct_general); + nf_ct_set(skb, ct, oldinfo); + return NF_ACCEPT; + } + nf_ct_put(ct); } NF_CT_STAT_INC(net, drop); return NF_DROP;