diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/signal.c | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index b3dedf1f932..13371d17358 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
| @@ -2219,6 +2219,7 @@ static int do_tkill(int tgid, int pid, int sig) | |||
| 2219 | int error; | 2219 | int error; |
| 2220 | struct siginfo info; | 2220 | struct siginfo info; |
| 2221 | struct task_struct *p; | 2221 | struct task_struct *p; |
| 2222 | unsigned long flags; | ||
| 2222 | 2223 | ||
| 2223 | error = -ESRCH; | 2224 | error = -ESRCH; |
| 2224 | info.si_signo = sig; | 2225 | info.si_signo = sig; |
| @@ -2227,21 +2228,24 @@ static int do_tkill(int tgid, int pid, int sig) | |||
| 2227 | info.si_pid = task_tgid_vnr(current); | 2228 | info.si_pid = task_tgid_vnr(current); |
| 2228 | info.si_uid = current->uid; | 2229 | info.si_uid = current->uid; |
| 2229 | 2230 | ||
| 2230 | read_lock(&tasklist_lock); | 2231 | rcu_read_lock(); |
| 2231 | p = find_task_by_vpid(pid); | 2232 | p = find_task_by_vpid(pid); |
| 2232 | if (p && (tgid <= 0 || task_tgid_vnr(p) == tgid)) { | 2233 | if (p && (tgid <= 0 || task_tgid_vnr(p) == tgid)) { |
| 2233 | error = check_kill_permission(sig, &info, p); | 2234 | error = check_kill_permission(sig, &info, p); |
| 2234 | /* | 2235 | /* |
| 2235 | * The null signal is a permissions and process existence | 2236 | * The null signal is a permissions and process existence |
| 2236 | * probe. No signal is actually delivered. | 2237 | * probe. No signal is actually delivered. |
| 2238 | * | ||
| 2239 | * If lock_task_sighand() fails we pretend the task dies | ||
| 2240 | * after receiving the signal. The window is tiny, and the | ||
| 2241 | * signal is private anyway. | ||
| 2237 | */ | 2242 | */ |
| 2238 | if (!error && sig && p->sighand) { | 2243 | if (!error && sig && lock_task_sighand(p, &flags)) { |
| 2239 | spin_lock_irq(&p->sighand->siglock); | ||
| 2240 | error = specific_send_sig_info(sig, &info, p); | 2244 | error = specific_send_sig_info(sig, &info, p); |
| 2241 | spin_unlock_irq(&p->sighand->siglock); | 2245 | unlock_task_sighand(p, &flags); |
| 2242 | } | 2246 | } |
| 2243 | } | 2247 | } |
| 2244 | read_unlock(&tasklist_lock); | 2248 | rcu_read_unlock(); |
| 2245 | 2249 | ||
| 2246 | return error; | 2250 | return error; |
| 2247 | } | 2251 | } |
