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=1793782970; b=xIH5q66hbJUbl1LLDRFrDG2ADdKdqCQzHa0g5DGo3IBdBmP6VSMSYJF+fVezHwowROaf iL68KJtg3XErw6dnx/TwfCWhtEJ6fgeYFEfWcXABCMueoBQeFRI9sNWAuV9QgTT57mrBg LbvzlmxJSurrXVuLU3DEvooe5e4jheaB5+505bVZhYi9mgXWNmkEAymJTkKlwKKy/3pE5 Qx3aGapJLmU82SOFJL1qcR4m2C8HBTx+iVf9l7oNryXIok/2GaGZEDZR9KoFvrpH7oCzn YbfXH2HhAGj1qxBZIXEJcFEX8z9b23idPz7HRUvtQc0F0bzjl7o2eQQoUhZFwdu7B6A== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1793782970; 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=TaFMJ0UW3LigUoc0s6WNECoAhHhD44ITTyoS2M06BTs=; b=DbEhA8C9mbN1NbID3oasD8shAHwrP3VmvdqiFGL75nnWAKiOjtzQ6H917Pggu9MAQGNI Yux8vC6rxwtFzOEtO7n5KtouiC/kp2+I0QuLg++/h7BzJg+pXw4VBwSx/fnRNUppBG+QY y0glJGPUenqMq80SpvAkjN3O5p81D29tcXvP3cpuPAnoP8RwZaXT97UojhEeorgojlwZ3 r+7g5V29hcLvFCWDiEJi8hNk5VQmNpdwKAWiVT2eg1eFUnmFV5aWhL4rxcr9wqCo/3eo2 mlbG6FY0Re5pVBnqFg6y/N0zvq/hipAct8GbFRvj8KTyqjTK2tapW6BVdIFwDLlmf2Q== 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=SNZowZtm; 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 18A89606D83F; Wed, 4 Nov 2026 09:02:50 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.2 smtp.subspace.kernel.org 18A89606D83F 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=SNZowZtm DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=netfilter.org; s=2025; t=1793782968; bh=TaFMJ0UW3LigUoc0s6WNECoAhHhD44ITTyoS2M06BTs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=SNZowZtmw7PK4J7Fk5ZI/pi2aEqvB7W9RE2SOFE8MpeBcsfITB1hl5lxVLB3rMPjr Q6abWOIEUj0Yhm4yLpkJgHmfkAk3I49E88raPVSaF66cb7+pp2E+Xsl8HMu8JeGUB/ 4O+Cd9YPUUE8DJ1ELHdIX5oEdgJPoKi1bNNvYYyVshZ8AeyhHn0WCrnooEglZowQMv MSp0qvhwW5/vKfkLrJPpzL7QJkoknI5k1k9TTs4KTi8/CIQo3u5yQEXf/K1HBNhILf Pi/KfO+cxgGvxcIRWPjMH9NIcJj8aNHM8/mVwoOZYl5r40L+yLtCOEtwvnXrlhcPKD mYfm7FDSCUrhw== Received: from localhost.localdomain (mail-agni [217.70.190.124]) by mail.netfilter.org (Postfix) with ESMTPSA id 086296008A; Wed, 4 Nov 2026 10:02:47 +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 12/13] netfilter: xt_recent: do not call remove_proc_entry() under recent_lock Date: Wed, 4 Nov 2026 10:02:23 +0100 Message-ID: <20261104090224.750548-13-pablo@netfilter.org> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20261104090224.750548-1-pablo@netfilter.org> References: <20261104090224.750548-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: "Cen Zhang (Microsoft)" recent_proc_net_exit() removes the /proc/net/xt_recent/ entries of a dying network namespace while holding spin_lock_bh(&recent_lock). remove_proc_entry() may sleep: proc_entry_rundown() waits until every task that is still inside the entry's file operations has left. A reader of such an entry is counted in by proc_reg_read() before recent_seq_start() takes recent_lock. So if a read is in flight when the namespace is torn down, cleanup_net() sleeps in atomic context holding the spinlock that the reader is spinning on, and neither side can ever make progress. An unprivileged user can trigger this from a user namespace by adding a rule with the "recent" match and reading its proc file while the namespace is being destroyed. As recent_lock is global, every later attempt to take it spins forever too: the spinning can spread to all CPUs, and network namespace teardown stops system-wide. BUG: sleeping function called from invalid context at kernel/sched/completion.c:116 #3: (recent_lock){+...}-{3:3}, at: recent_net_exit+0x2b/0x140 Workqueue: netns cleanup_net Call Trace: proc_entry_rundown+0x185/0x1b0 remove_proc_entry+0x21a/0x520 recent_net_exit+0x7f/0x140 cleanup_net+0x414/0x8f0 ... rcu: INFO: rcu_preempt self-detected stall on CPU Call Trace: queued_spin_lock_slowpath+0x313/0xc20 recent_seq_start+0x87/0x1b0 seq_read_iter+0x265/0x11e0 proc_reg_read+0x1ab/0x270 Fix by taking recent_mutex instead of recent_lock. According to commit a0e889bb1bdc ("[NETFILTER]: recent match: fix "sleeping function called from invalid context""), recent_mutex is the lock to use here: it protects recent_net->tables and was introduced so that proc entries are created and removed without recent_lock held, because those calls may sleep. hashlimit_proc_net_exit() does the same for xt_hashlimit. Fixes: 665e205c16c1 ("netfilter: xt_recent: fix namespace destroy path") Cc: stable@vger.kernel.org Cc: AutonomousCodeSecurity@microsoft.com Signed-off-by: Cen Zhang (Microsoft) Signed-off-by: Pablo Neira Ayuso --- net/netfilter/xt_recent.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c index 55f1f2d89952..00cccf003cff 100644 --- a/net/netfilter/xt_recent.c +++ b/net/netfilter/xt_recent.c @@ -650,14 +650,15 @@ static void __net_exit recent_proc_net_exit(struct net *net) /* recent_net_exit() is called before recent_mt_destroy(). Make sure * that the parent xt_recent proc entry is empty before trying to - * remove it. + * remove it. Use recent_mutex instead of recent_lock since + * remove_proc_entry() may sleep. */ - spin_lock_bh(&recent_lock); + mutex_lock(&recent_mutex); list_for_each_entry(t, &recent_net->tables, list) remove_proc_entry(t->name, recent_net->xt_recent); recent_net->xt_recent = NULL; - spin_unlock_bh(&recent_lock); + mutex_unlock(&recent_mutex); remove_proc_entry("xt_recent", net->proc_net); } -- 2.47.3