diff options
Diffstat (limited to 'kernel/signal.c')
-rw-r--r-- | kernel/signal.c | 50 |
1 files changed, 25 insertions, 25 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index a4077e90f19f..8f0876f9f6dd 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -1263,6 +1263,10 @@ struct sighand_struct *__lock_task_sighand(struct task_struct *tsk, | |||
1263 | struct sighand_struct *sighand; | 1263 | struct sighand_struct *sighand; |
1264 | 1264 | ||
1265 | for (;;) { | 1265 | for (;;) { |
1266 | /* | ||
1267 | * Disable interrupts early to avoid deadlocks. | ||
1268 | * See rcu_read_unlock() comment header for details. | ||
1269 | */ | ||
1266 | local_irq_save(*flags); | 1270 | local_irq_save(*flags); |
1267 | rcu_read_lock(); | 1271 | rcu_read_lock(); |
1268 | sighand = rcu_dereference(tsk->sighand); | 1272 | sighand = rcu_dereference(tsk->sighand); |
@@ -2166,8 +2170,7 @@ static int ptrace_signal(int signr, siginfo_t *info) | |||
2166 | return signr; | 2170 | return signr; |
2167 | } | 2171 | } |
2168 | 2172 | ||
2169 | int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, | 2173 | int get_signal(struct ksignal *ksig) |
2170 | struct pt_regs *regs, void *cookie) | ||
2171 | { | 2174 | { |
2172 | struct sighand_struct *sighand = current->sighand; | 2175 | struct sighand_struct *sighand = current->sighand; |
2173 | struct signal_struct *signal = current->signal; | 2176 | struct signal_struct *signal = current->signal; |
@@ -2237,13 +2240,13 @@ relock: | |||
2237 | goto relock; | 2240 | goto relock; |
2238 | } | 2241 | } |
2239 | 2242 | ||
2240 | signr = dequeue_signal(current, ¤t->blocked, info); | 2243 | signr = dequeue_signal(current, ¤t->blocked, &ksig->info); |
2241 | 2244 | ||
2242 | if (!signr) | 2245 | if (!signr) |
2243 | break; /* will return 0 */ | 2246 | break; /* will return 0 */ |
2244 | 2247 | ||
2245 | if (unlikely(current->ptrace) && signr != SIGKILL) { | 2248 | if (unlikely(current->ptrace) && signr != SIGKILL) { |
2246 | signr = ptrace_signal(signr, info); | 2249 | signr = ptrace_signal(signr, &ksig->info); |
2247 | if (!signr) | 2250 | if (!signr) |
2248 | continue; | 2251 | continue; |
2249 | } | 2252 | } |
@@ -2251,13 +2254,13 @@ relock: | |||
2251 | ka = &sighand->action[signr-1]; | 2254 | ka = &sighand->action[signr-1]; |
2252 | 2255 | ||
2253 | /* Trace actually delivered signals. */ | 2256 | /* Trace actually delivered signals. */ |
2254 | trace_signal_deliver(signr, info, ka); | 2257 | trace_signal_deliver(signr, &ksig->info, ka); |
2255 | 2258 | ||
2256 | if (ka->sa.sa_handler == SIG_IGN) /* Do nothing. */ | 2259 | if (ka->sa.sa_handler == SIG_IGN) /* Do nothing. */ |
2257 | continue; | 2260 | continue; |
2258 | if (ka->sa.sa_handler != SIG_DFL) { | 2261 | if (ka->sa.sa_handler != SIG_DFL) { |
2259 | /* Run the handler. */ | 2262 | /* Run the handler. */ |
2260 | *return_ka = *ka; | 2263 | ksig->ka = *ka; |
2261 | 2264 | ||
2262 | if (ka->sa.sa_flags & SA_ONESHOT) | 2265 | if (ka->sa.sa_flags & SA_ONESHOT) |
2263 | ka->sa.sa_handler = SIG_DFL; | 2266 | ka->sa.sa_handler = SIG_DFL; |
@@ -2307,7 +2310,7 @@ relock: | |||
2307 | spin_lock_irq(&sighand->siglock); | 2310 | spin_lock_irq(&sighand->siglock); |
2308 | } | 2311 | } |
2309 | 2312 | ||
2310 | if (likely(do_signal_stop(info->si_signo))) { | 2313 | if (likely(do_signal_stop(ksig->info.si_signo))) { |
2311 | /* It released the siglock. */ | 2314 | /* It released the siglock. */ |
2312 | goto relock; | 2315 | goto relock; |
2313 | } | 2316 | } |
@@ -2328,7 +2331,7 @@ relock: | |||
2328 | 2331 | ||
2329 | if (sig_kernel_coredump(signr)) { | 2332 | if (sig_kernel_coredump(signr)) { |
2330 | if (print_fatal_signals) | 2333 | if (print_fatal_signals) |
2331 | print_fatal_signal(info->si_signo); | 2334 | print_fatal_signal(ksig->info.si_signo); |
2332 | proc_coredump_connector(current); | 2335 | proc_coredump_connector(current); |
2333 | /* | 2336 | /* |
2334 | * If it was able to dump core, this kills all | 2337 | * If it was able to dump core, this kills all |
@@ -2338,34 +2341,32 @@ relock: | |||
2338 | * first and our do_group_exit call below will use | 2341 | * first and our do_group_exit call below will use |
2339 | * that value and ignore the one we pass it. | 2342 | * that value and ignore the one we pass it. |
2340 | */ | 2343 | */ |
2341 | do_coredump(info); | 2344 | do_coredump(&ksig->info); |
2342 | } | 2345 | } |
2343 | 2346 | ||
2344 | /* | 2347 | /* |
2345 | * Death signals, no core dump. | 2348 | * Death signals, no core dump. |
2346 | */ | 2349 | */ |
2347 | do_group_exit(info->si_signo); | 2350 | do_group_exit(ksig->info.si_signo); |
2348 | /* NOTREACHED */ | 2351 | /* NOTREACHED */ |
2349 | } | 2352 | } |
2350 | spin_unlock_irq(&sighand->siglock); | 2353 | spin_unlock_irq(&sighand->siglock); |
2351 | return signr; | 2354 | |
2355 | ksig->sig = signr; | ||
2356 | return ksig->sig > 0; | ||
2352 | } | 2357 | } |
2353 | 2358 | ||
2354 | /** | 2359 | /** |
2355 | * signal_delivered - | 2360 | * signal_delivered - |
2356 | * @sig: number of signal being delivered | 2361 | * @ksig: kernel signal struct |
2357 | * @info: siginfo_t of signal being delivered | ||
2358 | * @ka: sigaction setting that chose the handler | ||
2359 | * @regs: user register state | ||
2360 | * @stepping: nonzero if debugger single-step or block-step in use | 2362 | * @stepping: nonzero if debugger single-step or block-step in use |
2361 | * | 2363 | * |
2362 | * This function should be called when a signal has successfully been | 2364 | * This function should be called when a signal has successfully been |
2363 | * delivered. It updates the blocked signals accordingly (@ka->sa.sa_mask | 2365 | * delivered. It updates the blocked signals accordingly (@ksig->ka.sa.sa_mask |
2364 | * is always blocked, and the signal itself is blocked unless %SA_NODEFER | 2366 | * is always blocked, and the signal itself is blocked unless %SA_NODEFER |
2365 | * is set in @ka->sa.sa_flags. Tracing is notified. | 2367 | * is set in @ksig->ka.sa.sa_flags. Tracing is notified. |
2366 | */ | 2368 | */ |
2367 | void signal_delivered(int sig, siginfo_t *info, struct k_sigaction *ka, | 2369 | static void signal_delivered(struct ksignal *ksig, int stepping) |
2368 | struct pt_regs *regs, int stepping) | ||
2369 | { | 2370 | { |
2370 | sigset_t blocked; | 2371 | sigset_t blocked; |
2371 | 2372 | ||
@@ -2375,11 +2376,11 @@ void signal_delivered(int sig, siginfo_t *info, struct k_sigaction *ka, | |||
2375 | simply clear the restore sigmask flag. */ | 2376 | simply clear the restore sigmask flag. */ |
2376 | clear_restore_sigmask(); | 2377 | clear_restore_sigmask(); |
2377 | 2378 | ||
2378 | sigorsets(&blocked, ¤t->blocked, &ka->sa.sa_mask); | 2379 | sigorsets(&blocked, ¤t->blocked, &ksig->ka.sa.sa_mask); |
2379 | if (!(ka->sa.sa_flags & SA_NODEFER)) | 2380 | if (!(ksig->ka.sa.sa_flags & SA_NODEFER)) |
2380 | sigaddset(&blocked, sig); | 2381 | sigaddset(&blocked, ksig->sig); |
2381 | set_current_blocked(&blocked); | 2382 | set_current_blocked(&blocked); |
2382 | tracehook_signal_handler(sig, info, ka, regs, stepping); | 2383 | tracehook_signal_handler(stepping); |
2383 | } | 2384 | } |
2384 | 2385 | ||
2385 | void signal_setup_done(int failed, struct ksignal *ksig, int stepping) | 2386 | void signal_setup_done(int failed, struct ksignal *ksig, int stepping) |
@@ -2387,8 +2388,7 @@ void signal_setup_done(int failed, struct ksignal *ksig, int stepping) | |||
2387 | if (failed) | 2388 | if (failed) |
2388 | force_sigsegv(ksig->sig, current); | 2389 | force_sigsegv(ksig->sig, current); |
2389 | else | 2390 | else |
2390 | signal_delivered(ksig->sig, &ksig->info, &ksig->ka, | 2391 | signal_delivered(ksig, stepping); |
2391 | signal_pt_regs(), stepping); | ||
2392 | } | 2392 | } |
2393 | 2393 | ||
2394 | /* | 2394 | /* |