diff options
author | Vasiliy Kulikov <segooon@gmail.com> | 2012-01-10 18:11:31 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-10 19:30:54 -0500 |
commit | 0499680a42141d86417a8fbaa8c8db806bea1201 (patch) | |
tree | eb2aeb559bf5418476319aa81fa4f6ed3659bbc0 /fs/proc/root.c | |
parent | 97412950b10e64f347aec4a9b759395c2465adf6 (diff) |
procfs: add hidepid= and gid= mount options
Add support for mount options to restrict access to /proc/PID/
directories. The default backward-compatible "relaxed" behaviour is left
untouched.
The first mount option is called "hidepid" and its value defines how much
info about processes we want to be available for non-owners:
hidepid=0 (default) means the old behavior - anybody may read all
world-readable /proc/PID/* files.
hidepid=1 means users may not access any /proc/<pid>/ directories, but
their own. Sensitive files like cmdline, sched*, status are now protected
against other users. As permission checking done in proc_pid_permission()
and files' permissions are left untouched, programs expecting specific
files' modes are not confused.
hidepid=2 means hidepid=1 plus all /proc/PID/ will be invisible to other
users. It doesn't mean that it hides whether a process exists (it can be
learned by other means, e.g. by kill -0 $PID), but it hides process' euid
and egid. It compicates intruder's task of gathering info about running
processes, whether some daemon runs with elevated privileges, whether
another user runs some sensitive program, whether other users run any
program at all, etc.
gid=XXX defines a group that will be able to gather all processes' info
(as in hidepid=0 mode). This group should be used instead of putting
nonroot user in sudoers file or something. However, untrusted users (like
daemons, etc.) which are not supposed to monitor the tasks in the whole
system should not be added to the group.
hidepid=1 or higher is designed to restrict access to procfs files, which
might reveal some sensitive private information like precise keystrokes
timings:
http://www.openwall.com/lists/oss-security/2011/11/05/3
hidepid=1/2 doesn't break monitoring userspace tools. ps, top, pgrep, and
conky gracefully handle EPERM/ENOENT and behave as if the current user is
the only user running processes. pstree shows the process subtree which
contains "pstree" process.
Note: the patch doesn't deal with setuid/setgid issues of keeping
preopened descriptors of procfs files (like
https://lkml.org/lkml/2011/2/7/368). We rely on that the leaked
information like the scheduling counters of setuid apps doesn't threaten
anybody's privacy - only the user started the setuid program may read the
counters.
Signed-off-by: Vasiliy Kulikov <segoon@openwall.com>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Randy Dunlap <rdunlap@xenotime.net>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Greg KH <greg@kroah.com>
Cc: Theodore Tso <tytso@MIT.EDU>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: James Morris <jmorris@namei.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Hugh Dickins <hughd@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/proc/root.c')
-rw-r--r-- | fs/proc/root.c | 21 |
1 files changed, 18 insertions, 3 deletions
diff --git a/fs/proc/root.c b/fs/proc/root.c index 6a8ac1d361a9..46a15d8a29ca 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c | |||
@@ -38,10 +38,12 @@ static int proc_set_super(struct super_block *sb, void *data) | |||
38 | } | 38 | } |
39 | 39 | ||
40 | enum { | 40 | enum { |
41 | Opt_err, | 41 | Opt_gid, Opt_hidepid, Opt_err, |
42 | }; | 42 | }; |
43 | 43 | ||
44 | static const match_table_t tokens = { | 44 | static const match_table_t tokens = { |
45 | {Opt_hidepid, "hidepid=%u"}, | ||
46 | {Opt_gid, "gid=%u"}, | ||
45 | {Opt_err, NULL}, | 47 | {Opt_err, NULL}, |
46 | }; | 48 | }; |
47 | 49 | ||
@@ -49,8 +51,7 @@ static int proc_parse_options(char *options, struct pid_namespace *pid) | |||
49 | { | 51 | { |
50 | char *p; | 52 | char *p; |
51 | substring_t args[MAX_OPT_ARGS]; | 53 | substring_t args[MAX_OPT_ARGS]; |
52 | 54 | int option; | |
53 | pr_debug("proc: options = %s\n", options); | ||
54 | 55 | ||
55 | if (!options) | 56 | if (!options) |
56 | return 1; | 57 | return 1; |
@@ -63,6 +64,20 @@ static int proc_parse_options(char *options, struct pid_namespace *pid) | |||
63 | args[0].to = args[0].from = 0; | 64 | args[0].to = args[0].from = 0; |
64 | token = match_token(p, tokens, args); | 65 | token = match_token(p, tokens, args); |
65 | switch (token) { | 66 | switch (token) { |
67 | case Opt_gid: | ||
68 | if (match_int(&args[0], &option)) | ||
69 | return 0; | ||
70 | pid->pid_gid = option; | ||
71 | break; | ||
72 | case Opt_hidepid: | ||
73 | if (match_int(&args[0], &option)) | ||
74 | return 0; | ||
75 | if (option < 0 || option > 2) { | ||
76 | pr_err("proc: hidepid value must be between 0 and 2.\n"); | ||
77 | return 0; | ||
78 | } | ||
79 | pid->hide_pid = option; | ||
80 | break; | ||
66 | default: | 81 | default: |
67 | pr_err("proc: unrecognized mount option \"%s\" " | 82 | pr_err("proc: unrecognized mount option \"%s\" " |
68 | "or missing value\n", p); | 83 | "or missing value\n", p); |