From: Daniel J Blueman on
Calling waitid [1] on a stopped process results in access to the
task's credentials without the RCU read lock, which may change in the
meantime, eliciting a warning [2].

This is fixed by:

Ensure the task's credentials don't change before calling
wait_noreap_copyout via acquisition of the RCU read lock.

Signed-off-by: Daniel J Blueman <daniel.blueman(a)gmail.com>

diff --git a/kernel/exit.c b/kernel/exit.c
index ceffc67..cc8b4b9 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -1457,6 +1457,7 @@ static int wait_task_continued(struct wait_opts
*wo, struct task_struct *p)
}
if (!unlikely(wo->wo_flags & WNOWAIT))
p->signal->flags &= ~SIGNAL_STOP_CONTINUED;
+ rcu_read_lock();
uid = __task_cred(p)->uid;
spin_unlock_irq(&p->sighand->siglock);

@@ -1477,6 +1478,7 @@ static int wait_task_continued(struct wait_opts
*wo, struct task_struct *p)
CLD_CONTINUED, SIGCONT);
BUG_ON(retval == 0);
}
+ rcu_read_unlock();

return retval;
}

--- [1]

#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(void) {
id_t id;
siginfo_t infop;
pid_t res;

id = fork();
if (id == 0) {
sleep(1);
exit(0);
}

kill(id, SIGSTOP);
alarm(1);

res = waitid(P_PID, id, &infop, WCONTINUED);

return 0;
}

--- [2]

===================================================
[ INFO: suspicious rcu_dereference_check() usage. ]
---------------------------------------------------
kernel/exit.c:1460 invoked rcu_dereference_check() without protection!

other info that might help us debug this:

rcu_scheduler_active = 1, debug_locks = 1
2 locks held by waitid02/22252:
#0: (tasklist_lock){.?.?..}, at: [<ffffffff81061ce5>] do_wait+0xc5/0x310
#1: (&(&sighand->siglock)->rlock){-.-...}, at: [<ffffffff810611da>]
wait_consider_task+0x19a/0xbe0

stack backtrace:
Pid: 22252, comm: waitid02 Not tainted 2.6.35-323cd+ #3
Call Trace:
[<ffffffff81095da4>] lockdep_rcu_dereference+0xa4/0xc0
[<ffffffff81061b31>] wait_consider_task+0xaf1/0xbe0
[<ffffffff81061d15>] do_wait+0xf5/0x310
[<ffffffff810620b6>] sys_waitid+0x86/0x1f0
[<ffffffff8105fce0>] ? child_wait_callback+0x0/0x70
[<ffffffff81003282>] system_call_fastpath+0x16/0x1b
--
Daniel J Blueman
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/