aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/signal_64.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/signal_64.c')
-rw-r--r--arch/x86/kernel/signal_64.c50
1 files changed, 15 insertions, 35 deletions
diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c
index 162da796a323..694aa888bb19 100644
--- a/arch/x86/kernel/signal_64.c
+++ b/arch/x86/kernel/signal_64.c
@@ -15,6 +15,7 @@
15#include <linux/errno.h> 15#include <linux/errno.h>
16#include <linux/wait.h> 16#include <linux/wait.h>
17#include <linux/ptrace.h> 17#include <linux/ptrace.h>
18#include <linux/tracehook.h>
18#include <linux/unistd.h> 19#include <linux/unistd.h>
19#include <linux/stddef.h> 20#include <linux/stddef.h>
20#include <linux/personality.h> 21#include <linux/personality.h>
@@ -27,6 +28,8 @@
27#include <asm/proto.h> 28#include <asm/proto.h>
28#include <asm/ia32_unistd.h> 29#include <asm/ia32_unistd.h>
29#include <asm/mce.h> 30#include <asm/mce.h>
31#include <asm/syscall.h>
32#include <asm/syscalls.h>
30#include "sigframe.h" 33#include "sigframe.h"
31 34
32#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 35#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
@@ -352,35 +355,6 @@ give_sigsegv:
352} 355}
353 356
354/* 357/*
355 * Return -1L or the syscall number that @regs is executing.
356 */
357static long current_syscall(struct pt_regs *regs)
358{
359 /*
360 * We always sign-extend a -1 value being set here,
361 * so this is always either -1L or a syscall number.
362 */
363 return regs->orig_ax;
364}
365
366/*
367 * Return a value that is -EFOO if the system call in @regs->orig_ax
368 * returned an error. This only works for @regs from @current.
369 */
370static long current_syscall_ret(struct pt_regs *regs)
371{
372#ifdef CONFIG_IA32_EMULATION
373 if (test_thread_flag(TIF_IA32))
374 /*
375 * Sign-extend the value so (int)-EFOO becomes (long)-EFOO
376 * and will match correctly in comparisons.
377 */
378 return (int) regs->ax;
379#endif
380 return regs->ax;
381}
382
383/*
384 * OK, we're invoking a handler 358 * OK, we're invoking a handler
385 */ 359 */
386 360
@@ -391,9 +365,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
391 int ret; 365 int ret;
392 366
393 /* Are we from a system call? */ 367 /* Are we from a system call? */
394 if (current_syscall(regs) >= 0) { 368 if (syscall_get_nr(current, regs) >= 0) {
395 /* If so, check system call restarting.. */ 369 /* If so, check system call restarting.. */
396 switch (current_syscall_ret(regs)) { 370 switch (syscall_get_error(current, regs)) {
397 case -ERESTART_RESTARTBLOCK: 371 case -ERESTART_RESTARTBLOCK:
398 case -ERESTARTNOHAND: 372 case -ERESTARTNOHAND:
399 regs->ax = -EINTR; 373 regs->ax = -EINTR;
@@ -450,8 +424,6 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
450 * handler too. 424 * handler too.
451 */ 425 */
452 regs->flags &= ~X86_EFLAGS_TF; 426 regs->flags &= ~X86_EFLAGS_TF;
453 if (test_thread_flag(TIF_SINGLESTEP))
454 ptrace_notify(SIGTRAP);
455 427
456 spin_lock_irq(&current->sighand->siglock); 428 spin_lock_irq(&current->sighand->siglock);
457 sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask); 429 sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
@@ -459,6 +431,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
459 sigaddset(&current->blocked, sig); 431 sigaddset(&current->blocked, sig);
460 recalc_sigpending(); 432 recalc_sigpending();
461 spin_unlock_irq(&current->sighand->siglock); 433 spin_unlock_irq(&current->sighand->siglock);
434
435 tracehook_signal_handler(sig, info, ka, regs,
436 test_thread_flag(TIF_SINGLESTEP));
462 } 437 }
463 438
464 return ret; 439 return ret;
@@ -515,9 +490,9 @@ static void do_signal(struct pt_regs *regs)
515 } 490 }
516 491
517 /* Did we come from a system call? */ 492 /* Did we come from a system call? */
518 if (current_syscall(regs) >= 0) { 493 if (syscall_get_nr(current, regs) >= 0) {
519 /* Restart the system call - no handlers present */ 494 /* Restart the system call - no handlers present */
520 switch (current_syscall_ret(regs)) { 495 switch (syscall_get_error(current, regs)) {
521 case -ERESTARTNOHAND: 496 case -ERESTARTNOHAND:
522 case -ERESTARTSYS: 497 case -ERESTARTSYS:
523 case -ERESTARTNOINTR: 498 case -ERESTARTNOINTR:
@@ -555,6 +530,11 @@ void do_notify_resume(struct pt_regs *regs, void *unused,
555 /* deal with pending signal delivery */ 530 /* deal with pending signal delivery */
556 if (thread_info_flags & _TIF_SIGPENDING) 531 if (thread_info_flags & _TIF_SIGPENDING)
557 do_signal(regs); 532 do_signal(regs);
533
534 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
535 clear_thread_flag(TIF_NOTIFY_RESUME);
536 tracehook_notify_resume(regs);
537 }
558} 538}
559 539
560void signal_fault(struct pt_regs *regs, void __user *frame, char *where) 540void signal_fault(struct pt_regs *regs, void __user *frame, char *where)