]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
pidfs: protect PIDFD_GET_* ioctls() via ifdef
authorChristian Brauner <brauner@kernel.org>
Wed, 24 Dec 2025 12:00:24 +0000 (13:00 +0100)
committerChristian Brauner <brauner@kernel.org>
Tue, 6 Jan 2026 22:08:12 +0000 (23:08 +0100)
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>
fs/pidfs.c

index dba703d4ce4a8a1a1c96f4aa6fcc3f5dd5aa3169..1e20e36e0ed559b32e948db1e2ecd2852b86f903 100644 (file)
@@ -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;