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: [<
ffffffff8130e548>] seq_read+0xc8/0x820
#1: (&(&p->alloc_lock)->rlock){+.+...}, at: [<
ffffffff810c5f77>] 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:
[<
ffffffff815e3176>] dump_stack+0x86/0xc0
[<
ffffffff8112decf>] lockdep_rcu_suspicious+0x11f/0x130
[<
ffffffff810c516c>] ___ptrace_may_access+0x6c/0x560
[<
ffffffff810c5f8b>] ptrace_may_access+0x3b/0x60
[<
ffffffff8138f7d9>] do_task_stat+0x129/0xef0
...
Orabug:
27344012
CVE:CVE-2017-5715
Signed-off-by: Jamie Iles <jamie.iles@oracle.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Signed-off-by: Brian Maly <brian.maly@oracle.com>
Signed-off-by: Kirtikar Kashyap <kirtikar.kashyap@oracle.com>
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;
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;