Re: [PATCH 0/2] nsfs: gate pid-translation ioctls behind ptrace read access
From: Christian Brauner
Date: Fri Oct 30 2026 - 12:26:10 EST
On Fri, Oct 30, 2026 at 09:04:20PM +0800, Tao Cui wrote:
> The four NS_GET_{PID,TGID}_{FROM,IN}_PIDNS ioctls on nsfs descriptors
> only check that the fd refers to a PID namespace; they never check
> whether the caller may inspect the task being looked up. An nsfs fd
> is freely transferable (SCM_RIGHTS), so an unprivileged process that
> receives one - the way container runtimes and LXCFS hand namespace
> fds to less privileged helpers - can use these ioctls as a task
> enumeration oracle across pid namespaces, bypassing the ptrace-gated
> /proc files.
No. These ioctls translate pid numbers between the caller's pid
namespace and the one the fd refers to. NS_GET_PID_FROM_PIDNS does
find_task_by_pid_ns() and then task_pid_vnr(), so a task the caller
can't see from its own pid namespace already comes back as -ESRCH.
And NS_GET_PID_IN_PIDNS starts from find_task_by_vpid(), i.e. from tasks
the caller can see anyway. IOW, they already follow the same rule that
PIDFD_GET_INFO enforces.
And pid numbers aren't hidden from unprivileged tasks to begin with.
pidfd_open() has no permission check, /proc/self/fdinfo/<pidfd> prints
NSpid for every level below the caller's pid namespace, PIDFD_GET_INFO
returns pid, tgid and ppid without a ptrace check and so does
/proc/<pid>/status with hidepid=0. hidepid hides /proc/<pid>, it never
hid pid existence or pid numbers.
> Two residual behaviours are worth stating explicitly: ESRCH is still
> returned before the permission check, so pid existence remains a
> 1-bit signal - the same residual pidfs and /proc carry today; and
That's not what the patch does. With an ancestor or sibling pid
namespace fd a task outside the caller's hierarchy now fails with
-EACCES while a missing pid fails with -ESRCH. That's a new existence
oracle. for example, for host pids from inside a container, that doesn't
exist today. And it breaks same-uid translation of non-dumpable tasks
and any LSM-confined holder that gets ptrace read denied, which includes
the LXCFS case you say is unaffected.
The selftest isn't correct either.