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.c108
1 files changed, 45 insertions, 63 deletions
diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c
index 1c83e5124c65..827179c5b32a 100644
--- a/arch/x86/kernel/signal_64.c
+++ b/arch/x86/kernel/signal_64.c
@@ -19,17 +19,28 @@
19#include <linux/stddef.h> 19#include <linux/stddef.h>
20#include <linux/personality.h> 20#include <linux/personality.h>
21#include <linux/compiler.h> 21#include <linux/compiler.h>
22#include <asm/processor.h>
22#include <asm/ucontext.h> 23#include <asm/ucontext.h>
23#include <asm/uaccess.h> 24#include <asm/uaccess.h>
24#include <asm/i387.h> 25#include <asm/i387.h>
25#include <asm/proto.h> 26#include <asm/proto.h>
26#include <asm/ia32_unistd.h> 27#include <asm/ia32_unistd.h>
27#include <asm/mce.h> 28#include <asm/mce.h>
28 29#include "sigframe.h"
29/* #define DEBUG_SIG 1 */
30 30
31#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 31#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
32 32
33#define __FIX_EFLAGS (X86_EFLAGS_AC | X86_EFLAGS_OF | \
34 X86_EFLAGS_DF | X86_EFLAGS_TF | X86_EFLAGS_SF | \
35 X86_EFLAGS_ZF | X86_EFLAGS_AF | X86_EFLAGS_PF | \
36 X86_EFLAGS_CF)
37
38#ifdef CONFIG_X86_32
39# define FIX_EFLAGS (__FIX_EFLAGS | X86_EFLAGS_RF)
40#else
41# define FIX_EFLAGS __FIX_EFLAGS
42#endif
43
33int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, 44int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
34 sigset_t *set, struct pt_regs * regs); 45 sigset_t *set, struct pt_regs * regs);
35int ia32_setup_frame(int sig, struct k_sigaction *ka, 46int ia32_setup_frame(int sig, struct k_sigaction *ka,
@@ -46,16 +57,9 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
46/* 57/*
47 * Do a signal return; undo the signal stack. 58 * Do a signal return; undo the signal stack.
48 */ 59 */
49
50struct rt_sigframe
51{
52 char __user *pretcode;
53 struct ucontext uc;
54 struct siginfo info;
55};
56
57static int 60static int
58restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, unsigned long *prax) 61restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
62 unsigned long *pax)
59{ 63{
60 unsigned int err = 0; 64 unsigned int err = 0;
61 65
@@ -87,7 +91,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, unsigned
87 { 91 {
88 unsigned int tmpflags; 92 unsigned int tmpflags;
89 err |= __get_user(tmpflags, &sc->flags); 93 err |= __get_user(tmpflags, &sc->flags);
90 regs->flags = (regs->flags & ~0x40DD5) | (tmpflags & 0x40DD5); 94 regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
91 regs->orig_ax = -1; /* disable syscall checks */ 95 regs->orig_ax = -1; /* disable syscall checks */
92 } 96 }
93 97
@@ -108,7 +112,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, unsigned
108 } 112 }
109 } 113 }
110 114
111 err |= __get_user(*prax, &sc->ax); 115 err |= __get_user(*pax, &sc->ax);
112 return err; 116 return err;
113 117
114badframe: 118badframe:
@@ -121,13 +125,11 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
121 sigset_t set; 125 sigset_t set;
122 unsigned long ax; 126 unsigned long ax;
123 127
124 frame = (struct rt_sigframe __user *)(regs->sp - 8); 128 frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long));
125 if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) { 129 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
126 goto badframe; 130 goto badframe;
127 } 131 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
128 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) {
129 goto badframe; 132 goto badframe;
130 }
131 133
132 sigdelsetmask(&set, ~_BLOCKABLE); 134 sigdelsetmask(&set, ~_BLOCKABLE);
133 spin_lock_irq(&current->sighand->siglock); 135 spin_lock_irq(&current->sighand->siglock);
@@ -138,10 +140,6 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
138 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax)) 140 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
139 goto badframe; 141 goto badframe;
140 142
141#ifdef DEBUG_SIG
142 printk("%d sigreturn ip:%lx sp:%lx frame:%p ax:%lx\n",current->pid,regs->ip,regs->sp,frame,ax);
143#endif
144
145 if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT) 143 if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT)
146 goto badframe; 144 goto badframe;
147 145
@@ -270,10 +268,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
270 if (err) 268 if (err)
271 goto give_sigsegv; 269 goto give_sigsegv;
272 270
273#ifdef DEBUG_SIG
274 printk("%d old ip %lx old sp %lx old ax %lx\n", current->pid,regs->ip,regs->sp,regs->ax);
275#endif
276
277 /* Set up registers for signal handler */ 271 /* Set up registers for signal handler */
278 regs->di = sig; 272 regs->di = sig;
279 /* In case the signal handler was declared without prototypes */ 273 /* In case the signal handler was declared without prototypes */
@@ -298,10 +292,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
298 regs->flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_DF); 292 regs->flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_DF);
299 if (test_thread_flag(TIF_SINGLESTEP)) 293 if (test_thread_flag(TIF_SINGLESTEP))
300 ptrace_notify(SIGTRAP); 294 ptrace_notify(SIGTRAP);
301#ifdef DEBUG_SIG
302 printk("SIG deliver (%s:%d): sp=%p pc=%lx ra=%p\n",
303 current->comm, current->pid, frame, regs->ip, frame->pretcode);
304#endif
305 295
306 return 0; 296 return 0;
307 297
@@ -345,35 +335,29 @@ static long current_syscall_ret(struct pt_regs *regs)
345 335
346static int 336static int
347handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, 337handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
348 sigset_t *oldset, struct pt_regs *regs) 338 sigset_t *oldset, struct pt_regs *regs)
349{ 339{
350 int ret; 340 int ret;
351 341
352#ifdef DEBUG_SIG
353 printk("handle_signal pid:%d sig:%lu ip:%lx sp:%lx regs=%p\n",
354 current->pid, sig,
355 regs->ip, regs->sp, regs);
356#endif
357
358 /* Are we from a system call? */ 342 /* Are we from a system call? */
359 if (current_syscall(regs) >= 0) { 343 if (current_syscall(regs) >= 0) {
360 /* If so, check system call restarting.. */ 344 /* If so, check system call restarting.. */
361 switch (current_syscall_ret(regs)) { 345 switch (current_syscall_ret(regs)) {
362 case -ERESTART_RESTARTBLOCK: 346 case -ERESTART_RESTARTBLOCK:
363 case -ERESTARTNOHAND: 347 case -ERESTARTNOHAND:
364 regs->ax = -EINTR; 348 regs->ax = -EINTR;
365 break; 349 break;
366 350
367 case -ERESTARTSYS: 351 case -ERESTARTSYS:
368 if (!(ka->sa.sa_flags & SA_RESTART)) { 352 if (!(ka->sa.sa_flags & SA_RESTART)) {
369 regs->ax = -EINTR; 353 regs->ax = -EINTR;
370 break;
371 }
372 /* fallthrough */
373 case -ERESTARTNOINTR:
374 regs->ax = regs->orig_ax;
375 regs->ip -= 2;
376 break; 354 break;
355 }
356 /* fallthrough */
357 case -ERESTARTNOINTR:
358 regs->ax = regs->orig_ax;
359 regs->ip -= 2;
360 break;
377 } 361 }
378 } 362 }
379 363
@@ -420,10 +404,11 @@ static void do_signal(struct pt_regs *regs)
420 sigset_t *oldset; 404 sigset_t *oldset;
421 405
422 /* 406 /*
423 * We want the common case to go fast, which 407 * We want the common case to go fast, which is why we may in certain
424 * is why we may in certain cases get here from 408 * cases get here from kernel mode. Just return without doing anything
425 * kernel mode. Just return without doing anything
426 * if so. 409 * if so.
410 * X86_32: vm86 regs switched out by assembly code before reaching
411 * here, so testing against kernel CS suffices.
427 */ 412 */
428 if (!user_mode(regs)) 413 if (!user_mode(regs))
429 return; 414 return;
@@ -473,22 +458,19 @@ static void do_signal(struct pt_regs *regs)
473 } 458 }
474 } 459 }
475 460
476 /* if there's no signal to deliver, we just put the saved sigmask 461 /*
477 back. */ 462 * If there's no signal to deliver, we just put the saved sigmask
463 * back.
464 */
478 if (test_thread_flag(TIF_RESTORE_SIGMASK)) { 465 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
479 clear_thread_flag(TIF_RESTORE_SIGMASK); 466 clear_thread_flag(TIF_RESTORE_SIGMASK);
480 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL); 467 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
481 } 468 }
482} 469}
483 470
484void 471void do_notify_resume(struct pt_regs *regs, void *unused,
485do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) 472 __u32 thread_info_flags)
486{ 473{
487#ifdef DEBUG_SIG
488 printk("do_notify_resume flags:%x ip:%lx sp:%lx caller:%p pending:%x\n",
489 thread_info_flags, regs->ip, regs->sp, __builtin_return_address(0),signal_pending(current));
490#endif
491
492 /* Pending single-step? */ 474 /* Pending single-step? */
493 if (thread_info_flags & _TIF_SINGLESTEP) { 475 if (thread_info_flags & _TIF_SINGLESTEP) {
494 regs->flags |= X86_EFLAGS_TF; 476 regs->flags |= X86_EFLAGS_TF;
@@ -502,7 +484,7 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
502#endif /* CONFIG_X86_MCE */ 484#endif /* CONFIG_X86_MCE */
503 485
504 /* deal with pending signal delivery */ 486 /* deal with pending signal delivery */
505 if (thread_info_flags & (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK)) 487 if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
506 do_signal(regs); 488 do_signal(regs);
507 489
508 if (thread_info_flags & _TIF_HRTICK_RESCHED) 490 if (thread_info_flags & _TIF_HRTICK_RESCHED)