lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<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

Powered by Openwall GNU/*/Linux Powered by OpenVZ