[PATCH 1/2] nsfs: require ptrace read access for pid translation ioctls
From: Tao Cui
Date: Fri Oct 30 2026 - 09:14:40 EST
From: Tao Cui <cuitao@xxxxxxxxxx>
The four NS_GET_{PID,TGID}_{FROM,IN}_PIDNS ioctls translate a pid
between the caller's pid namespace and the namespace referred to by
the open nsfs file without checking that the caller may ptrace the
task being looked up. Nsfs fds travel freely over SCM_RIGHTS, so
once such an fd reaches a process on a hidepid=2 host it can
enumerate and resolve the pids of tasks hidepid means to hide.
Mirror the ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS) check
the PIDFD_GET_*_NAMESPACE ioctls have had since
commit 5b08bd408534 ("pidfs: allow retrieval of namespace file
descriptors"): perform the check inside the existing RCU read-side
critical section and return -EACCES when the caller lacks ptrace
access. Legitimate holders such as LXCFS are unaffected.
Fixes: ca567df74a28 ("nsfs: add pid translation ioctls")
Signed-off-by: Tao Cui <cuitao@xxxxxxxxxx>
---
fs/nsfs.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/fs/nsfs.c b/fs/nsfs.c
index 8179d69da038..9ff30bd876cf 100644
--- a/fs/nsfs.c
+++ b/fs/nsfs.c
@@ -9,6 +9,7 @@
#include <linux/ktime.h>
#include <linux/seq_file.h>
#include <linux/pid_namespace.h>
+#include <linux/ptrace.h>
#include <linux/user_namespace.h>
#include <linux/nsfs.h>
#include <linux/uaccess.h>
@@ -268,6 +269,19 @@ static long ns_ioctl(struct file *filp, unsigned int ioctl,
if (!tsk)
return ret;
+ /*
+ * The returned ids reveal whether @tsk is alive and which
+ * pid it has in @pid_ns, so require the same read access
+ * to @tsk that ptrace-gated /proc/<pid> files need. @tsk is
+ * only pinned by RCU, but calling ptrace_may_access()
+ * here is safe by the same pattern as validate_nsset()
+ * (kernel/nsproxy.c); ptrace_may_access() runs under
+ * the target's task_lock. The PIDFD_GET_*_NAMESPACE ioctls
+ * in fs/pidfs.c carry the same check.
+ */
+ if (!ptrace_may_access(tsk, PTRACE_MODE_READ_FSCREDS))
+ return -EACCES;
+
switch (ioctl) {
case NS_GET_PID_FROM_PIDNS:
ret = task_pid_vnr(tsk);
--
2.43.0