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.c56
1 files changed, 27 insertions, 29 deletions
diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c
index 2f28252d2d26..823a55bf8c39 100644
--- a/arch/x86/kernel/signal_64.c
+++ b/arch/x86/kernel/signal_64.c
@@ -20,9 +20,10 @@
20#include <linux/stddef.h> 20#include <linux/stddef.h>
21#include <linux/personality.h> 21#include <linux/personality.h>
22#include <linux/compiler.h> 22#include <linux/compiler.h>
23#include <linux/uaccess.h>
24
23#include <asm/processor.h> 25#include <asm/processor.h>
24#include <asm/ucontext.h> 26#include <asm/ucontext.h>
25#include <asm/uaccess.h>
26#include <asm/i387.h> 27#include <asm/i387.h>
27#include <asm/proto.h> 28#include <asm/proto.h>
28#include <asm/ia32_unistd.h> 29#include <asm/ia32_unistd.h>
@@ -44,11 +45,6 @@
44# define FIX_EFLAGS __FIX_EFLAGS 45# define FIX_EFLAGS __FIX_EFLAGS
45#endif 46#endif
46 47
47int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
48 sigset_t *set, struct pt_regs * regs);
49int ia32_setup_frame(int sig, struct k_sigaction *ka,
50 sigset_t *set, struct pt_regs * regs);
51
52asmlinkage long 48asmlinkage long
53sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, 49sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
54 struct pt_regs *regs) 50 struct pt_regs *regs)
@@ -68,7 +64,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
68 /* Always make any pending restarted system calls return -EINTR */ 64 /* Always make any pending restarted system calls return -EINTR */
69 current_thread_info()->restart_block.fn = do_no_restart_syscall; 65 current_thread_info()->restart_block.fn = do_no_restart_syscall;
70 66
71#define COPY(x) err |= __get_user(regs->x, &sc->x) 67#define COPY(x) (err |= __get_user(regs->x, &sc->x))
72 68
73 COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); 69 COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
74 COPY(dx); COPY(cx); COPY(ip); 70 COPY(dx); COPY(cx); COPY(ip);
@@ -98,7 +94,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
98 } 94 }
99 95
100 { 96 {
101 struct _fpstate __user * buf; 97 struct _fpstate __user *buf;
102 err |= __get_user(buf, &sc->fpstate); 98 err |= __get_user(buf, &sc->fpstate);
103 err |= restore_i387_xstate(buf); 99 err |= restore_i387_xstate(buf);
104 } 100 }
@@ -124,7 +120,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
124 current->blocked = set; 120 current->blocked = set;
125 recalc_sigpending(); 121 recalc_sigpending();
126 spin_unlock_irq(&current->sighand->siglock); 122 spin_unlock_irq(&current->sighand->siglock);
127 123
128 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax)) 124 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
129 goto badframe; 125 goto badframe;
130 126
@@ -134,16 +130,17 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
134 return ax; 130 return ax;
135 131
136badframe: 132badframe:
137 signal_fault(regs,frame,"sigreturn"); 133 signal_fault(regs, frame, "sigreturn");
138 return 0; 134 return 0;
139} 135}
140 136
141/* 137/*
142 * Set up a signal frame. 138 * Set up a signal frame.
143 */ 139 */
144 140
145static inline int 141static inline int
146setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, unsigned long mask, struct task_struct *me) 142setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
143 unsigned long mask, struct task_struct *me)
147{ 144{
148 int err = 0; 145 int err = 0;
149 146
@@ -199,7 +196,7 @@ get_stack(struct k_sigaction *ka, struct pt_regs *regs, unsigned long size)
199} 196}
200 197
201static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, 198static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
202 sigset_t *set, struct pt_regs * regs) 199 sigset_t *set, struct pt_regs *regs)
203{ 200{
204 struct rt_sigframe __user *frame; 201 struct rt_sigframe __user *frame;
205 void __user *fp = NULL; 202 void __user *fp = NULL;
@@ -212,19 +209,19 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
212 (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8; 209 (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8;
213 210
214 if (save_i387_xstate(fp) < 0) 211 if (save_i387_xstate(fp) < 0)
215 err |= -1; 212 err |= -1;
216 } else 213 } else
217 frame = get_stack(ka, regs, sizeof(struct rt_sigframe)) - 8; 214 frame = get_stack(ka, regs, sizeof(struct rt_sigframe)) - 8;
218 215
219 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) 216 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
220 goto give_sigsegv; 217 goto give_sigsegv;
221 218
222 if (ka->sa.sa_flags & SA_SIGINFO) { 219 if (ka->sa.sa_flags & SA_SIGINFO) {
223 err |= copy_siginfo_to_user(&frame->info, info); 220 err |= copy_siginfo_to_user(&frame->info, info);
224 if (err) 221 if (err)
225 goto give_sigsegv; 222 goto give_sigsegv;
226 } 223 }
227 224
228 /* Create the ucontext. */ 225 /* Create the ucontext. */
229 if (cpu_has_xsave) 226 if (cpu_has_xsave)
230 err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags); 227 err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags);
@@ -237,9 +234,9 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
237 err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size); 234 err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size);
238 err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0], me); 235 err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0], me);
239 err |= __put_user(fp, &frame->uc.uc_mcontext.fpstate); 236 err |= __put_user(fp, &frame->uc.uc_mcontext.fpstate);
240 if (sizeof(*set) == 16) { 237 if (sizeof(*set) == 16) {
241 __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]); 238 __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]);
242 __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]); 239 __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]);
243 } else 240 } else
244 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); 241 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
245 242
@@ -250,7 +247,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
250 err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); 247 err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
251 } else { 248 } else {
252 /* could use a vstub here */ 249 /* could use a vstub here */
253 goto give_sigsegv; 250 goto give_sigsegv;
254 } 251 }
255 252
256 if (err) 253 if (err)
@@ -258,7 +255,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
258 255
259 /* Set up registers for signal handler */ 256 /* Set up registers for signal handler */
260 regs->di = sig; 257 regs->di = sig;
261 /* In case the signal handler was declared without prototypes */ 258 /* In case the signal handler was declared without prototypes */
262 regs->ax = 0; 259 regs->ax = 0;
263 260
264 /* This also works for non SA_SIGINFO handlers because they expect the 261 /* This also works for non SA_SIGINFO handlers because they expect the
@@ -282,7 +279,7 @@ give_sigsegv:
282 279
283/* 280/*
284 * OK, we're invoking a handler 281 * OK, we're invoking a handler
285 */ 282 */
286 283
287static int 284static int
288handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, 285handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
@@ -326,7 +323,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
326 ret = ia32_setup_rt_frame(sig, ka, info, oldset, regs); 323 ret = ia32_setup_rt_frame(sig, ka, info, oldset, regs);
327 else 324 else
328 ret = ia32_setup_frame(sig, ka, oldset, regs); 325 ret = ia32_setup_frame(sig, ka, oldset, regs);
329 } else 326 } else
330#endif 327#endif
331 ret = setup_rt_frame(sig, ka, info, oldset, regs); 328 ret = setup_rt_frame(sig, ka, info, oldset, regs);
332 329
@@ -352,9 +349,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
352 regs->flags &= ~X86_EFLAGS_TF; 349 regs->flags &= ~X86_EFLAGS_TF;
353 350
354 spin_lock_irq(&current->sighand->siglock); 351 spin_lock_irq(&current->sighand->siglock);
355 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask); 352 sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
356 if (!(ka->sa.sa_flags & SA_NODEFER)) 353 if (!(ka->sa.sa_flags & SA_NODEFER))
357 sigaddset(&current->blocked,sig); 354 sigaddset(&current->blocked, sig);
358 recalc_sigpending(); 355 recalc_sigpending();
359 spin_unlock_irq(&current->sighand->siglock); 356 spin_unlock_irq(&current->sighand->siglock);
360 357
@@ -464,14 +461,15 @@ void do_notify_resume(struct pt_regs *regs, void *unused,
464} 461}
465 462
466void signal_fault(struct pt_regs *regs, void __user *frame, char *where) 463void signal_fault(struct pt_regs *regs, void __user *frame, char *where)
467{ 464{
468 struct task_struct *me = current; 465 struct task_struct *me = current;
469 if (show_unhandled_signals && printk_ratelimit()) { 466 if (show_unhandled_signals && printk_ratelimit()) {
470 printk("%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx", 467 printk("%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx",
471 me->comm,me->pid,where,frame,regs->ip,regs->sp,regs->orig_ax); 468 me->comm, me->pid, where, frame, regs->ip,
469 regs->sp, regs->orig_ax);
472 print_vma_addr(" in ", regs->ip); 470 print_vma_addr(" in ", regs->ip);
473 printk("\n"); 471 printk("\n");
474 } 472 }
475 473
476 force_sig(SIGSEGV, me); 474 force_sig(SIGSEGV, me);
477} 475}