From patchwork Mon Jul 2 14:52:14 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martynas Pumputis X-Patchwork-Id: 937963 X-Patchwork-Delegate: pablo@netfilter.org 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=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=weave.works Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=weave.works header.i=@weave.works header.b="rg9bqHnh"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 41K9Pv4xvkz9s4Z for ; Tue, 3 Jul 2018 00:59:15 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752552AbeGBO6Y (ORCPT ); Mon, 2 Jul 2018 10:58:24 -0400 Received: from mail-wm0-f68.google.com ([74.125.82.68]:51866 "EHLO mail-wm0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752237AbeGBO6V (ORCPT ); Mon, 2 Jul 2018 10:58:21 -0400 Received: by mail-wm0-f68.google.com with SMTP id s12-v6so397765wmc.1 for ; Mon, 02 Jul 2018 07:58:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=weave.works; s=google; h=from:to:cc:subject:date:message-id; bh=gU+2nX2LVvn1RRCF5CRcX2BZBEe5OYaMQgYyBKOUL8w=; b=rg9bqHnhO0UhE8XpxLSZiNtN0XRVCi/OTMleNCTb4MSayxu3+eKrCetf3iK7afdIJp MEieBUdzQi8EpOHvyKZPDZjPtlVVv4DXB6R0tE9M8N6PXJ19zEw5LbUuMtn9anmAsxcQ VkZWXvjihdIsncaTdqNHjed2OLIfQHi/fghiw= 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; bh=gU+2nX2LVvn1RRCF5CRcX2BZBEe5OYaMQgYyBKOUL8w=; b=K3HYDPDjhJ9OWHUUavRek4bFgegPX177HnMh3k6XkKmdsKVrCvyzqiOlc24jvSsf4r p8vEthdx9dvbfuRO6quXKyZRbz4iecZP02VsjfW77PTkrzLPvDfyOKxTczmvN68MheNT xM3/Qmo/X042jfPyGcZvurtInC8IsSxiOo9epDqBV6wPuwMS0qNOkW8sJiYFI6q1pv1k Rx4EvtRflf0K6DllR2vyhEJEiDERtT5GRTnXRthVZB6BZnvpcwsvHaeKIQJ8OHTfpRLI VVOqpv/ecaEothKYMIAp2CLZ6UNu2jCJ8U2jqcvgmifH7YR8fb2nx4oG2fbPHrjXQXkN IjEA== X-Gm-Message-State: APt69E34tjIWQajrfm4kjvPMXnaCFwrAgBYJH4mC7Tmk174ttu6DEzTb zRWIDv/TIDox1m6nJJEEbrIvgA== X-Google-Smtp-Source: AAOMgpd9NVEDyytLe5JGXAwW8+G4PA7euUl2QGIVBSsZXn1xKGwpuAOxvrLdTYXMSiaOsiiaGcvrLQ== X-Received: by 2002:a1c:8010:: with SMTP id b16-v6mr8946708wmd.9.1530543500154; Mon, 02 Jul 2018 07:58:20 -0700 (PDT) Received: from localhost.localdomain (ner74-h01-176-138-79-102.dsl.sta.abo.bbox.fr. [176.138.79.102]) by smtp.googlemail.com with ESMTPSA id h102-v6sm2299156wrh.60.2018.07.02.07.58.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 02 Jul 2018 07:58:18 -0700 (PDT) From: Martynas Pumputis To: pablo@netfilter.org Cc: kadlec@blackhole.kfki.hu, fw@strlen.de, netfilter-devel@vger.kernel.org, Martynas Pumputis Subject: [PATCH v2] netfilter: nf_conntrack: resolve clash for matching conntracks Date: Mon, 2 Jul 2018 16:52:14 +0200 Message-Id: <20180702145214.14925-1-martynas@weave.works> X-Mailer: git-send-email 2.18.0 Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org 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 --- net/netfilter/nf_conntrack_core.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 3465da2a98bd..cc5ef8c9d0da 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) { @@ -696,18 +708,21 @@ static int nf_ct_resolve_clash(struct net *net, struct sk_buff *skb, 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;