History

proc: use human-readable values for hidepid

The hidepid parameter values are becoming more and more and it becomes difficult to remember what each new magic number means. Backward compatibility is preserved since it is possible to specify numerical value for the hidepid parameter. This does not break the fsconfig since it is not possible to specify a numerical value through it. All numeric values are converted to a string. The type FSCONFIG_SET_BINARY cannot be used to indicate a numerical value. Selftest has been added to verify this behavior.

Alexey Gladkov committed 6 years ago

Commit 1c6c4d11 parent 37e76476 files · +126 −31Browse files

Unified · Split

6 files
  1. Documentation/filesystems/proc.rst +26 −26
  2. fs/proc/inode.c +14 −1
  3. fs/proc/root.c +34 −4
  4. tools/testing/selftests/proc/.gitignore +1 −0
  5. tools/testing/selftests/proc/Makefile +1 −0
  6. tools/testing/selftests/proc/proc-fsconfig-hidepid.c +50 −0
Documentation/filesystems/proc.rst+26−26
@@ -2147,28 +2147,28 @@ The following mount options are supported: · 2146 unmodified lines
2147 subset= Show only the specified subset of procfs.2147 subset= Show only the specified subset of procfs.
2148 ========= ========================================================2148 ========= ========================================================
2149 2149
2150hidepid=0 means classic mode - everybody may access all /proc/<pid>/ directories2150hidepid=off or hidepid=0 means classic mode - everybody may access all
2151(default).2151/proc/<pid>/ directories (default).
2152 2152
2153hidepid=1 means users may not access any /proc/<pid>/ directories but their2153hidepid=noaccess or hidepid=1 means users may not access any /proc/<pid>/
2154own. Sensitive files like cmdline, sched*, status are now protected against2154directories but their own. Sensitive files like cmdline, sched*, status are now
2155other users. This makes it impossible to learn whether any user runs2155protected against other users. This makes it impossible to learn whether any
2156specific program (given the program doesn't reveal itself by its behaviour).2156user runs specific program (given the program doesn't reveal itself by its
2157As an additional bonus, as /proc/<pid>/cmdline is unaccessible for other users,2157behaviour). As an additional bonus, as /proc/<pid>/cmdline is unaccessible for
2158poorly written programs passing sensitive information via program arguments are2158other users, poorly written programs passing sensitive information via program
2159now protected against local eavesdroppers.2159arguments are now protected against local eavesdroppers.
2160 2160
2161hidepid=2 means hidepid=1 plus all /proc/<pid>/ will be fully invisible to other2161hidepid=invisible or hidepid=2 means hidepid=1 plus all /proc/<pid>/ will be
2162users. It doesn't mean that it hides a fact whether a process with a specific2162fully invisible to other users. It doesn't mean that it hides a fact whether a
2163pid value exists (it can be learned by other means, e.g. by "kill -0 $PID"),2163process with a specific pid value exists (it can be learned by other means, e.g.
2164but it hides process' uid and gid, which may be learned by stat()'ing2164by "kill -0 $PID"), but it hides process' uid and gid, which may be learned by
2165/proc/<pid>/ otherwise. It greatly complicates an intruder's task of gathering2165stat()'ing /proc/<pid>/ otherwise. It greatly complicates an intruder's task of
2166information about running processes, whether some daemon runs with elevated2166gathering information about running processes, whether some daemon runs with
2167privileges, whether other user runs some sensitive program, whether other users2167elevated privileges, whether other user runs some sensitive program, whether
2168run any program at all, etc.2168other users run any program at all, etc.
2169 2169
2170hidepid=4 means that procfs should only contain /proc/<pid>/ directories2170hidepid=ptraceable or hidepid=4 means that procfs should only contain
2171that the caller can ptrace.2171/proc/<pid>/ directories that the caller can ptrace.
2172 2172
2173gid= defines a group authorized to learn processes information otherwise2173gid= defines a group authorized to learn processes information otherwise
2174prohibited by hidepid=. If you use some daemon like identd which needs to learn2174prohibited by hidepid=. If you use some daemon like identd which needs to learn
@@ -2216,8 +2216,8 @@ creates a new procfs instance. Mount options affect own procfs instance. · 41 unmodified lines
2216It means that it became possible to have several procfs instances2216It means that it became possible to have several procfs instances
2217displaying tasks with different filtering options in one pid namespace.2217displaying tasks with different filtering options in one pid namespace.
2218 2218
2219# mount -o hidepid=2 -t proc proc /proc2219# mount -o hidepid=invisible -t proc proc /proc
2220# mount -o hidepid=1 -t proc proc /tmp/proc2220# mount -o hidepid=noaccess -t proc proc /tmp/proc
2221# grep ^proc /proc/mounts2221# grep ^proc /proc/mounts
2222proc /proc proc rw,relatime,hidepid=2 0 02222proc /proc proc rw,relatime,hidepid=invisible 0 0
2223proc /tmp/proc proc rw,relatime,hidepid=1 0 02223proc /tmp/proc proc rw,relatime,hidepid=noaccess 0 0
fs/proc/inode.c+14−1
@@ -24,6 +24,7 @@ · 23 unmodified lines
24#include <linux/seq_file.h>24#include <linux/seq_file.h>
25#include <linux/slab.h>25#include <linux/slab.h>
26#include <linux/mount.h>26#include <linux/mount.h>
27#include <linux/bug.h>
27 28
28#include <linux/uaccess.h>29#include <linux/uaccess.h>
29 30
@@ -165,6 +166,18 @@ void proc_invalidate_siblings_dcache(struct hlist_head *inodes, spinlock_t *lock · 135 unmodified lines
165 deactivate_super(old_sb);166 deactivate_super(old_sb);
166}167}
167 168
169static inline const char *hidepid2str(int v)
170{
171 switch (v) {
172 case HIDEPID_OFF: return "off";
173 case HIDEPID_NO_ACCESS: return "noaccess";
174 case HIDEPID_INVISIBLE: return "invisible";
175 case HIDEPID_NOT_PTRACEABLE: return "ptraceable";
176 }
177 WARN_ONCE(1, "bad hide_pid value: %d\n", v);
178 return "unknown";
179}
180
168static int proc_show_options(struct seq_file *seq, struct dentry *root)181static int proc_show_options(struct seq_file *seq, struct dentry *root)
169{182{
170 struct proc_fs_info *fs_info = proc_sb_info(root->d_sb);183 struct proc_fs_info *fs_info = proc_sb_info(root->d_sb);
@@ -172,7 +185,7 @@ static int proc_show_options(struct seq_file *seq, struct dentry *root) · 1 unmodified line
172 if (!gid_eq(fs_info->pid_gid, GLOBAL_ROOT_GID))185 if (!gid_eq(fs_info->pid_gid, GLOBAL_ROOT_GID))
173 seq_printf(seq, ",gid=%u", from_kgid_munged(&init_user_ns, fs_info->pid_gid));186 seq_printf(seq, ",gid=%u", from_kgid_munged(&init_user_ns, fs_info->pid_gid));
174 if (fs_info->hide_pid != HIDEPID_OFF)187 if (fs_info->hide_pid != HIDEPID_OFF)
175 seq_printf(seq, ",hidepid=%u", fs_info->hide_pid);188 seq_printf(seq, ",hidepid=%s", hidepid2str(fs_info->hide_pid));
176 if (fs_info->pidonly != PROC_PIDONLY_OFF)189 if (fs_info->pidonly != PROC_PIDONLY_OFF)
177 seq_printf(seq, ",subset=pid");190 seq_printf(seq, ",subset=pid");
178 191
fs/proc/root.c+34−4
@@ -45,7 +45,7 @@ enum proc_param { · 44 unmodified lines
45 45
46static const struct fs_parameter_spec proc_fs_parameters[] = {46static const struct fs_parameter_spec proc_fs_parameters[] = {
47 fsparam_u32("gid", Opt_gid),47 fsparam_u32("gid", Opt_gid),
48 fsparam_u32("hidepid", Opt_hidepid),48 fsparam_string("hidepid", Opt_hidepid),
49 fsparam_string("subset", Opt_subset),49 fsparam_string("subset", Opt_subset),
50 {}50 {}
51};51};
@@ -58,6 +58,37 @@ static inline int valid_hidepid(unsigned int value) · 6 unmodified lines
58 value == HIDEPID_NOT_PTRACEABLE);58 value == HIDEPID_NOT_PTRACEABLE);
59}59}
60 60
61static int proc_parse_hidepid_param(struct fs_context *fc, struct fs_parameter *param)
62{
63 struct proc_fs_context *ctx = fc->fs_private;
64 struct fs_parameter_spec hidepid_u32_spec = fsparam_u32("hidepid", Opt_hidepid);
65 struct fs_parse_result result;
66 int base = (unsigned long)hidepid_u32_spec.data;
67
68 if (param->type != fs_value_is_string)
69 return invalf(fc, "proc: unexpected type of hidepid value\n");
70
71 if (!kstrtouint(param->string, base, &result.uint_32)) {
72 if (!valid_hidepid(result.uint_32))
73 return invalf(fc, "proc: unknown value of hidepid - %s\n", param->string);
74 ctx->hidepid = result.uint_32;
75 return 0;
76 }
77
78 if (!strcmp(param->string, "off"))
79 ctx->hidepid = HIDEPID_OFF;
80 else if (!strcmp(param->string, "noaccess"))
81 ctx->hidepid = HIDEPID_NO_ACCESS;
82 else if (!strcmp(param->string, "invisible"))
83 ctx->hidepid = HIDEPID_INVISIBLE;
84 else if (!strcmp(param->string, "ptraceable"))
85 ctx->hidepid = HIDEPID_NOT_PTRACEABLE;
86 else
87 return invalf(fc, "proc: unknown value of hidepid - %s\n", param->string);
88
89 return 0;
90}
91
61static int proc_parse_subset_param(struct fs_context *fc, char *value)92static int proc_parse_subset_param(struct fs_context *fc, char *value)
62{93{
63 struct proc_fs_context *ctx = fc->fs_private;94 struct proc_fs_context *ctx = fc->fs_private;
@@ -97,9 +128,8 @@ static int proc_parse_param(struct fs_context *fc, struct fs_parameter *param) · 33 unmodified lines
97 break;128 break;
98 129
99 case Opt_hidepid:130 case Opt_hidepid:
100 if (!valid_hidepid(result.uint_32))131 if (proc_parse_hidepid_param(fc, param))
101 return invalf(fc, "proc: unknown value of hidepid.\n");132 return -EINVAL;
102 ctx->hidepid = result.uint_32;
103 break;133 break;
104 134
105 case Opt_subset:135 case Opt_subset:
tools/testing/selftests/proc/.gitignore+1−0
@@ -2,6 +2,7 @@ · 1 unmodified line
2/fd-001-lookup2/fd-001-lookup
3/fd-002-posix-eq3/fd-002-posix-eq
4/fd-003-kthread4/fd-003-kthread
5/proc-fsconfig-hidepid
5/proc-loadavg-0016/proc-loadavg-001
6/proc-multiple-procfs7/proc-multiple-procfs
7/proc-pid-vm8/proc-pid-vm
tools/testing/selftests/proc/Makefile+1−0
@@ -20,5 +20,6 @@ TEST_GEN_PROGS += setns-dcache · 19 unmodified lines
20TEST_GEN_PROGS += setns-sysvipc20TEST_GEN_PROGS += setns-sysvipc
21TEST_GEN_PROGS += thread-self21TEST_GEN_PROGS += thread-self
22TEST_GEN_PROGS += proc-multiple-procfs22TEST_GEN_PROGS += proc-multiple-procfs
23TEST_GEN_PROGS += proc-fsconfig-hidepid
23 24
24include ../lib.mk25include ../lib.mk
tools/testing/selftests/proc/proc-fsconfig-hidepid.c+50−0
@@ -0,0 +1,50 @@
1/*
2 * Copyright © 2020 Alexey Gladkov <gladkov.alexey@gmail.com>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16#include <assert.h>
17#include <unistd.h>
18#include <stdlib.h>
19#include <errno.h>
20#include <linux/mount.h>
21#include <linux/unistd.h>
22
23static inline int fsopen(const char *fsname, unsigned int flags)
24{
25 return syscall(__NR_fsopen, fsname, flags);
26}
27
28static inline int fsconfig(int fd, unsigned int cmd, const char *key, const void *val, int aux)
29{
30 return syscall(__NR_fsconfig, fd, cmd, key, val, aux);
31}
32
33int main(void)
34{
35 int fsfd, ret;
36 int hidepid = 2;
37
38 assert((fsfd = fsopen("proc", 0)) != -1);
39
40 ret = fsconfig(fsfd, FSCONFIG_SET_BINARY, "hidepid", &hidepid, 0);
41 assert(ret == -1);
42 assert(errno == EINVAL);
43
44 assert(!fsconfig(fsfd, FSCONFIG_SET_STRING, "hidepid", "2", 0));
45 assert(!fsconfig(fsfd, FSCONFIG_SET_STRING, "hidepid", "invisible", 0));
46
47 assert(!close(fsfd));
48
49 return 0;
50}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t