From: Christian Brauner <brauner@kernel.org>
To: syzbot <syzbot+0b2e79f91ff6579bfa5b@syzkaller.appspotmail.com>
Cc: Christian Brauner <brauner@kernel.org>,
akpm@linux-foundation.org, bpf@vger.kernel.org,
bsegall@google.com, david@redhat.com, dietmar.eggemann@arm.com,
jack@suse.cz, jsavitz@redhat.com, juri.lelli@redhat.com,
kartikey406@gmail.com, kees@kernel.org, liam.howlett@oracle.com,
linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-mm@kvack.org, linux-security-module@vger.kernel.org,
lorenzo.stoakes@oracle.com, mgorman@suse.de, mhocko@suse.com,
mingo@redhat.com, mjguzik@gmail.com, oleg@redhat.com,
paul@paul-moore.com, peterz@infradead.org, rostedt@goodmis.org,
rppt@kernel.org, sergeh@kernel.org, surenb@google.com,
syzkaller-bugs@googlegroups.com, vbabka@suse.cz,
vincent.guittot@linaro.org, viro@zeniv.linux.org.uk,
vschneid@redhat.com,
syzbot+0a8655a80e189278487e@syzkaller.appspotmail.com
Subject: [PATCH] nsproxy: fix free_nsproxy() and simplify create_new_namespaces()
Date: Tue, 11 Nov 2025 22:29:44 +0100 [thread overview]
Message-ID: <20251111-sakralbau-guthaben-7dcc277d337f@brauner> (raw)
In-Reply-To: <691360cc.a70a0220.22f260.013e.GAE@google.com>
Make it possible to handle NULL being passed to the reference count
helpers instead of forcing the caller to handle this. Afterwards we can
nicely allow a cleanup guard to handle nsproxy freeing.
Active reference count handling is not done in nsproxy_free() but rather
in free_nsproxy() as nsproxy_free() is also called from setns() failure
paths where a new nsproxy has been prepared but has not been marked as
active via switch_task_namespaces().
Fixes: 3c9820d5c64a ("ns: add active reference count")
Reported-by: syzbot+0b2e79f91ff6579bfa5b@syzkaller.appspotmail.com
Reported-by: syzbot+0a8655a80e189278487e@syzkaller.appspotmail.com
Link: https://lore.kernel.org/690bfb9e.050a0220.2e3c35.0013.GAE@google.com
Signed-off-by: Christian Brauner <brauner@kernel.org>
---
include/linux/ns_common.h | 11 ++--
kernel/nsproxy.c | 107 +++++++++++++++-----------------------
2 files changed, 48 insertions(+), 70 deletions(-)
diff --git a/include/linux/ns_common.h b/include/linux/ns_common.h
index 136f6a322e53..825f5865bfc5 100644
--- a/include/linux/ns_common.h
+++ b/include/linux/ns_common.h
@@ -114,11 +114,14 @@ static __always_inline __must_check bool __ns_ref_dec_and_lock(struct ns_common
}
#define ns_ref_read(__ns) __ns_ref_read(to_ns_common((__ns)))
-#define ns_ref_inc(__ns) __ns_ref_inc(to_ns_common((__ns)))
-#define ns_ref_get(__ns) __ns_ref_get(to_ns_common((__ns)))
-#define ns_ref_put(__ns) __ns_ref_put(to_ns_common((__ns)))
+#define ns_ref_inc(__ns) \
+ do { if (__ns) __ns_ref_inc(to_ns_common((__ns))); } while (0)
+#define ns_ref_get(__ns) \
+ ((__ns) ? __ns_ref_get(to_ns_common((__ns))) : false)
+#define ns_ref_put(__ns) \
+ ((__ns) ? __ns_ref_put(to_ns_common((__ns))) : false)
#define ns_ref_put_and_lock(__ns, __ns_lock) \
- __ns_ref_dec_and_lock(to_ns_common((__ns)), __ns_lock)
+ ((__ns) ? __ns_ref_dec_and_lock(to_ns_common((__ns)), __ns_lock) : false)
#define ns_ref_active_read(__ns) \
((__ns) ? __ns_ref_active_read(to_ns_common(__ns)) : 0)
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index 94c2cfe0afa1..2c94452dc793 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -60,6 +60,27 @@ static inline struct nsproxy *create_nsproxy(void)
return nsproxy;
}
+static inline void nsproxy_free(struct nsproxy *ns)
+{
+ put_mnt_ns(ns->mnt_ns);
+ put_uts_ns(ns->uts_ns);
+ put_ipc_ns(ns->ipc_ns);
+ put_pid_ns(ns->pid_ns_for_children);
+ put_time_ns(ns->time_ns);
+ put_time_ns(ns->time_ns_for_children);
+ put_cgroup_ns(ns->cgroup_ns);
+ put_net(ns->net_ns);
+ kmem_cache_free(nsproxy_cachep, ns);
+}
+
+DEFINE_FREE(nsproxy_free, struct nsproxy *, if (_T) nsproxy_free(_T))
+
+void free_nsproxy(struct nsproxy *ns)
+{
+ nsproxy_ns_active_put(ns);
+ nsproxy_free(ns);
+}
+
/*
* Create new nsproxy and all of its the associated namespaces.
* Return the newly created nsproxy. Do not attach this to the task,
@@ -69,76 +90,45 @@ static struct nsproxy *create_new_namespaces(u64 flags,
struct task_struct *tsk, struct user_namespace *user_ns,
struct fs_struct *new_fs)
{
- struct nsproxy *new_nsp;
- int err;
+ struct nsproxy *new_nsp __free(nsproxy_free) = NULL;
new_nsp = create_nsproxy();
if (!new_nsp)
return ERR_PTR(-ENOMEM);
new_nsp->mnt_ns = copy_mnt_ns(flags, tsk->nsproxy->mnt_ns, user_ns, new_fs);
- if (IS_ERR(new_nsp->mnt_ns)) {
- err = PTR_ERR(new_nsp->mnt_ns);
- goto out_ns;
- }
+ if (IS_ERR(new_nsp->mnt_ns))
+ return ERR_CAST(new_nsp->mnt_ns);
new_nsp->uts_ns = copy_utsname(flags, user_ns, tsk->nsproxy->uts_ns);
- if (IS_ERR(new_nsp->uts_ns)) {
- err = PTR_ERR(new_nsp->uts_ns);
- goto out_uts;
- }
+ if (IS_ERR(new_nsp->uts_ns))
+ return ERR_CAST(new_nsp->uts_ns);
new_nsp->ipc_ns = copy_ipcs(flags, user_ns, tsk->nsproxy->ipc_ns);
- if (IS_ERR(new_nsp->ipc_ns)) {
- err = PTR_ERR(new_nsp->ipc_ns);
- goto out_ipc;
- }
+ if (IS_ERR(new_nsp->ipc_ns))
+ return ERR_CAST(new_nsp->ipc_ns);
- new_nsp->pid_ns_for_children =
- copy_pid_ns(flags, user_ns, tsk->nsproxy->pid_ns_for_children);
- if (IS_ERR(new_nsp->pid_ns_for_children)) {
- err = PTR_ERR(new_nsp->pid_ns_for_children);
- goto out_pid;
- }
+ new_nsp->pid_ns_for_children = copy_pid_ns(flags, user_ns,
+ tsk->nsproxy->pid_ns_for_children);
+ if (IS_ERR(new_nsp->pid_ns_for_children))
+ return ERR_CAST(new_nsp->pid_ns_for_children);
new_nsp->cgroup_ns = copy_cgroup_ns(flags, user_ns,
tsk->nsproxy->cgroup_ns);
- if (IS_ERR(new_nsp->cgroup_ns)) {
- err = PTR_ERR(new_nsp->cgroup_ns);
- goto out_cgroup;
- }
+ if (IS_ERR(new_nsp->cgroup_ns))
+ return ERR_CAST(new_nsp->cgroup_ns);
new_nsp->net_ns = copy_net_ns(flags, user_ns, tsk->nsproxy->net_ns);
- if (IS_ERR(new_nsp->net_ns)) {
- err = PTR_ERR(new_nsp->net_ns);
- goto out_net;
- }
+ if (IS_ERR(new_nsp->net_ns))
+ return ERR_CAST(new_nsp->net_ns);
new_nsp->time_ns_for_children = copy_time_ns(flags, user_ns,
- tsk->nsproxy->time_ns_for_children);
- if (IS_ERR(new_nsp->time_ns_for_children)) {
- err = PTR_ERR(new_nsp->time_ns_for_children);
- goto out_time;
- }
+ tsk->nsproxy->time_ns_for_children);
+ if (IS_ERR(new_nsp->time_ns_for_children))
+ return ERR_CAST(new_nsp->time_ns_for_children);
new_nsp->time_ns = get_time_ns(tsk->nsproxy->time_ns);
- return new_nsp;
-
-out_time:
- put_net(new_nsp->net_ns);
-out_net:
- put_cgroup_ns(new_nsp->cgroup_ns);
-out_cgroup:
- put_pid_ns(new_nsp->pid_ns_for_children);
-out_pid:
- put_ipc_ns(new_nsp->ipc_ns);
-out_ipc:
- put_uts_ns(new_nsp->uts_ns);
-out_uts:
- put_mnt_ns(new_nsp->mnt_ns);
-out_ns:
- kmem_cache_free(nsproxy_cachep, new_nsp);
- return ERR_PTR(err);
+ return no_free_ptr(new_nsp);
}
/*
@@ -185,21 +175,6 @@ int copy_namespaces(u64 flags, struct task_struct *tsk)
return 0;
}
-void free_nsproxy(struct nsproxy *ns)
-{
- nsproxy_ns_active_put(ns);
-
- put_mnt_ns(ns->mnt_ns);
- put_uts_ns(ns->uts_ns);
- put_ipc_ns(ns->ipc_ns);
- put_pid_ns(ns->pid_ns_for_children);
- put_time_ns(ns->time_ns);
- put_time_ns(ns->time_ns_for_children);
- put_cgroup_ns(ns->cgroup_ns);
- put_net(ns->net_ns);
- kmem_cache_free(nsproxy_cachep, ns);
-}
-
/*
* Called from unshare. Unshare all the namespaces part of nsproxy.
* On success, returns the new nsproxy.
@@ -338,7 +313,7 @@ static void put_nsset(struct nsset *nsset)
if (nsset->fs && (flags & CLONE_NEWNS) && (flags & ~CLONE_NEWNS))
free_fs_struct(nsset->fs);
if (nsset->nsproxy)
- free_nsproxy(nsset->nsproxy);
+ nsproxy_free(nsset->nsproxy);
}
static int prepare_nsset(unsigned flags, struct nsset *nsset)
--
2.47.3
next prev parent reply other threads:[~2025-11-11 21:30 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <690bfb9e.050a0220.2e3c35.0013.GAE@google.com>
2025-11-09 8:24 ` [syzbot] [fs?] WARNING in nsproxy_ns_active_put syzbot
2025-11-11 9:24 ` Christian Brauner
2025-11-11 9:46 ` syzbot
2025-11-11 10:26 ` Christian Brauner
2025-11-11 11:02 ` syzbot
2025-11-11 11:23 ` Christian Brauner
2025-11-11 11:38 ` Christian Brauner
2025-11-11 13:03 ` syzbot
2025-11-11 15:07 ` Christian Brauner
2025-11-11 16:14 ` syzbot
2025-11-11 21:29 ` Christian Brauner [this message]
2025-11-13 11:19 ` [PATCH] nsproxy: fix free_nsproxy() and simplify create_new_namespaces() Jan Kara
2025-11-13 13:05 ` Christian Brauner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251111-sakralbau-guthaben-7dcc277d337f@brauner \
--to=brauner@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=bpf@vger.kernel.org \
--cc=bsegall@google.com \
--cc=david@redhat.com \
--cc=dietmar.eggemann@arm.com \
--cc=jack@suse.cz \
--cc=jsavitz@redhat.com \
--cc=juri.lelli@redhat.com \
--cc=kartikey406@gmail.com \
--cc=kees@kernel.org \
--cc=liam.howlett@oracle.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-security-module@vger.kernel.org \
--cc=lorenzo.stoakes@oracle.com \
--cc=mgorman@suse.de \
--cc=mhocko@suse.com \
--cc=mingo@redhat.com \
--cc=mjguzik@gmail.com \
--cc=oleg@redhat.com \
--cc=paul@paul-moore.com \
--cc=peterz@infradead.org \
--cc=rostedt@goodmis.org \
--cc=rppt@kernel.org \
--cc=sergeh@kernel.org \
--cc=surenb@google.com \
--cc=syzbot+0a8655a80e189278487e@syzkaller.appspotmail.com \
--cc=syzbot+0b2e79f91ff6579bfa5b@syzkaller.appspotmail.com \
--cc=syzkaller-bugs@googlegroups.com \
--cc=vbabka@suse.cz \
--cc=vincent.guittot@linaro.org \
--cc=viro@zeniv.linux.org.uk \
--cc=vschneid@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox