[PATCH v2] nstree: check listing permission before taking a namespace reference

Norbert Szetei posted 1 patch 2 weeks, 4 days ago
kernel/nstree.c | 10 ++--------
1 file changed, 2 insertions(+), 8 deletions(-)
[PATCH v2] nstree: check listing permission before taking a namespace reference
Posted by Norbert Szetei 2 weeks, 4 days ago
legitimize_ns() takes a reference on the candidate namespace before
may_list_ns() has decided whether the caller may see it. The
__free(ns_put) cleanup on the denied path can drop the last reference to a
mount namespace while we still hold the rcu read lock, and put_mnt_ns()
may sleep there. This is the same problem commit 2ec2aff3c8e2 ("ns: make
sure reference are dropped outside of rcu lock") fixed for the put_user()
path. Neither ns_requested() nor may_list_ns() needs a reference, both
only look at the namespace type and at the caller's own namespaces, so do
the checks first and take the reference last.

Splat:

  Voluntary context switch within RCU read-side critical section!
  WARNING: kernel/rcu/tree_plugin.h:332 at rcu_note_context_switch+0x238/0x2a0, CPU#5: a/3442
  CPU: 5 UID: 1000 PID: 3442 Comm: a Not tainted 7.0.0-30-generic #30-Ubuntu PREEMPT(lazy)
  RIP: 0010:rcu_note_context_switch+0x238/0x2a0
  Call Trace:
   <TASK>
   __schedule+0xcf/0x650
   schedule+0x27/0x90
   schedule_preempt_disabled+0x15/0x30
   __mutex_lock.constprop.0+0x550/0xaf0
   __mutex_lock_slowpath+0x13/0x20
   mutex_lock+0x3b/0x50
   exp_funnel_lock+0xb2/0x260
   synchronize_rcu_expedited+0xe7/0x220
   namespace_unlock+0x26a/0x320
   put_mnt_ns+0xd3/0x120
   mntns_put+0xe/0x20
   do_listns+0x13e/0x560
   __do_sys_listns+0x126/0x2d0
   __x64_sys_listns+0x20/0x30
   x64_sys_call+0x2366/0x2390
   do_syscall_64+0x105/0x5a0
   entry_SYSCALL_64_after_hwframe+0x76/0x7e
   </TASK>

Fixes: 76b6f5dfb3fd ("nstree: add listns()")
Signed-off-by: Norbert Szetei <norbert@doyensec.com>
Reviewed-by: Bradley Morgan <brads@mainlining.org>
---
v2: include the splat in the description, no code changes.
v1: https://lore.kernel.org/all/34C54FF6-AA8F-4124-9B40-C68EADB26D99@doyensec.com/

 kernel/nstree.c | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/kernel/nstree.c b/kernel/nstree.c
index 6d12e5900ac0..831f279d174a 100644
--- a/kernel/nstree.c
+++ b/kernel/nstree.c
@@ -533,19 +533,13 @@ DEFINE_FREE(ns_put, struct ns_common *, if (!IS_ERR_OR_NULL(_T)) ns_put(_T))
 static inline struct ns_common *__must_check legitimize_ns(const struct klistns *kls,
 							   struct ns_common *candidate)
 {
-	struct ns_common *ns __free(ns_put) = NULL;
-
 	if (!ns_requested(kls, candidate))
 		return NULL;
 
-	ns = ns_get_unless_inactive(candidate);
-	if (!ns)
-		return NULL;
-
-	if (!may_list_ns(kls, ns))
+	if (!may_list_ns(kls, candidate))
 		return NULL;
 
-	return no_free_ptr(ns);
+	return ns_get_unless_inactive(candidate);
 }
 
 static ssize_t do_listns_userns(struct klistns *kls)
-- 
2.55.0
Re: [PATCH v2] nstree: check listing permission before taking a namespace reference
Posted by Christian Brauner 2 weeks, 2 days ago
On Mon, 07 Sep 2026 16:22:17 +0200, Norbert Szetei wrote:
> legitimize_ns() takes a reference on the candidate namespace before
> may_list_ns() has decided whether the caller may see it. The
> __free(ns_put) cleanup on the denied path can drop the last reference to a
> mount namespace while we still hold the rcu read lock, and put_mnt_ns()
> may sleep there. This is the same problem commit 2ec2aff3c8e2 ("ns: make
> sure reference are dropped outside of rcu lock") fixed for the put_user()
> path. Neither ns_requested() nor may_list_ns() needs a reference, both
> only look at the namespace type and at the caller's own namespaces, so do
> the checks first and take the reference last.
> 
> [...]

Applied to the vfs.fixes branch of the vfs/vfs.git tree.
Patches in the vfs.fixes branch should appear in linux-next soon.

Please report any outstanding bugs that were missed during review in a
new review to the original patch series allowing us to drop it.

It's encouraged to provide Acked-bys and Reviewed-bys even though the
patch has now been applied. If possible patch trailers will be updated.

Note that commit hashes shown below are subject to change due to rebase,
trailer updates or similar. If in doubt, please check the listed branch.

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git
branch: vfs.fixes

[1/1] nstree: check listing permission before taking a namespace reference
      https://git.kernel.org/vfs/vfs/c/ecfee3a7c9ea