|
@@ -218,13 +218,13 @@ __sigqueue_alloc(int sig, struct task_struct *t, gfp_t flags, int override_rlimi
|
|
|
struct user_struct *user;
|
|
|
|
|
|
/*
|
|
|
- * We won't get problems with the target's UID changing under us
|
|
|
- * because changing it requires RCU be used, and if t != current, the
|
|
|
- * caller must be holding the RCU readlock (by way of a spinlock) and
|
|
|
- * we use RCU protection here
|
|
|
+ * Protect access to @t credentials. This can go away when all
|
|
|
+ * callers hold rcu read lock.
|
|
|
*/
|
|
|
+ rcu_read_lock();
|
|
|
user = get_uid(__task_cred(t)->user);
|
|
|
atomic_inc(&user->sigpending);
|
|
|
+ rcu_read_unlock();
|
|
|
|
|
|
if (override_rlimit ||
|
|
|
atomic_read(&user->sigpending) <=
|
|
@@ -1179,11 +1179,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;
|
|
@@ -1199,14 +1200,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);
|