diff options
author | Alexey Gladkov <gladkov.alexey@gmail.com> | 2020-04-19 16:10:53 +0200 |
---|---|---|
committer | Eric W. Biederman <ebiederm@xmission.com> | 2020-04-22 10:51:21 -0500 |
commit | 24a71ce5c47f6b1b3cdacf544cb24220f5c3b7ef (patch) | |
tree | da93b7bfc767c3fad21663b6c1aab72e2e9ffec8 | |
parent | fa10fed30f2550313a8284365b3e2398526eb42c (diff) |
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 <tixxdz@gmail.com>
Signed-off-by: Alexey Gladkov <gladkov.alexey@gmail.com>
Reviewed-by: Alexey Dobriyan <adobriyan@gmail.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
-rw-r--r-- | fs/proc/base.c | 15 | ||||
-rw-r--r-- | fs/proc/root.c | 13 | ||||
-rw-r--r-- | include/linux/proc_fs.h | 1 |
3 files changed, 26 insertions, 3 deletions
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: diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 1b98a41fdd8a..5bdc117ae947 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -47,6 +47,7 @@ enum { HIDEPID_OFF = 0, HIDEPID_NO_ACCESS = 1, HIDEPID_INVISIBLE = 2, + HIDEPID_NOT_PTRACEABLE = 4, /* Limit pids to only ptraceable pids */ }; struct proc_fs_info { |