aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/kernel/signal.c
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>2005-06-23 03:08:37 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-23 12:45:13 -0400
commit0928d6ef7f204979749fb241a90a04a35dae133a (patch)
treef91a3a4725a2e59ed3cfce4cabd31f61798b9342 /arch/x86_64/kernel/signal.c
parenta3a00751ad8970c13d0563c2e92ee68c655a8e6b (diff)
[PATCH] x86_64: never block forced SIGSEGV
This is the x86_64 version of the signal fix I just posted for i386. This problem was first noticed on PPC and has already been fixed there. But the exact same issue applies to other platforms in the same way. The signal blocking for sa_mask and the handled signal takes place after the handler setup. When the stack is bogus, the handler setup forces a SIGSEGV. But then this will be blocked, and returning to user mode will fault again and iterate. This patch fixes the problem by checking whether signal handler setup failed, and not doing the signal-blocking if so. This copies what was done in the ppc code. I think all architectures' signal handler setup code follows this pattern and needs the change. Signed-off-by: Roland McGrath <roland@redhat.com> Cc: Andi Kleen <ak@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/x86_64/kernel/signal.c')
-rw-r--r--arch/x86_64/kernel/signal.c26
1 files changed, 15 insertions, 11 deletions
diff --git a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c
index 429c0269dc4e..3c5f30893715 100644
--- a/arch/x86_64/kernel/signal.c
+++ b/arch/x86_64/kernel/signal.c
@@ -34,9 +34,9 @@
34 34
35#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 35#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
36 36
37void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, 37int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
38 sigset_t *set, struct pt_regs * regs); 38 sigset_t *set, struct pt_regs * regs);
39void ia32_setup_frame(int sig, struct k_sigaction *ka, 39int ia32_setup_frame(int sig, struct k_sigaction *ka,
40 sigset_t *set, struct pt_regs * regs); 40 sigset_t *set, struct pt_regs * regs);
41 41
42asmlinkage long 42asmlinkage long
@@ -238,7 +238,7 @@ get_stack(struct k_sigaction *ka, struct pt_regs *regs, unsigned long size)
238 return (void __user *)round_down(rsp - size, 16); 238 return (void __user *)round_down(rsp - size, 16);
239} 239}
240 240
241static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, 241static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
242 sigset_t *set, struct pt_regs * regs) 242 sigset_t *set, struct pt_regs * regs)
243{ 243{
244 struct rt_sigframe __user *frame; 244 struct rt_sigframe __user *frame;
@@ -327,20 +327,23 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
327 current->comm, current->pid, frame, regs->rip, frame->pretcode); 327 current->comm, current->pid, frame, regs->rip, frame->pretcode);
328#endif 328#endif
329 329
330 return; 330 return 1;
331 331
332give_sigsegv: 332give_sigsegv:
333 force_sigsegv(sig, current); 333 force_sigsegv(sig, current);
334 return 0;
334} 335}
335 336
336/* 337/*
337 * OK, we're invoking a handler 338 * OK, we're invoking a handler
338 */ 339 */
339 340
340static void 341static int
341handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, 342handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
342 sigset_t *oldset, struct pt_regs *regs) 343 sigset_t *oldset, struct pt_regs *regs)
343{ 344{
345 int ret;
346
344#ifdef DEBUG_SIG 347#ifdef DEBUG_SIG
345 printk("handle_signal pid:%d sig:%lu rip:%lx rsp:%lx regs=%p\n", 348 printk("handle_signal pid:%d sig:%lu rip:%lx rsp:%lx regs=%p\n",
346 current->pid, sig, 349 current->pid, sig,
@@ -384,20 +387,22 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
384#ifdef CONFIG_IA32_EMULATION 387#ifdef CONFIG_IA32_EMULATION
385 if (test_thread_flag(TIF_IA32)) { 388 if (test_thread_flag(TIF_IA32)) {
386 if (ka->sa.sa_flags & SA_SIGINFO) 389 if (ka->sa.sa_flags & SA_SIGINFO)
387 ia32_setup_rt_frame(sig, ka, info, oldset, regs); 390 ret = ia32_setup_rt_frame(sig, ka, info, oldset, regs);
388 else 391 else
389 ia32_setup_frame(sig, ka, oldset, regs); 392 ret = ia32_setup_frame(sig, ka, oldset, regs);
390 } else 393 } else
391#endif 394#endif
392 setup_rt_frame(sig, ka, info, oldset, regs); 395 ret = setup_rt_frame(sig, ka, info, oldset, regs);
393 396
394 if (!(ka->sa.sa_flags & SA_NODEFER)) { 397 if (ret && !(ka->sa.sa_flags & SA_NODEFER)) {
395 spin_lock_irq(&current->sighand->siglock); 398 spin_lock_irq(&current->sighand->siglock);
396 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask); 399 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
397 sigaddset(&current->blocked,sig); 400 sigaddset(&current->blocked,sig);
398 recalc_sigpending(); 401 recalc_sigpending();
399 spin_unlock_irq(&current->sighand->siglock); 402 spin_unlock_irq(&current->sighand->siglock);
400 } 403 }
404
405 return ret;
401} 406}
402 407
403/* 408/*
@@ -437,8 +442,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
437 asm volatile("movq %0,%%db7" : : "r" (current->thread.debugreg7)); 442 asm volatile("movq %0,%%db7" : : "r" (current->thread.debugreg7));
438 443
439 /* Whee! Actually deliver the signal. */ 444 /* Whee! Actually deliver the signal. */
440 handle_signal(signr, &info, &ka, oldset, regs); 445 return handle_signal(signr, &info, &ka, oldset, regs);
441 return 1;
442 } 446 }
443 447
444 no_signal: 448 no_signal: