nf_dup_ipv4() and nf_dup_ipv6() send a cloned packet through ip_local_out() or ip6_local_out(), so the clone can traverse netfilter hooks again. A network namespace owned by a non-initial user namespace can combine NFQUEUE with TEE or nftables dup and retain the clone until a later verdict resumes it. The transient in_nf_duplicate task guard has already been cleared by then, so the resumed clone can be duplicated again and generate packets without bound. There is no sensible use case for packet duplication in a user namespace. Skip IPv4 and IPv6 duplication when the network namespace is not owned by the initial user namespace. Keep the existing TEE/dup behavior in the initial user namespace. Fixes: cd58bcd9787e ("netfilter: xt_TEE: have cloned packet travel through Xtables too") Cc: stable@vger.kernel.org Reported-by: Vega Assisted-by: LLM Suggested-by: Florian Westphal Signed-off-by: Zihan Xi --- changes in v2: - drop the persistent struct sk_buff::nf_duplicated field and nf_copy() change from v1 - disable IPv4/IPv6 duplication in network namespaces owned by a non-initial user namespace, as preferred on review - v1 Link: https://lore.kernel.org/all/cover.1787903722.git.zihanx@nebusec.ai/ net/ipv4/netfilter/nf_dup_ipv4.c | 3 +++ net/ipv6/netfilter/nf_dup_ipv6.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/net/ipv4/netfilter/nf_dup_ipv4.c b/net/ipv4/netfilter/nf_dup_ipv4.c index 9a773502f10a..c33dae248c47 100644 --- a/net/ipv4/netfilter/nf_dup_ipv4.c +++ b/net/ipv4/netfilter/nf_dup_ipv4.c @@ -53,6 +53,9 @@ void nf_dup_ipv4(struct net *net, struct sk_buff *skb, unsigned int hooknum, { struct iphdr *iph; + if (net->user_ns != &init_user_ns) + return; + local_bh_disable(); if (current->in_nf_duplicate) goto out; diff --git a/net/ipv6/netfilter/nf_dup_ipv6.c b/net/ipv6/netfilter/nf_dup_ipv6.c index 6da3102b7c1b..a5f6f074a7e9 100644 --- a/net/ipv6/netfilter/nf_dup_ipv6.c +++ b/net/ipv6/netfilter/nf_dup_ipv6.c @@ -47,6 +47,9 @@ static bool nf_dup_ipv6_route(struct net *net, struct sk_buff *skb, void nf_dup_ipv6(struct net *net, struct sk_buff *skb, unsigned int hooknum, const struct in6_addr *gw, int oif) { + if (net->user_ns != &init_user_ns) + return; + local_bh_disable(); if (current->in_nf_duplicate) goto out; -- 2.43.0