1
0
mirror of https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git synced 2026-01-11 17:10:13 +00:00

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>
This commit is contained in:
Christian Brauner 2025-12-24 13:00:24 +01:00
parent 78c850021d
commit 75ddaa4ddc
No known key found for this signature in database
GPG Key ID: 91C61BC06578DCA2

View File

@ -517,14 +517,18 @@ static long pidfd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
switch (cmd) { switch (cmd) {
/* Namespaces that hang of nsproxy. */ /* Namespaces that hang of nsproxy. */
case PIDFD_GET_CGROUP_NAMESPACE: case PIDFD_GET_CGROUP_NAMESPACE:
#ifdef CONFIG_CGROUPS
if (!ns_ref_get(nsp->cgroup_ns)) if (!ns_ref_get(nsp->cgroup_ns))
break; break;
ns_common = to_ns_common(nsp->cgroup_ns); ns_common = to_ns_common(nsp->cgroup_ns);
#endif
break; break;
case PIDFD_GET_IPC_NAMESPACE: case PIDFD_GET_IPC_NAMESPACE:
#ifdef CONFIG_IPC_NS
if (!ns_ref_get(nsp->ipc_ns)) if (!ns_ref_get(nsp->ipc_ns))
break; break;
ns_common = to_ns_common(nsp->ipc_ns); ns_common = to_ns_common(nsp->ipc_ns);
#endif
break; break;
case PIDFD_GET_MNT_NAMESPACE: case PIDFD_GET_MNT_NAMESPACE:
if (!ns_ref_get(nsp->mnt_ns)) 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); ns_common = to_ns_common(nsp->mnt_ns);
break; break;
case PIDFD_GET_NET_NAMESPACE: case PIDFD_GET_NET_NAMESPACE:
#ifdef CONFIG_NET_NS
if (!ns_ref_get(nsp->net_ns)) if (!ns_ref_get(nsp->net_ns))
break; break;
ns_common = to_ns_common(nsp->net_ns); ns_common = to_ns_common(nsp->net_ns);
#endif
break; break;
case PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE: case PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE:
#ifdef CONFIG_PID_NS
if (!ns_ref_get(nsp->pid_ns_for_children)) if (!ns_ref_get(nsp->pid_ns_for_children))
break; break;
ns_common = to_ns_common(nsp->pid_ns_for_children); ns_common = to_ns_common(nsp->pid_ns_for_children);
#endif
break; break;
case PIDFD_GET_TIME_NAMESPACE: case PIDFD_GET_TIME_NAMESPACE:
#ifdef CONFIG_TIME_NS
if (!ns_ref_get(nsp->time_ns)) if (!ns_ref_get(nsp->time_ns))
break; break;
ns_common = to_ns_common(nsp->time_ns); ns_common = to_ns_common(nsp->time_ns);
#endif
break; break;
case PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE: case PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE:
#ifdef CONFIG_TIME_NS
if (!ns_ref_get(nsp->time_ns_for_children)) if (!ns_ref_get(nsp->time_ns_for_children))
break; break;
ns_common = to_ns_common(nsp->time_ns_for_children); ns_common = to_ns_common(nsp->time_ns_for_children);
#endif
break; break;
case PIDFD_GET_UTS_NAMESPACE: case PIDFD_GET_UTS_NAMESPACE:
#ifdef CONFIG_UTS_NS
if (!ns_ref_get(nsp->uts_ns)) if (!ns_ref_get(nsp->uts_ns))
break; break;
ns_common = to_ns_common(nsp->uts_ns); ns_common = to_ns_common(nsp->uts_ns);
#endif
break; break;
/* Namespaces that don't hang of nsproxy. */ /* Namespaces that don't hang of nsproxy. */
case PIDFD_GET_USER_NAMESPACE: case PIDFD_GET_USER_NAMESPACE:
#ifdef CONFIG_USER_NS
scoped_guard(rcu) { scoped_guard(rcu) {
struct user_namespace *user_ns; struct user_namespace *user_ns;
@ -566,8 +581,10 @@ static long pidfd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
break; break;
ns_common = to_ns_common(user_ns); ns_common = to_ns_common(user_ns);
} }
#endif
break; break;
case PIDFD_GET_PID_NAMESPACE: case PIDFD_GET_PID_NAMESPACE:
#ifdef CONFIG_PID_NS
scoped_guard(rcu) { scoped_guard(rcu) {
struct pid_namespace *pid_ns; struct pid_namespace *pid_ns;
@ -576,6 +593,7 @@ static long pidfd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
break; break;
ns_common = to_ns_common(pid_ns); ns_common = to_ns_common(pid_ns);
} }
#endif
break; break;
default: default:
return -ENOIOCTLCMD; return -ENOIOCTLCMD;