FAILED: patch "[PATCH] unshare: don't drop active namespace references that were" failed to apply to 5.15-stable tree
Subsystems (4)
[email protected]
maintainerThe patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.15.y
git checkout FETCH_HEAD
git cherry-pick -x 0b6f31a3c0b16066f812e94b52a704174a6f23cd
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026101253-shape-overstep-3470@gregkh' --subject-prefix 'PATCH 5.15.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 0b6f31a3c0b16066f812e94b52a704174a6f23cd Mon Sep 17 00:00:00 2001
From: Christian Brauner <[email protected]>
Date: Wed, 30 Sep 2026 15:32:08 +0200
Subject: [PATCH] unshare: don't drop active namespace references that were
never taken
Active references on the namespaces of an nsproxy are taken when the nsproxy is installed into a task in switch_task_namespaces() and copy_namespaces() and dropped again by put_nsproxy() through deactivate_nsproxy().
But ksys_unshare() calls put_nsproxy() on an nsproxy that was never installed when set_cred_ucounts() fails. The new namespaces of that nsproxy go from zero to minus one and the namespaces shared with the caller lose a reference that belongs to the nsproxy the caller keeps using:
WARNING: kernel/nscommon.c:171 at __ns_ref_active_put+0x1cd/0x230 nsproxy_ns_active_put deactivate_nsproxy ksys_unshare
Afterwards the namespaces the caller lives in aren't listed by listns() anymore. set_cred_ucounts() only fails when alloc_ucounts() can't allocate and it only allocates when the real uid of the caller differs from its effective uid.
Commit cefd55bd2159 ("nsproxy: fix free_nsproxy() and simplify create_new_namespaces()") separated the two cases on purpose. nsproxy_free() frees an nsproxy that was prepared but never installed and that's what a failed setns() uses in put_nsset(). Export it and use it for a failed unshare() as well.
include/linux/nsproxy.h +1 -0
@@ -100,6 +100,7 @@ void exit_cred_namespaces(struct task_struct *tsk);void switch_task_namespaces (struct task_struct *tsk,struct nsproxy *new);int exec_task_namespaces (void );void deactivate_nsproxy (struct nsproxy *ns); +void nsproxy_free (struct nsproxy *ns);int unshare_nsproxy_namespaces (unsigned long ,struct nsproxy **,struct cred *,struct fs_struct *);int __init nsproxy_cache_init (void );
kernel/fork.c +2 -1
@@ -3338,8 +3338,9 @@ int ksys_unshare(unsigned long unshare_flags)perf_event_namespaces (current); bad_unshare_cleanup_nsproxy: +/* never installed, so no active references to drop */ if (new_nsproxy) -put_nsproxy (new_nsproxy); +nsproxy_free (new_nsproxy); bad_unshare_cleanup_cred:if (new_cred)put_cred (new_cred);
kernel/nsproxy.c +1 -1
@@ -61,7 +61,7 @@ static inline struct nsproxy *create_nsproxy(void)return nsproxy; } -static inline void nsproxy_free (struct nsproxy *ns) +void nsproxy_free (struct nsproxy *ns) {put_mnt_ns (ns->mnt_ns);put_uts_ns (ns->uts_ns);