Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

pidfd: add NSpid entries to fdinfo

Currently, the fdinfo file contains the Pid field which shows the
pid a given pidfd refers to in the pid namespace of the procfs
instance. If pid namespaces are configured, also show an NSpid field
for easy retrieval of the pid in all descendant pid namespaces. If
the pid namespace of the process is not a descendant of the pid
namespace of the procfs instance 0 will be shown as its first NSpid
entry and no other entries will be shown. Add a block comment to
pidfd_show_fdinfo with a detailed explanation of Pid and NSpid fields.

Co-developed-by: Christian Brauner <christian.brauner@ubuntu.com>
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
Signed-off-by: Christian Kellner <christian@kellner.me>
Reviewed-by: Christian Brauner <christian.brauner@ubuntu.com>
Link: https://lore.kernel.org/r/20191014162034.2185-1-ckellner@redhat.com
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>

authored by

Christian Kellner and committed by
Christian Brauner
15d42eb2 4f5cafb5

+52 -1
+52 -1
kernel/fork.c
··· 1695 1695 } 1696 1696 1697 1697 #ifdef CONFIG_PROC_FS 1698 + /** 1699 + * pidfd_show_fdinfo - print information about a pidfd 1700 + * @m: proc fdinfo file 1701 + * @f: file referencing a pidfd 1702 + * 1703 + * Pid: 1704 + * This function will print the pid that a given pidfd refers to in the 1705 + * pid namespace of the procfs instance. 1706 + * If the pid namespace of the process is not a descendant of the pid 1707 + * namespace of the procfs instance 0 will be shown as its pid. This is 1708 + * similar to calling getppid() on a process whose parent is outside of 1709 + * its pid namespace. 1710 + * 1711 + * NSpid: 1712 + * If pid namespaces are supported then this function will also print 1713 + * the pid of a given pidfd refers to for all descendant pid namespaces 1714 + * starting from the current pid namespace of the instance, i.e. the 1715 + * Pid field and the first entry in the NSpid field will be identical. 1716 + * If the pid namespace of the process is not a descendant of the pid 1717 + * namespace of the procfs instance 0 will be shown as its first NSpid 1718 + * entry and no others will be shown. 1719 + * Note that this differs from the Pid and NSpid fields in 1720 + * /proc/<pid>/status where Pid and NSpid are always shown relative to 1721 + * the pid namespace of the procfs instance. The difference becomes 1722 + * obvious when sending around a pidfd between pid namespaces from a 1723 + * different branch of the tree, i.e. where no ancestoral relation is 1724 + * present between the pid namespaces: 1725 + * - create two new pid namespaces ns1 and ns2 in the initial pid 1726 + * namespace (also take care to create new mount namespaces in the 1727 + * new pid namespace and mount procfs) 1728 + * - create a process with a pidfd in ns1 1729 + * - send pidfd from ns1 to ns2 1730 + * - read /proc/self/fdinfo/<pidfd> and observe that both Pid and NSpid 1731 + * have exactly one entry, which is 0 1732 + */ 1698 1733 static void pidfd_show_fdinfo(struct seq_file *m, struct file *f) 1699 1734 { 1700 1735 struct pid_namespace *ns = proc_pid_ns(file_inode(m->file)); 1701 1736 struct pid *pid = f->private_data; 1737 + pid_t nr = pid_nr_ns(pid, ns); 1702 1738 1703 - seq_put_decimal_ull(m, "Pid:\t", pid_nr_ns(pid, ns)); 1739 + seq_put_decimal_ull(m, "Pid:\t", nr); 1740 + 1741 + #ifdef CONFIG_PID_NS 1742 + seq_put_decimal_ull(m, "\nNSpid:\t", nr); 1743 + if (nr) { 1744 + int i; 1745 + 1746 + /* If nr is non-zero it means that 'pid' is valid and that 1747 + * ns, i.e. the pid namespace associated with the procfs 1748 + * instance, is in the pid namespace hierarchy of pid. 1749 + * Start at one below the already printed level. 1750 + */ 1751 + for (i = ns->level + 1; i <= pid->level; i++) 1752 + seq_put_decimal_ull(m, "\t", pid->numbers[i].nr); 1753 + } 1754 + #endif 1704 1755 seq_putc(m, '\n'); 1705 1756 } 1706 1757 #endif