[Devel] [PATCH 12/13] pidns: add proc mount option 'hidepidns=0|1'

Alexander Mikhalitsyn alexander.mikhalitsyn at virtuozzo.com
Wed Apr 14 10:57:59 MSK 2021


From: Konstantin Khlebnikov <khlebnikov at openvz.org>

hidepidns=1 makes all tasks from nested pid-namespaces invisible.
They are still accessible via /proc/<pid>/, but readdir will not show them.

Signed-off-by: Konstantin Khlebnikov <khlebnikov at openvz.org>

===

VZ 8 rebase part https://jira.sw.ru/browse/PSBM-127782

Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn at virtuozzo.com>
---
 Documentation/filesystems/proc.txt |  4 ++++
 fs/proc/base.c                     | 10 +++++++++-
 fs/proc/inode.c                    |  2 ++
 fs/proc/root.c                     | 12 +++++++++++-
 include/linux/pid_namespace.h      |  1 +
 5 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index aa9a006b4bac..e19717145ba1 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -1943,6 +1943,7 @@ Configuring procfs
 The following mount options are supported:
 
 	hidepid=	Set /proc/<pid>/ access mode.
+	hidepidns=	Hide tasks from nested pid-namespaces.
 	gid=		Set the group authorized to learn processes information.
 
 hidepid=0 means classic mode - everybody may access all /proc/<pid>/ directories
@@ -1965,6 +1966,9 @@ information about running processes, whether some daemon runs with elevated
 privileges, whether other user runs some sensitive program, whether other users
 run any program at all, etc.
 
+hidepidns=1 makes all tasks from nested pid-namespaces invisible. They are still
+accessible via /proc/<pid>/, but readdir will not show them.
+
 gid= defines a group authorized to learn processes information otherwise
 prohibited by hidepid=.  If you use some daemon like identd which needs to learn
 information about processes information, just add identd to this group.
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 38268a980989..f931b1c0f902 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -690,6 +690,14 @@ static bool has_pid_permissions(struct pid_namespace *pid,
 	return ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS);
 }
 
+static bool is_visible_task(struct pid_namespace *ns, struct task_struct *tsk)
+{
+	if (ns->hide_pidns == 1 && task_active_pid_ns(tsk) != ns)
+		return false;
+	if (!has_pid_permissions(ns, tsk, HIDEPID_INVISIBLE))
+		return false;
+	return true;
+}
 
 static int proc_pid_permission(struct inode *inode, int mask)
 {
@@ -3275,7 +3283,7 @@ int proc_pid_readdir(struct file *file, struct dir_context *ctx)
 		unsigned int len;
 
 		cond_resched();
-		if (!has_pid_permissions(ns, iter.task, HIDEPID_INVISIBLE))
+		if (!is_visible_task(ns, iter.task))
 			continue;
 
 		len = snprintf(name, sizeof(name), "%u", iter.tgid);
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 847f4f3d2197..b448ecfeef77 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -118,6 +118,8 @@ static int proc_show_options(struct seq_file *seq, struct dentry *root)
 		seq_printf(seq, ",gid=%u", from_kgid_munged(&init_user_ns, pid->pid_gid));
 	if (pid->hide_pid != HIDEPID_OFF)
 		seq_printf(seq, ",hidepid=%u", pid->hide_pid);
+	if (pid->hide_pidns)
+		seq_printf(seq, ",hidepidns=%u", pid->hide_pidns);
 
 	return 0;
 }
diff --git a/fs/proc/root.c b/fs/proc/root.c
index cc34755ab33f..5be02b4af298 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -27,11 +27,12 @@
 #include "internal.h"
 
 enum {
-	Opt_gid, Opt_hidepid, Opt_err,
+	Opt_gid, Opt_hidepid, Opt_hidepidns, Opt_err,
 };
 
 static const match_table_t tokens = {
 	{Opt_hidepid, "hidepid=%u"},
+	{Opt_hidepidns, "hidepidns=%u"},
 	{Opt_gid, "gid=%u"},
 	{Opt_err, NULL},
 };
@@ -68,6 +69,15 @@ int proc_parse_options(char *options, struct pid_namespace *pid)
 			}
 			pid->hide_pid = option;
 			break;
+		case Opt_hidepidns:
+			if (match_int(&args[0], &option))
+				return 0;
+			if (option < 0 || option > 1) {
+				pr_err("proc: hidepidns value must be between 0 and 1.\n");
+				return 0;
+			}
+			pid->hide_pidns = option;
+			break;
 		default:
 			pr_err("proc: unrecognized mount option \"%s\" "
 			       "or missing value\n", p);
diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h
index 49538b172483..41a948c37e0f 100644
--- a/include/linux/pid_namespace.h
+++ b/include/linux/pid_namespace.h
@@ -43,6 +43,7 @@ struct pid_namespace {
 	struct work_struct proc_work;
 	kgid_t pid_gid;
 	int hide_pid;
+	int hide_pidns;
 	int reboot;	/* group exit code if this pidns was rebooted */
 	struct ns_common ns;
 } __randomize_layout;
-- 
2.28.0



More information about the Devel mailing list