diff options
| author | Christian Brauner <brauner@kernel.org> | 2025-12-24 13:00:24 +0100 |
|---|---|---|
| committer | Christian Brauner <brauner@kernel.org> | 2026-01-06 23:08:12 +0100 |
| commit | 75ddaa4ddc86d31edb15e50152adf4ddee77a6ba (patch) | |
| tree | 33b0f6e26e24051de90102290222f7bad6e2b988 | |
| parent | 78c850021d36d43401de2fb4758f02df93266a6f (diff) | |
pidfs: protect PIDFD_GET_* ioctls() via ifdef
We originally protected PIDFD_GET_<ns-type>_NAMESPACE ioctls() through
ifdefs and recent rework made it possible to drop them. There was an
oversight though. When the relevant namespace is turned off ns->ops will
be NULL so even though opening a file descriptor is perfectly legitimate
it would fail during inode eviction when the file was closed.
The simple fix would be to check ns->ops for NULL and continue allow to
retrieve namespace fds from pidfds but we don't allow retrieving them
when the relevant namespace type is turned off. So keep the
simplification but add the ifdefs back in.
Link: https://lore.kernel.org/20251222214907.GA189632@quark
Link: https://patch.msgid.link/20251224-ununterbrochen-gagen-ea949b83f8f2@brauner
Fixes: a71e4f103aed ("pidfs: simplify PIDFD_GET_<type>_NAMESPACE ioctls")
Tested-by: Brendan Jackman <jackmanb@kernel.org>
Tested-by: Eric Biggers <ebiggers@kernel.org>
Reported-by: Eric Biggers <ebiggers@kernel.org>
Signed-off-by: Christian Brauner <brauner@kernel.org>
| -rw-r--r-- | fs/pidfs.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/fs/pidfs.c b/fs/pidfs.c index dba703d4ce4a..1e20e36e0ed5 100644 --- a/fs/pidfs.c +++ b/fs/pidfs.c @@ -517,14 +517,18 @@ static long pidfd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) switch (cmd) { /* Namespaces that hang of nsproxy. */ case PIDFD_GET_CGROUP_NAMESPACE: +#ifdef CONFIG_CGROUPS if (!ns_ref_get(nsp->cgroup_ns)) break; ns_common = to_ns_common(nsp->cgroup_ns); +#endif break; case PIDFD_GET_IPC_NAMESPACE: +#ifdef CONFIG_IPC_NS if (!ns_ref_get(nsp->ipc_ns)) break; ns_common = to_ns_common(nsp->ipc_ns); +#endif break; case PIDFD_GET_MNT_NAMESPACE: if (!ns_ref_get(nsp->mnt_ns)) @@ -532,32 +536,43 @@ static long pidfd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ns_common = to_ns_common(nsp->mnt_ns); break; case PIDFD_GET_NET_NAMESPACE: +#ifdef CONFIG_NET_NS if (!ns_ref_get(nsp->net_ns)) break; ns_common = to_ns_common(nsp->net_ns); +#endif break; case PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE: +#ifdef CONFIG_PID_NS if (!ns_ref_get(nsp->pid_ns_for_children)) break; ns_common = to_ns_common(nsp->pid_ns_for_children); +#endif break; case PIDFD_GET_TIME_NAMESPACE: +#ifdef CONFIG_TIME_NS if (!ns_ref_get(nsp->time_ns)) break; ns_common = to_ns_common(nsp->time_ns); +#endif break; case PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE: +#ifdef CONFIG_TIME_NS if (!ns_ref_get(nsp->time_ns_for_children)) break; ns_common = to_ns_common(nsp->time_ns_for_children); +#endif break; case PIDFD_GET_UTS_NAMESPACE: +#ifdef CONFIG_UTS_NS if (!ns_ref_get(nsp->uts_ns)) break; ns_common = to_ns_common(nsp->uts_ns); +#endif break; /* Namespaces that don't hang of nsproxy. */ case PIDFD_GET_USER_NAMESPACE: +#ifdef CONFIG_USER_NS scoped_guard(rcu) { struct user_namespace *user_ns; @@ -566,8 +581,10 @@ static long pidfd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; ns_common = to_ns_common(user_ns); } +#endif break; case PIDFD_GET_PID_NAMESPACE: +#ifdef CONFIG_PID_NS scoped_guard(rcu) { struct pid_namespace *pid_ns; @@ -576,6 +593,7 @@ static long pidfd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; ns_common = to_ns_common(pid_ns); } +#endif break; default: return -ENOIOCTLCMD; |
