[Devel] [PATCH RH9 16/22] pidns: add proc mount option 'hidepidns=0|1'

Andrey Zhadchenko andrey.zhadchenko at virtuozzo.com
Thu Oct 7 13:57:40 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
vz7 commit: a98711f ("pidns: add proc mount option 'hidepidns=0|1'")

Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn at virtuozzo.com>

Rebased to vz9:
- hide_pid is moved from struct pid_namespace to new struct proc_fs_info,
so move hide_pidns accordingly
- add new fs_info argument to is_visible() since has_pid_permissions() now
uses fs_context argument

(cherry picked from vz8 commit e227ad685ab89e1ef76bfe7c6de84900d4590a73)
Signed-off-by: Andrey Zhadchenko <andrey.zhadchenko at virtuozzo.com>
---
 Documentation/filesystems/proc.rst |  4 ++++
 fs/proc/base.c                     | 11 ++++++++++-
 fs/proc/inode.c                    |  2 ++
 fs/proc/root.c                     | 12 ++++++++++++
 include/linux/proc_fs.h            |  1 +
 5 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/Documentation/filesystems/proc.rst b/Documentation/filesystems/proc.rst
index 042c418..49e3fa4 100644
--- a/Documentation/filesystems/proc.rst
+++ b/Documentation/filesystems/proc.rst
@@ -2184,6 +2184,7 @@ Chapter 4: Configuring procfs
 
 	=========	========================================================
 	hidepid=	Set /proc/<pid>/ access mode.
+	hidepidns=	Hide tasks from nested pid-namespaces.
 	gid=		Set the group authorized to learn processes information.
 	subset=		Show only the specified subset of procfs.
 	=========	========================================================
@@ -2211,6 +2212,9 @@ other users run any program at all, etc.
 hidepid=ptraceable or hidepid=4 means that procfs should only contain
 /proc/<pid>/ directories that the caller can ptrace.
 
+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 6fb9575..550866d 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -730,6 +730,15 @@ static bool has_pid_permissions(struct proc_fs_info *fs_info,
 	return ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS);
 }
 
+static bool is_visible_task(struct pid_namespace *ns,
+			    struct proc_fs_info *fs_info, struct task_struct *tsk)
+{
+	if (fs_info->hide_pidns == 1 && task_active_pid_ns(tsk) != ns)
+		return false;
+	if (!has_pid_permissions(fs_info, tsk, HIDEPID_INVISIBLE))
+		return false;
+	return true;
+}
 
 static int proc_pid_permission(struct user_namespace *mnt_userns,
 			       struct inode *inode, int mask)
@@ -3491,7 +3500,7 @@ int proc_pid_readdir(struct file *file, struct dir_context *ctx)
 		unsigned int len;
 
 		cond_resched();
-		if (!has_pid_permissions(fs_info, iter.task, HIDEPID_INVISIBLE))
+		if (!is_visible_task(ns, fs_info, iter.task))
 			continue;
 
 		len = snprintf(name, sizeof(name), "%u", iter.tgid);
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 35699dc..270fb81 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -186,6 +186,8 @@ static int proc_show_options(struct seq_file *seq, struct dentry *root)
 		seq_printf(seq, ",gid=%u", from_kgid_munged(&init_user_ns, fs_info->pid_gid));
 	if (fs_info->hide_pid != HIDEPID_OFF)
 		seq_printf(seq, ",hidepid=%s", hidepid2str(fs_info->hide_pid));
+	if (fs_info->hide_pidns)
+		seq_printf(seq, ",hidepidns=%u", fs_info->hide_pidns);
 	if (fs_info->pidonly != PROC_PIDONLY_OFF)
 		seq_printf(seq, ",subset=pid");
 
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 5e5944a..3e9de20 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -33,6 +33,7 @@ struct proc_fs_context {
 	struct pid_namespace	*pid_ns;
 	unsigned int		mask;
 	enum proc_hidepid	hidepid;
+	int			hidepidns;
 	int			gid;
 	enum proc_pidonly	pidonly;
 };
@@ -40,12 +41,14 @@ struct proc_fs_context {
 enum proc_param {
 	Opt_gid,
 	Opt_hidepid,
+	Opt_hidepidns,
 	Opt_subset,
 };
 
 static const struct fs_parameter_spec proc_fs_parameters[] = {
 	fsparam_u32("gid",	Opt_gid),
 	fsparam_string("hidepid",	Opt_hidepid),
+	fsparam_u32("hidepidns",Opt_hidepidns),
 	fsparam_string("subset",	Opt_subset),
 	{}
 };
@@ -137,6 +140,13 @@ static int proc_parse_param(struct fs_context *fc, struct fs_parameter *param)
 			return -EINVAL;
 		break;
 
+	case Opt_hidepidns:
+		ctx->hidepidns = result.uint_32;
+		if (ctx->hidepidns < 0 || ctx->hidepidns > 1) {
+			return invalfc(fc, "proc: hidepidns value must be between 0 and 1.\n");
+		}
+		break;
+
 	default:
 		return -EINVAL;
 	}
@@ -155,6 +165,8 @@ static void proc_apply_options(struct proc_fs_info *fs_info,
 		fs_info->pid_gid = make_kgid(user_ns, ctx->gid);
 	if (ctx->mask & (1 << Opt_hidepid))
 		fs_info->hide_pid = ctx->hidepid;
+	if (ctx->mask & (1 << Opt_hidepidns))
+		fs_info->hide_pidns = ctx->hidepidns;
 	if (ctx->mask & (1 << Opt_subset))
 		fs_info->pidonly = ctx->pidonly;
 }
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index aa59b35..9c6f204 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -65,6 +65,7 @@ struct proc_fs_info {
 	kgid_t pid_gid;
 	enum proc_hidepid hide_pid;
 	enum proc_pidonly pidonly;
+	int hide_pidns;
 };
 
 static inline struct proc_fs_info *proc_sb_info(struct super_block *sb)
-- 
1.8.3.1



More information about the Devel mailing list