diff options
Diffstat (limited to 'arch/x86/kernel/signal_64.c')
-rw-r--r-- | arch/x86/kernel/signal_64.c | 201 |
1 files changed, 51 insertions, 150 deletions
diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index ca316b5b742c..823a55bf8c39 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c | |||
@@ -15,17 +15,21 @@ | |||
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> |
21 | #include <linux/compiler.h> | 22 | #include <linux/compiler.h> |
23 | #include <linux/uaccess.h> | ||
24 | |||
22 | #include <asm/processor.h> | 25 | #include <asm/processor.h> |
23 | #include <asm/ucontext.h> | 26 | #include <asm/ucontext.h> |
24 | #include <asm/uaccess.h> | ||
25 | #include <asm/i387.h> | 27 | #include <asm/i387.h> |
26 | #include <asm/proto.h> | 28 | #include <asm/proto.h> |
27 | #include <asm/ia32_unistd.h> | 29 | #include <asm/ia32_unistd.h> |
28 | #include <asm/mce.h> | 30 | #include <asm/mce.h> |
31 | #include <asm/syscall.h> | ||
32 | #include <asm/syscalls.h> | ||
29 | #include "sigframe.h" | 33 | #include "sigframe.h" |
30 | 34 | ||
31 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | 35 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) |
@@ -41,11 +45,6 @@ | |||
41 | # define FIX_EFLAGS __FIX_EFLAGS | 45 | # define FIX_EFLAGS __FIX_EFLAGS |
42 | #endif | 46 | #endif |
43 | 47 | ||
44 | int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | ||
45 | sigset_t *set, struct pt_regs * regs); | ||
46 | int ia32_setup_frame(int sig, struct k_sigaction *ka, | ||
47 | sigset_t *set, struct pt_regs * regs); | ||
48 | |||
49 | asmlinkage long | 48 | asmlinkage long |
50 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | 49 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, |
51 | struct pt_regs *regs) | 50 | struct pt_regs *regs) |
@@ -54,69 +53,6 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | |||
54 | } | 53 | } |
55 | 54 | ||
56 | /* | 55 | /* |
57 | * Signal frame handlers. | ||
58 | */ | ||
59 | |||
60 | static inline int save_i387(struct _fpstate __user *buf) | ||
61 | { | ||
62 | struct task_struct *tsk = current; | ||
63 | int err = 0; | ||
64 | |||
65 | BUILD_BUG_ON(sizeof(struct user_i387_struct) != | ||
66 | sizeof(tsk->thread.xstate->fxsave)); | ||
67 | |||
68 | if ((unsigned long)buf % 16) | ||
69 | printk("save_i387: bad fpstate %p\n", buf); | ||
70 | |||
71 | if (!used_math()) | ||
72 | return 0; | ||
73 | clear_used_math(); /* trigger finit */ | ||
74 | if (task_thread_info(tsk)->status & TS_USEDFPU) { | ||
75 | err = save_i387_checking((struct i387_fxsave_struct __user *) | ||
76 | buf); | ||
77 | if (err) | ||
78 | return err; | ||
79 | task_thread_info(tsk)->status &= ~TS_USEDFPU; | ||
80 | stts(); | ||
81 | } else { | ||
82 | if (__copy_to_user(buf, &tsk->thread.xstate->fxsave, | ||
83 | sizeof(struct i387_fxsave_struct))) | ||
84 | return -1; | ||
85 | } | ||
86 | return 1; | ||
87 | } | ||
88 | |||
89 | /* | ||
90 | * This restores directly out of user space. Exceptions are handled. | ||
91 | */ | ||
92 | static inline int restore_i387(struct _fpstate __user *buf) | ||
93 | { | ||
94 | struct task_struct *tsk = current; | ||
95 | int err; | ||
96 | |||
97 | if (!used_math()) { | ||
98 | err = init_fpu(tsk); | ||
99 | if (err) | ||
100 | return err; | ||
101 | } | ||
102 | |||
103 | if (!(task_thread_info(current)->status & TS_USEDFPU)) { | ||
104 | clts(); | ||
105 | task_thread_info(current)->status |= TS_USEDFPU; | ||
106 | } | ||
107 | err = restore_fpu_checking((__force struct i387_fxsave_struct *)buf); | ||
108 | if (unlikely(err)) { | ||
109 | /* | ||
110 | * Encountered an error while doing the restore from the | ||
111 | * user buffer, clear the fpu state. | ||
112 | */ | ||
113 | clear_fpu(tsk); | ||
114 | clear_used_math(); | ||
115 | } | ||
116 | return err; | ||
117 | } | ||
118 | |||
119 | /* | ||
120 | * Do a signal return; undo the signal stack. | 56 | * Do a signal return; undo the signal stack. |
121 | */ | 57 | */ |
122 | static int | 58 | static int |
@@ -128,7 +64,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, | |||
128 | /* Always make any pending restarted system calls return -EINTR */ | 64 | /* Always make any pending restarted system calls return -EINTR */ |
129 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | 65 | current_thread_info()->restart_block.fn = do_no_restart_syscall; |
130 | 66 | ||
131 | #define COPY(x) err |= __get_user(regs->x, &sc->x) | 67 | #define COPY(x) (err |= __get_user(regs->x, &sc->x)) |
132 | 68 | ||
133 | COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); | 69 | COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); |
134 | COPY(dx); COPY(cx); COPY(ip); | 70 | COPY(dx); COPY(cx); COPY(ip); |
@@ -158,27 +94,13 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, | |||
158 | } | 94 | } |
159 | 95 | ||
160 | { | 96 | { |
161 | struct _fpstate __user * buf; | 97 | struct _fpstate __user *buf; |
162 | err |= __get_user(buf, &sc->fpstate); | 98 | err |= __get_user(buf, &sc->fpstate); |
163 | 99 | err |= restore_i387_xstate(buf); | |
164 | if (buf) { | ||
165 | if (!access_ok(VERIFY_READ, buf, sizeof(*buf))) | ||
166 | goto badframe; | ||
167 | err |= restore_i387(buf); | ||
168 | } else { | ||
169 | struct task_struct *me = current; | ||
170 | if (used_math()) { | ||
171 | clear_fpu(me); | ||
172 | clear_used_math(); | ||
173 | } | ||
174 | } | ||
175 | } | 100 | } |
176 | 101 | ||
177 | err |= __get_user(*pax, &sc->ax); | 102 | err |= __get_user(*pax, &sc->ax); |
178 | return err; | 103 | return err; |
179 | |||
180 | badframe: | ||
181 | return 1; | ||
182 | } | 104 | } |
183 | 105 | ||
184 | asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) | 106 | asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) |
@@ -198,7 +120,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) | |||
198 | current->blocked = set; | 120 | current->blocked = set; |
199 | recalc_sigpending(); | 121 | recalc_sigpending(); |
200 | spin_unlock_irq(¤t->sighand->siglock); | 122 | spin_unlock_irq(¤t->sighand->siglock); |
201 | 123 | ||
202 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax)) | 124 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax)) |
203 | goto badframe; | 125 | goto badframe; |
204 | 126 | ||
@@ -208,16 +130,17 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) | |||
208 | return ax; | 130 | return ax; |
209 | 131 | ||
210 | badframe: | 132 | badframe: |
211 | signal_fault(regs,frame,"sigreturn"); | 133 | signal_fault(regs, frame, "sigreturn"); |
212 | return 0; | 134 | return 0; |
213 | } | 135 | } |
214 | 136 | ||
215 | /* | 137 | /* |
216 | * Set up a signal frame. | 138 | * Set up a signal frame. |
217 | */ | 139 | */ |
218 | 140 | ||
219 | static inline int | 141 | static inline int |
220 | setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, unsigned long mask, struct task_struct *me) | 142 | setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, |
143 | unsigned long mask, struct task_struct *me) | ||
221 | { | 144 | { |
222 | int err = 0; | 145 | int err = 0; |
223 | 146 | ||
@@ -269,41 +192,41 @@ get_stack(struct k_sigaction *ka, struct pt_regs *regs, unsigned long size) | |||
269 | sp = current->sas_ss_sp + current->sas_ss_size; | 192 | sp = current->sas_ss_sp + current->sas_ss_size; |
270 | } | 193 | } |
271 | 194 | ||
272 | return (void __user *)round_down(sp - size, 16); | 195 | return (void __user *)round_down(sp - size, 64); |
273 | } | 196 | } |
274 | 197 | ||
275 | static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 198 | static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, |
276 | sigset_t *set, struct pt_regs * regs) | 199 | sigset_t *set, struct pt_regs *regs) |
277 | { | 200 | { |
278 | struct rt_sigframe __user *frame; | 201 | struct rt_sigframe __user *frame; |
279 | struct _fpstate __user *fp = NULL; | 202 | void __user *fp = NULL; |
280 | int err = 0; | 203 | int err = 0; |
281 | struct task_struct *me = current; | 204 | struct task_struct *me = current; |
282 | 205 | ||
283 | if (used_math()) { | 206 | if (used_math()) { |
284 | fp = get_stack(ka, regs, sizeof(struct _fpstate)); | 207 | fp = get_stack(ka, regs, sig_xstate_size); |
285 | frame = (void __user *)round_down( | 208 | frame = (void __user *)round_down( |
286 | (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8; | 209 | (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8; |
287 | 210 | ||
288 | if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate))) | 211 | if (save_i387_xstate(fp) < 0) |
289 | goto give_sigsegv; | 212 | err |= -1; |
290 | |||
291 | if (save_i387(fp) < 0) | ||
292 | err |= -1; | ||
293 | } else | 213 | } else |
294 | frame = get_stack(ka, regs, sizeof(struct rt_sigframe)) - 8; | 214 | frame = get_stack(ka, regs, sizeof(struct rt_sigframe)) - 8; |
295 | 215 | ||
296 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 216 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
297 | goto give_sigsegv; | 217 | goto give_sigsegv; |
298 | 218 | ||
299 | if (ka->sa.sa_flags & SA_SIGINFO) { | 219 | if (ka->sa.sa_flags & SA_SIGINFO) { |
300 | err |= copy_siginfo_to_user(&frame->info, info); | 220 | err |= copy_siginfo_to_user(&frame->info, info); |
301 | if (err) | 221 | if (err) |
302 | goto give_sigsegv; | 222 | goto give_sigsegv; |
303 | } | 223 | } |
304 | 224 | ||
305 | /* Create the ucontext. */ | 225 | /* Create the ucontext. */ |
306 | err |= __put_user(0, &frame->uc.uc_flags); | 226 | if (cpu_has_xsave) |
227 | err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags); | ||
228 | else | ||
229 | err |= __put_user(0, &frame->uc.uc_flags); | ||
307 | err |= __put_user(0, &frame->uc.uc_link); | 230 | err |= __put_user(0, &frame->uc.uc_link); |
308 | err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp); | 231 | err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp); |
309 | err |= __put_user(sas_ss_flags(regs->sp), | 232 | err |= __put_user(sas_ss_flags(regs->sp), |
@@ -311,9 +234,9 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
311 | 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); |
312 | 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); |
313 | err |= __put_user(fp, &frame->uc.uc_mcontext.fpstate); | 236 | err |= __put_user(fp, &frame->uc.uc_mcontext.fpstate); |
314 | if (sizeof(*set) == 16) { | 237 | if (sizeof(*set) == 16) { |
315 | __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]); | 238 | __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]); |
316 | __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]); | 239 | __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]); |
317 | } else | 240 | } else |
318 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | 241 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
319 | 242 | ||
@@ -324,7 +247,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
324 | err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); | 247 | err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); |
325 | } else { | 248 | } else { |
326 | /* could use a vstub here */ | 249 | /* could use a vstub here */ |
327 | goto give_sigsegv; | 250 | goto give_sigsegv; |
328 | } | 251 | } |
329 | 252 | ||
330 | if (err) | 253 | if (err) |
@@ -332,7 +255,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
332 | 255 | ||
333 | /* Set up registers for signal handler */ | 256 | /* Set up registers for signal handler */ |
334 | regs->di = sig; | 257 | regs->di = sig; |
335 | /* In case the signal handler was declared without prototypes */ | 258 | /* In case the signal handler was declared without prototypes */ |
336 | regs->ax = 0; | 259 | regs->ax = 0; |
337 | 260 | ||
338 | /* 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 |
@@ -355,37 +278,8 @@ give_sigsegv: | |||
355 | } | 278 | } |
356 | 279 | ||
357 | /* | 280 | /* |
358 | * Return -1L or the syscall number that @regs is executing. | ||
359 | */ | ||
360 | static long current_syscall(struct pt_regs *regs) | ||
361 | { | ||
362 | /* | ||
363 | * We always sign-extend a -1 value being set here, | ||
364 | * so this is always either -1L or a syscall number. | ||
365 | */ | ||
366 | return regs->orig_ax; | ||
367 | } | ||
368 | |||
369 | /* | ||
370 | * Return a value that is -EFOO if the system call in @regs->orig_ax | ||
371 | * returned an error. This only works for @regs from @current. | ||
372 | */ | ||
373 | static long current_syscall_ret(struct pt_regs *regs) | ||
374 | { | ||
375 | #ifdef CONFIG_IA32_EMULATION | ||
376 | if (test_thread_flag(TIF_IA32)) | ||
377 | /* | ||
378 | * Sign-extend the value so (int)-EFOO becomes (long)-EFOO | ||
379 | * and will match correctly in comparisons. | ||
380 | */ | ||
381 | return (int) regs->ax; | ||
382 | #endif | ||
383 | return regs->ax; | ||
384 | } | ||
385 | |||
386 | /* | ||
387 | * OK, we're invoking a handler | 281 | * OK, we're invoking a handler |
388 | */ | 282 | */ |
389 | 283 | ||
390 | static int | 284 | static int |
391 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | 285 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, |
@@ -394,9 +288,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
394 | int ret; | 288 | int ret; |
395 | 289 | ||
396 | /* Are we from a system call? */ | 290 | /* Are we from a system call? */ |
397 | if (current_syscall(regs) >= 0) { | 291 | if (syscall_get_nr(current, regs) >= 0) { |
398 | /* If so, check system call restarting.. */ | 292 | /* If so, check system call restarting.. */ |
399 | switch (current_syscall_ret(regs)) { | 293 | switch (syscall_get_error(current, regs)) { |
400 | case -ERESTART_RESTARTBLOCK: | 294 | case -ERESTART_RESTARTBLOCK: |
401 | case -ERESTARTNOHAND: | 295 | case -ERESTARTNOHAND: |
402 | regs->ax = -EINTR; | 296 | regs->ax = -EINTR; |
@@ -429,7 +323,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
429 | ret = ia32_setup_rt_frame(sig, ka, info, oldset, regs); | 323 | ret = ia32_setup_rt_frame(sig, ka, info, oldset, regs); |
430 | else | 324 | else |
431 | ret = ia32_setup_frame(sig, ka, oldset, regs); | 325 | ret = ia32_setup_frame(sig, ka, oldset, regs); |
432 | } else | 326 | } else |
433 | #endif | 327 | #endif |
434 | ret = setup_rt_frame(sig, ka, info, oldset, regs); | 328 | ret = setup_rt_frame(sig, ka, info, oldset, regs); |
435 | 329 | ||
@@ -453,15 +347,16 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
453 | * handler too. | 347 | * handler too. |
454 | */ | 348 | */ |
455 | regs->flags &= ~X86_EFLAGS_TF; | 349 | regs->flags &= ~X86_EFLAGS_TF; |
456 | if (test_thread_flag(TIF_SINGLESTEP)) | ||
457 | ptrace_notify(SIGTRAP); | ||
458 | 350 | ||
459 | spin_lock_irq(¤t->sighand->siglock); | 351 | spin_lock_irq(¤t->sighand->siglock); |
460 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); | 352 | sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); |
461 | if (!(ka->sa.sa_flags & SA_NODEFER)) | 353 | if (!(ka->sa.sa_flags & SA_NODEFER)) |
462 | sigaddset(¤t->blocked,sig); | 354 | sigaddset(¤t->blocked, sig); |
463 | recalc_sigpending(); | 355 | recalc_sigpending(); |
464 | spin_unlock_irq(¤t->sighand->siglock); | 356 | spin_unlock_irq(¤t->sighand->siglock); |
357 | |||
358 | tracehook_signal_handler(sig, info, ka, regs, | ||
359 | test_thread_flag(TIF_SINGLESTEP)); | ||
465 | } | 360 | } |
466 | 361 | ||
467 | return ret; | 362 | return ret; |
@@ -518,9 +413,9 @@ static void do_signal(struct pt_regs *regs) | |||
518 | } | 413 | } |
519 | 414 | ||
520 | /* Did we come from a system call? */ | 415 | /* Did we come from a system call? */ |
521 | if (current_syscall(regs) >= 0) { | 416 | if (syscall_get_nr(current, regs) >= 0) { |
522 | /* Restart the system call - no handlers present */ | 417 | /* Restart the system call - no handlers present */ |
523 | switch (current_syscall_ret(regs)) { | 418 | switch (syscall_get_error(current, regs)) { |
524 | case -ERESTARTNOHAND: | 419 | case -ERESTARTNOHAND: |
525 | case -ERESTARTSYS: | 420 | case -ERESTARTSYS: |
526 | case -ERESTARTNOINTR: | 421 | case -ERESTARTNOINTR: |
@@ -558,17 +453,23 @@ void do_notify_resume(struct pt_regs *regs, void *unused, | |||
558 | /* deal with pending signal delivery */ | 453 | /* deal with pending signal delivery */ |
559 | if (thread_info_flags & _TIF_SIGPENDING) | 454 | if (thread_info_flags & _TIF_SIGPENDING) |
560 | do_signal(regs); | 455 | do_signal(regs); |
456 | |||
457 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | ||
458 | clear_thread_flag(TIF_NOTIFY_RESUME); | ||
459 | tracehook_notify_resume(regs); | ||
460 | } | ||
561 | } | 461 | } |
562 | 462 | ||
563 | void signal_fault(struct pt_regs *regs, void __user *frame, char *where) | 463 | void signal_fault(struct pt_regs *regs, void __user *frame, char *where) |
564 | { | 464 | { |
565 | struct task_struct *me = current; | 465 | struct task_struct *me = current; |
566 | if (show_unhandled_signals && printk_ratelimit()) { | 466 | if (show_unhandled_signals && printk_ratelimit()) { |
567 | 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", |
568 | 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); | ||
569 | print_vma_addr(" in ", regs->ip); | 470 | print_vma_addr(" in ", regs->ip); |
570 | printk("\n"); | 471 | printk("\n"); |
571 | } | 472 | } |
572 | 473 | ||
573 | force_sig(SIGSEGV, me); | 474 | force_sig(SIGSEGV, me); |
574 | } | 475 | } |