diff options
| author | Josef Bacik <josef@toxicpanda.com> | 2026-10-04 00:10:59 +0000 |
|---|---|---|
| committer | Christian Brauner <brauner@kernel.org> | 2026-10-29 15:46:57 +0100 |
| commit | da29ac46d34a19e8cc328ad17cb88713fd4563fa (patch) | |
| tree | e1a1459842133901a8acf439c46982e66cdaf316 /include | |
| parent | 02a336a831f02a18047bacbd49018a237af8a172 (diff) | |
nstree: don't end listns() at an inactive namespace
listns() resumes after the last returned id by looking up the first
namespace with a larger id with lookup_ns_id_after(), or with
lookup_ns_owner_after() when filtering by owner. Both also take a
reference with ns_get_unless_inactive(). If that namespace is inactive,
e.g. a network namespace that is only pinned by a socket or a user
namespace that is only pinned by a file's credentials, or if it is being
torn down, the lookup returns NULL and listns() fails with -ENOENT.
Userspace takes that as the end of the list, so every namespace after
it is silently missed:
ids 10 (active), 11 (inactive), 12 (active)
listns(ns_id = 0, nr = 1) -> 10
listns(ns_id = 10, nr = 1) -> lookup_ns_id_after(10) -> NULL, -ENOENT
12 is never listed
A call without a cursor doesn't have this problem because the loop just
skips the namespaces that legitimize_ns() rejects.
The reference only kept the starting point valid until the RCU walk
began. Look it up under rcu_read_lock() instead, without taking a
reference. The namespace can't be freed before the RCU read-side section
ends, and if it is unlinked in the meantime its ->next still leads back
into the list, which the walk already relies on for every other entry.
The starting namespace then goes through legitimize_ns() like every
other one, and kls->first_ns isn't needed anymore.
Reported-by: shaos <shawnq1@163.com>
Link: https://lore.kernel.org/r/20261020110746.959806-1-shawnq1@163.com
Fixes: 76b6f5dfb3fd ("nstree: add listns()")
Cc: stable@vger.kernel.org
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Diffstat (limited to 'include')
0 files changed, 0 insertions, 0 deletions
