]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ns: add asserts for active refcount underflow
authorChristian Brauner <brauner@kernel.org>
Sun, 9 Nov 2025 21:11:27 +0000 (22:11 +0100)
committerChristian Brauner <brauner@kernel.org>
Mon, 10 Nov 2025 09:20:54 +0000 (10:20 +0100)
Add a few more assert to detect active reference count underflows.

Link: https://patch.msgid.link/20251109-namespace-6-19-fixes-v1-6-ae8a4ad5a3b3@kernel.org
Signed-off-by: Christian Brauner <brauner@kernel.org>
include/linux/ns_common.h
kernel/nscommon.c

index 3aaba2ca31d7b22d1ce07ccc389a19ebeac15465..66ea09b4837741878a1d9453ca55559ad61ca69f 100644 (file)
@@ -294,7 +294,6 @@ void __ns_ref_active_put(struct ns_common *ns);
 
 static __always_inline struct ns_common *__must_check ns_get_unless_inactive(struct ns_common *ns)
 {
-       VFS_WARN_ON_ONCE(__ns_ref_active_read(ns) && !__ns_ref_read(ns));
        if (!__ns_ref_active_read(ns)) {
                VFS_WARN_ON_ONCE(is_ns_init_id(ns));
                return NULL;
index bfd2d6805776a2f571b0018db95834086fe90a9a..c910b979e4336c3a017eb21ddd1c21a2a17dc57e 100644 (file)
@@ -170,8 +170,10 @@ void __ns_ref_active_put(struct ns_common *ns)
        if (is_ns_init_id(ns))
                return;
 
-       if (!atomic_dec_and_test(&ns->__ns_ref_active))
+       if (!atomic_dec_and_test(&ns->__ns_ref_active)) {
+               VFS_WARN_ON_ONCE(__ns_ref_active_read(ns) < 0);
                return;
+       }
 
        VFS_WARN_ON_ONCE(is_ns_init_id(ns));
        VFS_WARN_ON_ONCE(!__ns_ref_read(ns));
@@ -181,8 +183,10 @@ void __ns_ref_active_put(struct ns_common *ns)
                if (!ns)
                        return;
                VFS_WARN_ON_ONCE(is_ns_init_id(ns));
-               if (!atomic_dec_and_test(&ns->__ns_ref_active))
+               if (!atomic_dec_and_test(&ns->__ns_ref_active)) {
+                       VFS_WARN_ON_ONCE(__ns_ref_active_read(ns) < 0);
                        return;
+               }
        }
 }
 
@@ -280,12 +284,16 @@ void __ns_ref_active_put(struct ns_common *ns)
  */
 void __ns_ref_active_get(struct ns_common *ns)
 {
+       int prev;
+
        /* Initial namespaces are always active. */
        if (is_ns_init_id(ns))
                return;
 
        /* If we didn't resurrect the namespace we're done. */
-       if (atomic_fetch_add(1, &ns->__ns_ref_active))
+       prev = atomic_fetch_add(1, &ns->__ns_ref_active);
+       VFS_WARN_ON_ONCE(prev < 0);
+       if (likely(prev))
                return;
 
        /*
@@ -298,7 +306,9 @@ void __ns_ref_active_get(struct ns_common *ns)
                        return;
 
                VFS_WARN_ON_ONCE(is_ns_init_id(ns));
-               if (atomic_fetch_add(1, &ns->__ns_ref_active))
+               prev = atomic_fetch_add(1, &ns->__ns_ref_active);
+               VFS_WARN_ON_ONCE(prev < 0);
+               if (likely(prev))
                        return;
        }
 }