Skip to content

Commit

Permalink
signal: Fix racy access to __task_cred in kill_pid_info_as_uid()
Browse files Browse the repository at this point in the history
kill_pid_info_as_uid() accesses __task_cred() without being in a RCU
read side critical section. tasklist_lock is not protecting that when
CONFIG_TREE_PREEMPT_RCU=y.

Convert the whole tasklist_lock section to rcu and use
lock_task_sighand to prevent the exit race.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
LKML-Reference: <20091210004703.232302055@linutronix.de>
Acked-by: Oleg Nesterov <oleg@redhat.com>
  • Loading branch information
Thomas Gleixner committed Dec 10, 2009
1 parent ea5b41f commit 14d8c9f
Showing 1 changed file with 10 additions and 7 deletions.
17 changes: 10 additions & 7 deletions kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -1175,11 +1175,12 @@ int kill_pid_info_as_uid(int sig, struct siginfo *info, struct pid *pid,
int ret = -EINVAL;
struct task_struct *p;
const struct cred *pcred;
unsigned long flags;

if (!valid_signal(sig))
return ret;

read_lock(&tasklist_lock);
rcu_read_lock();
p = pid_task(pid, PIDTYPE_PID);
if (!p) {
ret = -ESRCH;
Expand All @@ -1196,14 +1197,16 @@ int kill_pid_info_as_uid(int sig, struct siginfo *info, struct pid *pid,
ret = security_task_kill(p, info, sig, secid);
if (ret)
goto out_unlock;
if (sig && p->sighand) {
unsigned long flags;
spin_lock_irqsave(&p->sighand->siglock, flags);
ret = __send_signal(sig, info, p, 1, 0);
spin_unlock_irqrestore(&p->sighand->siglock, flags);

if (sig) {
if (lock_task_sighand(p, &flags)) {
ret = __send_signal(sig, info, p, 1, 0);
unlock_task_sighand(p, &flags);
} else
ret = -ESRCH;
}
out_unlock:
read_unlock(&tasklist_lock);
rcu_read_unlock();
return ret;
}
EXPORT_SYMBOL_GPL(kill_pid_info_as_uid);
Expand Down

0 comments on commit 14d8c9f

Please sign in to comment.