Messages in this thread | | | Date | Thu, 10 Dec 2009 16:11:21 +0100 | From | Oleg Nesterov <> | Subject | Re: [patch 6/9] signal: Fix racy access to __task_cred in kill_pid_info_as_uid() |
| |
On 12/10, Thomas Gleixner wrote: > > 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> > Cc: Oleg Nesterov <oleg@redhat.com> > --- > kernel/signal.c | 17 ++++++++++------- > 1 file changed, 10 insertions(+), 7 deletions(-)
Acked-by: Oleg Nesterov <oleg@redhat.com>
> Index: linux-2.6-tip/kernel/signal.c > =================================================================== > --- linux-2.6-tip.orig/kernel/signal.c > +++ linux-2.6-tip/kernel/signal.c > @@ -1175,11 +1175,12 @@ int kill_pid_info_as_uid(int sig, struct > 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; > @@ -1196,14 +1197,16 @@ int kill_pid_info_as_uid(int sig, struct > 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); > >
| |