From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=217.70.190.124 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1793882747; b=lzItkeAklfRuTon6qY4g69ZfWu7AFma+4hkWWsfQfe1iHLvD4axRON1jfHq9E09A0AHF c1Zzrn0KT0BSXkTiiOLIMC4zHe9aFv1CA7Uykhj0IjkeuAaJUs5TN/pBz8BsPF7IflABN iSZd0FUNy7WhieXeZ8ZeyUIbWXHymYpXSJLyGt7Dpw7Z37F+3wc8KsDsjyGqAZmKwA3k+ Co6mGc7b25TqiV49hm+fe4PvHvGlTwevLzEbhkIVqfYo0+LthJSg+d/hFcWlbSwz6qhxa FpWJbqocFAsPTmcBQwYxu2XivFJ2q8ZKwtG5vqW41+8BSgJuzqKEnp8crZI36HZiGOA== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1793882747; h=DMARC-Filter:DKIM-Signature:Received:From:To:Cc:Subject:Date: Message-ID:X-Mailer:In-Reply-To:References:MIME-Version: Content-Transfer-Encoding:X-Spam-Status:X-Spam-Checker-Version; bh=kuc0tSs2t8YhL7Z9z30YhIe5qV0tfMkKwJx3EJPkeDo=; b=BJjzneHeq6e54mKFskgZEKRLXPlJLlFZAQ39ZDpDeKa4rHPUJLTAVtSmeKe6T/S1a4Tc OW6eQ8guRWonmgsPhHyli8mJhpCsC68K+091jxZwty5s9Dv9TUd3VcLim1HTo7N1W8Sdk VL2JovhYtqCZY8Qc2DLvAtoKUGgXyKng/UnIhDrsoQ7d4m5/Ia3InctRWuHU70vWtr+O1 WMFPN+aVLzcCRT1cJMxgjSj5DNc8M/pFwLti9W997vRijJuNt87W9WUpyNYpQK9HpN5Ea GBeFZiBJ0+XueRs8x8WvPdc39599+ahStbOq0ZDSEh8Mce24U66/tWhVQ8+8Wv0GVZw== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none header.from=netfilter.org; spf=pass smtp.mailfrom=netfilter.org; dkim=pass header.d=netfilter.org header.i=@netfilter.org header.a=rsa-sha256 header.s=2025 header.b=EAyj1oZc; arc=none smtp.remote-ip=217.70.190.124 Received: from mail.netfilter.org (mail.netfilter.org [217.70.190.124]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 43AAE606A330; Thu, 5 Nov 2026 12:45:47 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.2 smtp.subspace.kernel.org 43AAE606A330 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=netfilter.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=netfilter.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key, unprotected) header.d=netfilter.org header.i=@netfilter.org header.a=rsa-sha256 header.s=2025 header.b=EAyj1oZc DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=netfilter.org; s=2025; t=1793882745; bh=kuc0tSs2t8YhL7Z9z30YhIe5qV0tfMkKwJx3EJPkeDo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=EAyj1oZcQNumuik1HHZTXFgqZfDDqAMHaDEFSCSMXIFwZsFUZGRCKZMbX/fFnqScT xxjovaAiK46OEE90079+2OChwGdg0vl7ZRJ34HQk/7g5PG67CHDJcKviApmHhxfrAG 7UIUnLUsfg1742Y7G/7NhzwL+/zs4T88u0JhQQSPm3XLr0RHKZ9UlTL96oIcNfA3az 6r0KN5vixstsGB60tsnnYyj66BPBoDm2HVf/NzefMNj252bvp9H5Em6TmIdwtyOqQ9 kenCxZg3+bVtsvLZt3endNzIpVKKfdtKGzgKL7+ktRg2A7wYDw2nCvtkmKFAlfWRen cDSLnqy0lIE0w== Received: from localhost.localdomain (mail-agni [217.70.190.124]) by mail.netfilter.org (Postfix) with ESMTPSA id 3E01460097; Thu, 5 Nov 2026 13:45:45 +0100 (CET) From: Pablo Neira Ayuso To: netfilter-devel@vger.kernel.org Cc: davem@davemloft.net, netdev@vger.kernel.org, kuba@kernel.org, pabeni@redhat.com, edumazet@kernel.org, horms@kernel.org, fw@strlen.de, ja@ssi.bg Subject: [PATCH net 04/12] netfilter: nf_dup: preserve guard across NFQUEUE reinjection Date: Thu, 5 Nov 2026 13:45:28 +0100 Message-ID: <20261105124536.1009301-5-pablo@netfilter.org> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20261105124536.1009301-1-pablo@netfilter.org> References: <20261105124536.1009301-1-pablo@netfilter.org> X-Mailing-List: netdev@vger.kernel.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Zihan Xi NFQUEUE can suspend traversal of a duplicated packet while the task-local duplication guard is set. The output call then returns and clears the guard before a later verdict resumes hook traversal. Save the guard in the queue entry and restore it while reinjection continues hook traversal. Preserve and restore the verdict task's prior state, including nested synchronous reinjection. Fixes: cd58bcd9787e ("netfilter: xt_TEE: have cloned packet travel through Xtables too") Cc: stable@vger.kernel.org Reported-by: Vega Assisted-by: LLM Co-developed-by: Luxing Yin Signed-off-by: Luxing Yin Signed-off-by: Zihan Xi Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_queue.h | 1 + net/netfilter/nf_queue.c | 1 + net/netfilter/nfnetlink_queue.c | 17 ++++++++++++++--- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h index 86021c55ba3c..4a8cefd8398d 100644 --- a/include/net/netfilter/nf_queue.h +++ b/include/net/netfilter/nf_queue.h @@ -23,6 +23,7 @@ struct nf_queue_entry { struct net_device *physout; #endif struct nf_hook_state state; + bool in_nf_duplicate; bool nf_ct_is_unconfirmed; u16 size; /* sizeof(entry) + saved route keys */ diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index 166d05e994ac..bd603e3a99a5 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c @@ -219,6 +219,7 @@ static int __nf_queue(struct sk_buff *skb, const struct nf_hook_state *state, *entry = (struct nf_queue_entry) { .skb = skb, .skb_dev = skb->dev, + .in_nf_duplicate = current->in_nf_duplicate, .state = *state, .hook_index = index, .size = sizeof(*entry) + route_key_size, diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 90d887546f7d..a8aa7ad832c3 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -365,21 +366,30 @@ static void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict) const struct nf_hook_entry *hook_entry; const struct nf_hook_entries *hooks; struct sk_buff *skb = entry->skb; + bool old_in_nf_duplicate; const struct net *net; unsigned int i; int err; u8 pf; + DEBUG_NET_WARN_ONCE(current->in_nf_duplicate && + !entry->in_nf_duplicate, + "%s called with unexpected duplication guard", + __func__); + local_bh_disable(); + old_in_nf_duplicate = current->in_nf_duplicate; + net = entry->state.net; pf = entry->state.pf; + current->in_nf_duplicate = entry->in_nf_duplicate; hooks = nf_hook_entries_head(net, pf, entry->state.hook); i = entry->hook_index; if (!hooks || i >= hooks->num_hook_entries) { kfree_skb_reason(skb, SKB_DROP_REASON_NETFILTER_DROP); nf_queue_entry_free(entry); - return; + goto out; } hook_entry = &hooks->hooks[i]; @@ -402,9 +412,7 @@ static void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict) switch (verdict & NF_VERDICT_MASK) { case NF_ACCEPT: case NF_STOP: - local_bh_disable(); entry->state.okfn(entry->state.net, entry->state.sk, skb); - local_bh_enable(); break; case NF_QUEUE: err = nf_queue(skb, &entry->state, i, verdict); @@ -418,6 +426,9 @@ static void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict) } nf_queue_entry_free(entry); +out: + current->in_nf_duplicate = old_in_nf_duplicate; + local_bh_enable(); } /* return true if the entry has an unconfirmed conntrack attached that isn't owned by us -- 2.47.3