[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20251109092333.844185-1-kartikey406@gmail.com>
Date: Sun, 9 Nov 2025 14:53:33 +0530
From: Deepanshu Kartikey <kartikey406@...il.com>
To: viro@...iv.linux.org.uk,
brauner@...nel.org,
jack@...e.cz
Cc: linux-fsdevel@...r.kernel.org,
linux-kernel@...r.kernel.org,
Deepanshu Kartikey <kartikey406@...il.com>,
syzbot+0b2e79f91ff6579bfa5b@...kaller.appspotmail.com
Subject: [PATCH v2] fs/nsfs: skip active ref counting for initial namespaces
Initial namespaces are statically allocated and exist for the entire
lifetime of the system. They should not participate in active
reference counting.
The recent introduction of active reference counting in commit
3a18f809184b ("ns: add active reference count") added functions that
unconditionally take/drop active references on all namespaces,
including initial ones.
This causes a WARN_ON_ONCE() to trigger when a namespace file for an
initial namespace is evicted:
WARNING: ./include/linux/ns_common.h:314 at nsfs_evict+0x18e/0x200
The same pattern exists in nsproxy_ns_active_get() and
nsproxy_ns_active_put() which could trigger similar warnings when
operating on initial namespaces.
Fix by checking is_initial_namespace() before taking or dropping
active references in:
- nsfs_evict()
- nsproxy_ns_active_get()
- nsproxy_ns_active_put()
Reported-by: syzbot+0b2e79f91ff6579bfa5b@...kaller.appspotmail.com
Link: https://syzkaller.appspot.com/bug?extid=0b2e79f91ff6579bfa5b
Fixes: 3a18f809184b ("ns: add active reference count")
Signed-off-by: Deepanshu Kartikey <kartikey406@...il.com>
---
fs/nsfs.c | 53 +++++++++++++++++++++++++++++++++++------------------
1 file changed, 35 insertions(+), 18 deletions(-)
diff --git a/fs/nsfs.c b/fs/nsfs.c
index ba6c8975c82e..eb14f29dc8d3 100644
--- a/fs/nsfs.c
+++ b/fs/nsfs.c
@@ -19,6 +19,7 @@
#include <linux/exportfs.h>
#include <linux/nstree.h>
#include <net/net_namespace.h>
+#include <linux/ns_common.h>
#include "mount.h"
#include "internal.h"
@@ -58,8 +59,8 @@ const struct dentry_operations ns_dentry_operations = {
static void nsfs_evict(struct inode *inode)
{
struct ns_common *ns = inode->i_private;
-
- __ns_ref_active_put(ns);
+ if (!is_initial_namespace(ns))
+ __ns_ref_active_put(ns);
clear_inode(inode);
ns->ops->put(ns);
}
@@ -686,24 +687,40 @@ void __init nsfs_init(void)
void nsproxy_ns_active_get(struct nsproxy *ns)
{
- ns_ref_active_get(ns->mnt_ns);
- ns_ref_active_get(ns->uts_ns);
- ns_ref_active_get(ns->ipc_ns);
- ns_ref_active_get(ns->pid_ns_for_children);
- ns_ref_active_get(ns->cgroup_ns);
- ns_ref_active_get(ns->net_ns);
- ns_ref_active_get(ns->time_ns);
- ns_ref_active_get(ns->time_ns_for_children);
+ if (ns->mnt_ns && !is_initial_namespace(&ns->mnt_ns->ns))
+ ns_ref_active_get(ns->mnt_ns);
+ if (ns->uts_ns && !is_initial_namespace(&ns->uts_ns->ns))
+ ns_ref_active_get(ns->uts_ns);
+ if (ns->ipc_ns && !is_initial_namespace(&ns->ipc_ns->ns))
+ ns_ref_active_get(ns->ipc_ns);
+ if (ns->pid_ns_for_children && !is_initial_namespace(&ns->pid_ns_for_children->ns))
+ ns_ref_active_get(ns->pid_ns_for_children);
+ if (ns->cgroup_ns && !is_initial_namespace(&ns->cgroup_ns->ns))
+ ns_ref_active_get(ns->cgroup_ns);
+ if (ns->net_ns && !is_initial_namespace(&ns->net_ns->ns))
+ ns_ref_active_get(ns->net_ns);
+ if (ns->time_ns && !is_initial_namespace(&ns->time_ns->ns))
+ ns_ref_active_get(ns->time_ns);
+ if (ns->time_ns_for_children && !is_initial_namespace(&ns->time_ns_for_children->ns))
+ ns_ref_active_get(ns->time_ns_for_children);
}
void nsproxy_ns_active_put(struct nsproxy *ns)
{
- ns_ref_active_put(ns->mnt_ns);
- ns_ref_active_put(ns->uts_ns);
- ns_ref_active_put(ns->ipc_ns);
- ns_ref_active_put(ns->pid_ns_for_children);
- ns_ref_active_put(ns->cgroup_ns);
- ns_ref_active_put(ns->net_ns);
- ns_ref_active_put(ns->time_ns);
- ns_ref_active_put(ns->time_ns_for_children);
+ if (ns->mnt_ns && !is_initial_namespace(&ns->mnt_ns->ns))
+ ns_ref_active_put(ns->mnt_ns);
+ if (ns->uts_ns && !is_initial_namespace(&ns->uts_ns->ns))
+ ns_ref_active_put(ns->uts_ns);
+ if (ns->ipc_ns && !is_initial_namespace(&ns->ipc_ns->ns))
+ ns_ref_active_put(ns->ipc_ns);
+ if (ns->pid_ns_for_children && !is_initial_namespace(&ns->pid_ns_for_children->ns))
+ ns_ref_active_put(ns->pid_ns_for_children);
+ if (ns->cgroup_ns && !is_initial_namespace(&ns->cgroup_ns->ns))
+ ns_ref_active_put(ns->cgroup_ns);
+ if (ns->net_ns && !is_initial_namespace(&ns->net_ns->ns))
+ ns_ref_active_put(ns->net_ns);
+ if (ns->time_ns && !is_initial_namespace(&ns->time_ns->ns))
+ ns_ref_active_put(ns->time_ns);
+ if (ns->time_ns_for_children && !is_initial_namespace(&ns->time_ns_for_children->ns))
+ ns_ref_active_put(ns->time_ns_for_children);
}
--
2.43.0
Powered by blists - more mailing lists