diff options
author | John Stultz <john.stultz@linaro.org> | 2016-10-07 20:02:26 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-07 21:46:30 -0400 |
commit | 7abbaf94049914f074306d960b0f968ffe52e59f (patch) | |
tree | 8b0166be20e0400467cd7441783ba7b34b32985b /fs/proc | |
parent | e16e2d8e14a14bd87df8482c637dde8f760a8d5f (diff) |
proc: relax /proc/<tid>/timerslack_ns capability requirements
When an interface to allow a task to change another tasks timerslack was
first proposed, it was suggested that something greater then
CAP_SYS_NICE would be needed, as a task could be delayed further then
what normally could be done with nice adjustments.
So CAP_SYS_PTRACE was adopted instead for what became the
/proc/<tid>/timerslack_ns interface. However, for Android (where this
feature originates), giving the system_server CAP_SYS_PTRACE would allow
it to observe and modify all tasks memory. This is considered too high
a privilege level for only needing to change the timerslack.
After some discussion, it was realized that a CAP_SYS_NICE process can
set a task as SCHED_FIFO, so they could fork some spinning processes and
set them all SCHED_FIFO 99, in effect delaying all other tasks for an
infinite amount of time.
So as a CAP_SYS_NICE task can already cause trouble for other tasks,
using it as a required capability for accessing and modifying
/proc/<tid>/timerslack_ns seems sufficient.
Thus, this patch loosens the capability requirements to CAP_SYS_NICE and
removes CAP_SYS_PTRACE, simplifying some of the code flow as well.
This is technically an ABI change, but as the feature just landed in
4.6, I suspect no one is yet using it.
Link: http://lkml.kernel.org/r/1469132667-17377-1-git-send-email-john.stultz@linaro.org
Signed-off-by: John Stultz <john.stultz@linaro.org>
Reviewed-by: Nick Kralevich <nnk@google.com>
Acked-by: Serge Hallyn <serge@hallyn.com>
Acked-by: Kees Cook <keescook@chromium.org>
Cc: Kees Cook <keescook@chromium.org>
Cc: "Serge E. Hallyn" <serge@hallyn.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Arjan van de Ven <arjan@linux.intel.com>
Cc: Oren Laadan <orenl@cellrox.com>
Cc: Ruchi Kandoi <kandoiruchi@google.com>
Cc: Rom Lemarchand <romlem@android.com>
Cc: Todd Kjos <tkjos@google.com>
Cc: Colin Cross <ccross@android.com>
Cc: Nick Kralevich <nnk@google.com>
Cc: Dmitry Shmidt <dimitrysh@google.com>
Cc: Elliott Hughes <enh@google.com>
Cc: Android Kernel Team <kernel-team@android.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/proc')
-rw-r--r-- | fs/proc/base.c | 34 |
1 files changed, 20 insertions, 14 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index 3b792ab3c0dc..248f008d46b8 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -2280,16 +2280,19 @@ static ssize_t timerslack_ns_write(struct file *file, const char __user *buf, | |||
2280 | if (!p) | 2280 | if (!p) |
2281 | return -ESRCH; | 2281 | return -ESRCH; |
2282 | 2282 | ||
2283 | if (ptrace_may_access(p, PTRACE_MODE_ATTACH_FSCREDS)) { | 2283 | if (!capable(CAP_SYS_NICE)) { |
2284 | task_lock(p); | ||
2285 | if (slack_ns == 0) | ||
2286 | p->timer_slack_ns = p->default_timer_slack_ns; | ||
2287 | else | ||
2288 | p->timer_slack_ns = slack_ns; | ||
2289 | task_unlock(p); | ||
2290 | } else | ||
2291 | count = -EPERM; | 2284 | count = -EPERM; |
2285 | goto out; | ||
2286 | } | ||
2292 | 2287 | ||
2288 | task_lock(p); | ||
2289 | if (slack_ns == 0) | ||
2290 | p->timer_slack_ns = p->default_timer_slack_ns; | ||
2291 | else | ||
2292 | p->timer_slack_ns = slack_ns; | ||
2293 | task_unlock(p); | ||
2294 | |||
2295 | out: | ||
2293 | put_task_struct(p); | 2296 | put_task_struct(p); |
2294 | 2297 | ||
2295 | return count; | 2298 | return count; |
@@ -2299,19 +2302,22 @@ static int timerslack_ns_show(struct seq_file *m, void *v) | |||
2299 | { | 2302 | { |
2300 | struct inode *inode = m->private; | 2303 | struct inode *inode = m->private; |
2301 | struct task_struct *p; | 2304 | struct task_struct *p; |
2302 | int err = 0; | 2305 | int err = 0; |
2303 | 2306 | ||
2304 | p = get_proc_task(inode); | 2307 | p = get_proc_task(inode); |
2305 | if (!p) | 2308 | if (!p) |
2306 | return -ESRCH; | 2309 | return -ESRCH; |
2307 | 2310 | ||
2308 | if (ptrace_may_access(p, PTRACE_MODE_ATTACH_FSCREDS)) { | 2311 | if (!capable(CAP_SYS_NICE)) { |
2309 | task_lock(p); | ||
2310 | seq_printf(m, "%llu\n", p->timer_slack_ns); | ||
2311 | task_unlock(p); | ||
2312 | } else | ||
2313 | err = -EPERM; | 2312 | err = -EPERM; |
2313 | goto out; | ||
2314 | } | ||
2314 | 2315 | ||
2316 | task_lock(p); | ||
2317 | seq_printf(m, "%llu\n", p->timer_slack_ns); | ||
2318 | task_unlock(p); | ||
2319 | |||
2320 | out: | ||
2315 | put_task_struct(p); | 2321 | put_task_struct(p); |
2316 | 2322 | ||
2317 | return err; | 2323 | return err; |