From 24a71ce5c47f6b1b3cdacf544cb24220f5c3b7ef Mon Sep 17 00:00:00 2001 From: Alexey Gladkov Date: Sun, 19 Apr 2020 16:10:53 +0200 Subject: proc: instantiate only pids that we can ptrace on 'hidepid=4' mount option If "hidepid=4" mount option is set then do not instantiate pids that we can not ptrace. "hidepid=4" means that procfs should only contain pids that the caller can ptrace. Signed-off-by: Djalal Harouni Signed-off-by: Alexey Gladkov Reviewed-by: Alexey Dobriyan Reviewed-by: Kees Cook Signed-off-by: Eric W. Biederman --- fs/proc/base.c | 15 +++++++++++++++ fs/proc/root.c | 13 ++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) (limited to 'fs/proc') diff --git a/fs/proc/base.c b/fs/proc/base.c index 93b5d05c142c..a52a91e90c25 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -701,6 +701,14 @@ static bool has_pid_permissions(struct proc_fs_info *fs_info, struct task_struct *task, int hide_pid_min) { + /* + * If 'hidpid' mount option is set force a ptrace check, + * we indicate that we are using a filesystem syscall + * by passing PTRACE_MODE_READ_FSCREDS + */ + if (fs_info->hide_pid == HIDEPID_NOT_PTRACEABLE) + return ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS); + if (fs_info->hide_pid < hide_pid_min) return true; if (in_group_p(fs_info->pid_gid)) @@ -3319,7 +3327,14 @@ struct dentry *proc_pid_lookup(struct dentry *dentry, unsigned int flags) if (!task) goto out; + /* Limit procfs to only ptraceable tasks */ + if (fs_info->hide_pid == HIDEPID_NOT_PTRACEABLE) { + if (!has_pid_permissions(fs_info, task, HIDEPID_NO_ACCESS)) + goto out_put_task; + } + result = proc_pid_instantiate(dentry, task, NULL); +out_put_task: put_task_struct(task); out: return result; diff --git a/fs/proc/root.c b/fs/proc/root.c index 208989274923..8f23b951d685 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -47,6 +47,14 @@ static const struct fs_parameter_spec proc_fs_parameters[] = { {} }; +static inline int valid_hidepid(unsigned int value) +{ + return (value == HIDEPID_OFF || + value == HIDEPID_NO_ACCESS || + value == HIDEPID_INVISIBLE || + value == HIDEPID_NOT_PTRACEABLE); +} + static int proc_parse_param(struct fs_context *fc, struct fs_parameter *param) { struct proc_fs_context *ctx = fc->fs_private; @@ -63,10 +71,9 @@ static int proc_parse_param(struct fs_context *fc, struct fs_parameter *param) break; case Opt_hidepid: + if (!valid_hidepid(result.uint_32)) + return invalf(fc, "proc: unknown value of hidepid.\n"); ctx->hidepid = result.uint_32; - if (ctx->hidepid < HIDEPID_OFF || - ctx->hidepid > HIDEPID_INVISIBLE) - return invalfc(fc, "hidepid value must be between 0 and 2.\n"); break; default: -- cgit v1.2.3