From 211574750851ff2c1e22ea39616d6758cbb1c0ab Mon Sep 17 00:00:00 2001 From: Jamie Iles Date: Tue, 9 Jan 2018 12:13:23 +0000 Subject: [PATCH] ptrace: remove unlocked RCU dereference. Commit 02bc4c7f77877 (x86/mm: Only set IBPB when the new thread cannot ptrace current thread) reworked ___ptrace_may_access to take an arbitrary task, but getting the task credentials needs to be done inside an RCU critical section. Move the dereference into the rcu_read_lock() below, preventing a boot splat like: =============================== [ INFO: suspicious RCU usage. ] 4.1.12+ #89 Not tainted ------------------------------- kernel/ptrace.c:224 suspicious rcu_dereference_check() usage! other info that might help us debug this: rcu_scheduler_active = 1, debug_locks = 0 2 locks held by systemd/1: #0: (&p->lock){+.+.+.}, at: [] seq_read+0xc8/0x820 #1: (&(&p->alloc_lock)->rlock){+.+...}, at: [] ptrace_may_access+0x27/0x60 stack backtrace: CPU: 0 PID: 1 Comm: systemd Not tainted 4.1.12+ #89 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.1-1ubuntu1 04/01/2014 ffffffff81c42760 ffff8801194577e8 ffffffff815e3176 ffff880119448000 0000000000000001 ffff880119457818 ffffffff8112decf ffff880119448000 000000000000000d ffff880119448000 ffff8800bb8d8a00 ffff880119457868 Call Trace: [] dump_stack+0x86/0xc0 [] lockdep_rcu_suspicious+0x11f/0x130 [] ___ptrace_may_access+0x6c/0x560 [] ptrace_may_access+0x3b/0x60 [] do_task_stat+0x129/0xef0 ... Orabug: 27344012 CVE:CVE-2017-5715 Signed-off-by: Jamie Iles Signed-off-by: Konrad Rzeszutek Wilk Reviewed-by: Daniel Kiper Signed-off-by: Brian Maly Signed-off-by: Kirtikar Kashyap --- kernel/ptrace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/ptrace.c b/kernel/ptrace.c index b776ee197cc0..15042d8e832f 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -221,7 +221,7 @@ static int ptrace_has_cap(struct user_namespace *ns, unsigned int mode) int ___ptrace_may_access(struct task_struct *cur, struct task_struct *task, unsigned int mode) { - const struct cred *cred = __task_cred(cur), *tcred; + const struct cred *cred, *tcred; int dumpable = 0; kuid_t caller_uid; kgid_t caller_gid; @@ -244,6 +244,7 @@ int ___ptrace_may_access(struct task_struct *cur, struct task_struct *task, if (same_thread_group(task, cur)) return 0; rcu_read_lock(); + cred = __task_cred(cur); if (mode & PTRACE_MODE_FSCREDS) { caller_uid = cred->fsuid; caller_gid = cred->fsgid; -- 2.50.1