diff options
Diffstat (limited to 'arch/x86/kernel/signal_64.c')
-rw-r--r-- | arch/x86/kernel/signal_64.c | 207 |
1 files changed, 124 insertions, 83 deletions
diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 823a55bf8c39..a5c9627f4db9 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c | |||
@@ -52,6 +52,16 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | |||
52 | return do_sigaltstack(uss, uoss, regs->sp); | 52 | return do_sigaltstack(uss, uoss, regs->sp); |
53 | } | 53 | } |
54 | 54 | ||
55 | #define COPY(x) { \ | ||
56 | err |= __get_user(regs->x, &sc->x); \ | ||
57 | } | ||
58 | |||
59 | #define COPY_SEG_STRICT(seg) { \ | ||
60 | unsigned short tmp; \ | ||
61 | err |= __get_user(tmp, &sc->seg); \ | ||
62 | regs->seg = tmp | 3; \ | ||
63 | } | ||
64 | |||
55 | /* | 65 | /* |
56 | * Do a signal return; undo the signal stack. | 66 | * Do a signal return; undo the signal stack. |
57 | */ | 67 | */ |
@@ -59,13 +69,13 @@ static int | |||
59 | restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, | 69 | restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, |
60 | unsigned long *pax) | 70 | unsigned long *pax) |
61 | { | 71 | { |
72 | void __user *buf; | ||
73 | unsigned int tmpflags; | ||
62 | unsigned int err = 0; | 74 | unsigned int err = 0; |
63 | 75 | ||
64 | /* Always make any pending restarted system calls return -EINTR */ | 76 | /* Always make any pending restarted system calls return -EINTR */ |
65 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | 77 | current_thread_info()->restart_block.fn = do_no_restart_syscall; |
66 | 78 | ||
67 | #define COPY(x) (err |= __get_user(regs->x, &sc->x)) | ||
68 | |||
69 | COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); | 79 | COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); |
70 | COPY(dx); COPY(cx); COPY(ip); | 80 | COPY(dx); COPY(cx); COPY(ip); |
71 | COPY(r8); | 81 | COPY(r8); |
@@ -80,34 +90,24 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, | |||
80 | /* Kernel saves and restores only the CS segment register on signals, | 90 | /* Kernel saves and restores only the CS segment register on signals, |
81 | * which is the bare minimum needed to allow mixed 32/64-bit code. | 91 | * which is the bare minimum needed to allow mixed 32/64-bit code. |
82 | * App's signal handler can save/restore other segments if needed. */ | 92 | * App's signal handler can save/restore other segments if needed. */ |
83 | { | 93 | COPY_SEG_STRICT(cs); |
84 | unsigned cs; | ||
85 | err |= __get_user(cs, &sc->cs); | ||
86 | regs->cs = cs | 3; /* Force into user mode */ | ||
87 | } | ||
88 | 94 | ||
89 | { | 95 | err |= __get_user(tmpflags, &sc->flags); |
90 | unsigned int tmpflags; | 96 | regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS); |
91 | err |= __get_user(tmpflags, &sc->flags); | 97 | regs->orig_ax = -1; /* disable syscall checks */ |
92 | regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS); | ||
93 | regs->orig_ax = -1; /* disable syscall checks */ | ||
94 | } | ||
95 | 98 | ||
96 | { | 99 | err |= __get_user(buf, &sc->fpstate); |
97 | struct _fpstate __user *buf; | 100 | err |= restore_i387_xstate(buf); |
98 | err |= __get_user(buf, &sc->fpstate); | ||
99 | err |= restore_i387_xstate(buf); | ||
100 | } | ||
101 | 101 | ||
102 | err |= __get_user(*pax, &sc->ax); | 102 | err |= __get_user(*pax, &sc->ax); |
103 | return err; | 103 | return err; |
104 | } | 104 | } |
105 | 105 | ||
106 | asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) | 106 | static long do_rt_sigreturn(struct pt_regs *regs) |
107 | { | 107 | { |
108 | struct rt_sigframe __user *frame; | 108 | struct rt_sigframe __user *frame; |
109 | sigset_t set; | ||
110 | unsigned long ax; | 109 | unsigned long ax; |
110 | sigset_t set; | ||
111 | 111 | ||
112 | frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long)); | 112 | frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long)); |
113 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 113 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
@@ -130,10 +130,15 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) | |||
130 | return ax; | 130 | return ax; |
131 | 131 | ||
132 | badframe: | 132 | badframe: |
133 | signal_fault(regs, frame, "sigreturn"); | 133 | signal_fault(regs, frame, "rt_sigreturn"); |
134 | return 0; | 134 | return 0; |
135 | } | 135 | } |
136 | 136 | ||
137 | asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) | ||
138 | { | ||
139 | return do_rt_sigreturn(regs); | ||
140 | } | ||
141 | |||
137 | /* | 142 | /* |
138 | * Set up a signal frame. | 143 | * Set up a signal frame. |
139 | */ | 144 | */ |
@@ -195,8 +200,8 @@ get_stack(struct k_sigaction *ka, struct pt_regs *regs, unsigned long size) | |||
195 | return (void __user *)round_down(sp - size, 64); | 200 | return (void __user *)round_down(sp - size, 64); |
196 | } | 201 | } |
197 | 202 | ||
198 | static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 203 | static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, |
199 | sigset_t *set, struct pt_regs *regs) | 204 | sigset_t *set, struct pt_regs *regs) |
200 | { | 205 | { |
201 | struct rt_sigframe __user *frame; | 206 | struct rt_sigframe __user *frame; |
202 | void __user *fp = NULL; | 207 | void __user *fp = NULL; |
@@ -209,17 +214,16 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
209 | (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8; | 214 | (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8; |
210 | 215 | ||
211 | if (save_i387_xstate(fp) < 0) | 216 | if (save_i387_xstate(fp) < 0) |
212 | err |= -1; | 217 | return -EFAULT; |
213 | } else | 218 | } else |
214 | frame = get_stack(ka, regs, sizeof(struct rt_sigframe)) - 8; | 219 | frame = get_stack(ka, regs, sizeof(struct rt_sigframe)) - 8; |
215 | 220 | ||
216 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 221 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
217 | goto give_sigsegv; | 222 | return -EFAULT; |
218 | 223 | ||
219 | if (ka->sa.sa_flags & SA_SIGINFO) { | 224 | if (ka->sa.sa_flags & SA_SIGINFO) { |
220 | err |= copy_siginfo_to_user(&frame->info, info); | 225 | if (copy_siginfo_to_user(&frame->info, info)) |
221 | if (err) | 226 | return -EFAULT; |
222 | goto give_sigsegv; | ||
223 | } | 227 | } |
224 | 228 | ||
225 | /* Create the ucontext. */ | 229 | /* Create the ucontext. */ |
@@ -247,11 +251,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
247 | err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); | 251 | err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); |
248 | } else { | 252 | } else { |
249 | /* could use a vstub here */ | 253 | /* could use a vstub here */ |
250 | goto give_sigsegv; | 254 | return -EFAULT; |
251 | } | 255 | } |
252 | 256 | ||
253 | if (err) | 257 | if (err) |
254 | goto give_sigsegv; | 258 | return -EFAULT; |
255 | 259 | ||
256 | /* Set up registers for signal handler */ | 260 | /* Set up registers for signal handler */ |
257 | regs->di = sig; | 261 | regs->di = sig; |
@@ -271,15 +275,45 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
271 | regs->cs = __USER_CS; | 275 | regs->cs = __USER_CS; |
272 | 276 | ||
273 | return 0; | 277 | return 0; |
274 | |||
275 | give_sigsegv: | ||
276 | force_sigsegv(sig, current); | ||
277 | return -EFAULT; | ||
278 | } | 278 | } |
279 | 279 | ||
280 | /* | 280 | /* |
281 | * OK, we're invoking a handler | 281 | * OK, we're invoking a handler |
282 | */ | 282 | */ |
283 | static int signr_convert(int sig) | ||
284 | { | ||
285 | return sig; | ||
286 | } | ||
287 | |||
288 | #ifdef CONFIG_IA32_EMULATION | ||
289 | #define is_ia32 test_thread_flag(TIF_IA32) | ||
290 | #else | ||
291 | #define is_ia32 0 | ||
292 | #endif | ||
293 | |||
294 | static int | ||
295 | setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | ||
296 | sigset_t *set, struct pt_regs *regs) | ||
297 | { | ||
298 | int usig = signr_convert(sig); | ||
299 | int ret; | ||
300 | |||
301 | /* Set up the stack frame */ | ||
302 | if (is_ia32) { | ||
303 | if (ka->sa.sa_flags & SA_SIGINFO) | ||
304 | ret = ia32_setup_rt_frame(usig, ka, info, set, regs); | ||
305 | else | ||
306 | ret = ia32_setup_frame(usig, ka, set, regs); | ||
307 | } else | ||
308 | ret = __setup_rt_frame(sig, ka, info, set, regs); | ||
309 | |||
310 | if (ret) { | ||
311 | force_sigsegv(sig, current); | ||
312 | return -EFAULT; | ||
313 | } | ||
314 | |||
315 | return ret; | ||
316 | } | ||
283 | 317 | ||
284 | static int | 318 | static int |
285 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | 319 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, |
@@ -317,51 +351,48 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
317 | likely(test_and_clear_thread_flag(TIF_FORCED_TF))) | 351 | likely(test_and_clear_thread_flag(TIF_FORCED_TF))) |
318 | regs->flags &= ~X86_EFLAGS_TF; | 352 | regs->flags &= ~X86_EFLAGS_TF; |
319 | 353 | ||
320 | #ifdef CONFIG_IA32_EMULATION | ||
321 | if (test_thread_flag(TIF_IA32)) { | ||
322 | if (ka->sa.sa_flags & SA_SIGINFO) | ||
323 | ret = ia32_setup_rt_frame(sig, ka, info, oldset, regs); | ||
324 | else | ||
325 | ret = ia32_setup_frame(sig, ka, oldset, regs); | ||
326 | } else | ||
327 | #endif | ||
328 | ret = setup_rt_frame(sig, ka, info, oldset, regs); | 354 | ret = setup_rt_frame(sig, ka, info, oldset, regs); |
329 | 355 | ||
330 | if (ret == 0) { | 356 | if (ret) |
331 | /* | 357 | return ret; |
332 | * This has nothing to do with segment registers, | ||
333 | * despite the name. This magic affects uaccess.h | ||
334 | * macros' behavior. Reset it to the normal setting. | ||
335 | */ | ||
336 | set_fs(USER_DS); | ||
337 | 358 | ||
338 | /* | 359 | #ifdef CONFIG_X86_64 |
339 | * Clear the direction flag as per the ABI for function entry. | 360 | /* |
340 | */ | 361 | * This has nothing to do with segment registers, |
341 | regs->flags &= ~X86_EFLAGS_DF; | 362 | * despite the name. This magic affects uaccess.h |
363 | * macros' behavior. Reset it to the normal setting. | ||
364 | */ | ||
365 | set_fs(USER_DS); | ||
366 | #endif | ||
342 | 367 | ||
343 | /* | 368 | /* |
344 | * Clear TF when entering the signal handler, but | 369 | * Clear the direction flag as per the ABI for function entry. |
345 | * notify any tracer that was single-stepping it. | 370 | */ |
346 | * The tracer may want to single-step inside the | 371 | regs->flags &= ~X86_EFLAGS_DF; |
347 | * handler too. | ||
348 | */ | ||
349 | regs->flags &= ~X86_EFLAGS_TF; | ||
350 | 372 | ||
351 | spin_lock_irq(¤t->sighand->siglock); | 373 | /* |
352 | sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); | 374 | * Clear TF when entering the signal handler, but |
353 | if (!(ka->sa.sa_flags & SA_NODEFER)) | 375 | * notify any tracer that was single-stepping it. |
354 | sigaddset(¤t->blocked, sig); | 376 | * The tracer may want to single-step inside the |
355 | recalc_sigpending(); | 377 | * handler too. |
356 | spin_unlock_irq(¤t->sighand->siglock); | 378 | */ |
379 | regs->flags &= ~X86_EFLAGS_TF; | ||
357 | 380 | ||
358 | tracehook_signal_handler(sig, info, ka, regs, | 381 | spin_lock_irq(¤t->sighand->siglock); |
359 | test_thread_flag(TIF_SINGLESTEP)); | 382 | sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); |
360 | } | 383 | if (!(ka->sa.sa_flags & SA_NODEFER)) |
384 | sigaddset(¤t->blocked, sig); | ||
385 | recalc_sigpending(); | ||
386 | spin_unlock_irq(¤t->sighand->siglock); | ||
361 | 387 | ||
362 | return ret; | 388 | tracehook_signal_handler(sig, info, ka, regs, |
389 | test_thread_flag(TIF_SINGLESTEP)); | ||
390 | |||
391 | return 0; | ||
363 | } | 392 | } |
364 | 393 | ||
394 | #define NR_restart_syscall \ | ||
395 | test_thread_flag(TIF_IA32) ? __NR_ia32_restart_syscall : __NR_restart_syscall | ||
365 | /* | 396 | /* |
366 | * Note that 'init' is a special process: it doesn't get signals it doesn't | 397 | * Note that 'init' is a special process: it doesn't get signals it doesn't |
367 | * want to handle. Thus you cannot kill init even with a SIGKILL even by | 398 | * want to handle. Thus you cannot kill init even with a SIGKILL even by |
@@ -391,7 +422,8 @@ static void do_signal(struct pt_regs *regs) | |||
391 | 422 | ||
392 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 423 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
393 | if (signr > 0) { | 424 | if (signr > 0) { |
394 | /* Re-enable any watchpoints before delivering the | 425 | /* |
426 | * Re-enable any watchpoints before delivering the | ||
395 | * signal to user space. The processor register will | 427 | * signal to user space. The processor register will |
396 | * have been cleared if the watchpoint triggered | 428 | * have been cleared if the watchpoint triggered |
397 | * inside the kernel. | 429 | * inside the kernel. |
@@ -399,7 +431,7 @@ static void do_signal(struct pt_regs *regs) | |||
399 | if (current->thread.debugreg7) | 431 | if (current->thread.debugreg7) |
400 | set_debugreg(current->thread.debugreg7, 7); | 432 | set_debugreg(current->thread.debugreg7, 7); |
401 | 433 | ||
402 | /* Whee! Actually deliver the signal. */ | 434 | /* Whee! Actually deliver the signal. */ |
403 | if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { | 435 | if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { |
404 | /* | 436 | /* |
405 | * A signal was successfully delivered; the saved | 437 | * A signal was successfully delivered; the saved |
@@ -422,10 +454,9 @@ static void do_signal(struct pt_regs *regs) | |||
422 | regs->ax = regs->orig_ax; | 454 | regs->ax = regs->orig_ax; |
423 | regs->ip -= 2; | 455 | regs->ip -= 2; |
424 | break; | 456 | break; |
457 | |||
425 | case -ERESTART_RESTARTBLOCK: | 458 | case -ERESTART_RESTARTBLOCK: |
426 | regs->ax = test_thread_flag(TIF_IA32) ? | 459 | regs->ax = NR_restart_syscall; |
427 | __NR_ia32_restart_syscall : | ||
428 | __NR_restart_syscall; | ||
429 | regs->ip -= 2; | 460 | regs->ip -= 2; |
430 | break; | 461 | break; |
431 | } | 462 | } |
@@ -441,14 +472,18 @@ static void do_signal(struct pt_regs *regs) | |||
441 | } | 472 | } |
442 | } | 473 | } |
443 | 474 | ||
444 | void do_notify_resume(struct pt_regs *regs, void *unused, | 475 | /* |
445 | __u32 thread_info_flags) | 476 | * notification of userspace execution resumption |
477 | * - triggered by the TIF_WORK_MASK flags | ||
478 | */ | ||
479 | void | ||
480 | do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) | ||
446 | { | 481 | { |
447 | #ifdef CONFIG_X86_MCE | 482 | #if defined(CONFIG_X86_64) && defined(CONFIG_X86_MCE) |
448 | /* notify userspace of pending MCEs */ | 483 | /* notify userspace of pending MCEs */ |
449 | if (thread_info_flags & _TIF_MCE_NOTIFY) | 484 | if (thread_info_flags & _TIF_MCE_NOTIFY) |
450 | mce_notify_user(); | 485 | mce_notify_user(); |
451 | #endif /* CONFIG_X86_MCE */ | 486 | #endif /* CONFIG_X86_64 && CONFIG_X86_MCE */ |
452 | 487 | ||
453 | /* deal with pending signal delivery */ | 488 | /* deal with pending signal delivery */ |
454 | if (thread_info_flags & _TIF_SIGPENDING) | 489 | if (thread_info_flags & _TIF_SIGPENDING) |
@@ -458,17 +493,23 @@ void do_notify_resume(struct pt_regs *regs, void *unused, | |||
458 | clear_thread_flag(TIF_NOTIFY_RESUME); | 493 | clear_thread_flag(TIF_NOTIFY_RESUME); |
459 | tracehook_notify_resume(regs); | 494 | tracehook_notify_resume(regs); |
460 | } | 495 | } |
496 | |||
497 | #ifdef CONFIG_X86_32 | ||
498 | clear_thread_flag(TIF_IRET); | ||
499 | #endif /* CONFIG_X86_32 */ | ||
461 | } | 500 | } |
462 | 501 | ||
463 | void signal_fault(struct pt_regs *regs, void __user *frame, char *where) | 502 | void signal_fault(struct pt_regs *regs, void __user *frame, char *where) |
464 | { | 503 | { |
465 | struct task_struct *me = current; | 504 | struct task_struct *me = current; |
505 | |||
466 | if (show_unhandled_signals && printk_ratelimit()) { | 506 | if (show_unhandled_signals && printk_ratelimit()) { |
467 | printk("%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx", | 507 | printk(KERN_INFO |
468 | me->comm, me->pid, where, frame, regs->ip, | 508 | "%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx", |
469 | regs->sp, regs->orig_ax); | 509 | me->comm, me->pid, where, frame, |
510 | regs->ip, regs->sp, regs->orig_ax); | ||
470 | print_vma_addr(" in ", regs->ip); | 511 | print_vma_addr(" in ", regs->ip); |
471 | printk("\n"); | 512 | printk(KERN_CONT "\n"); |
472 | } | 513 | } |
473 | 514 | ||
474 | force_sig(SIGSEGV, me); | 515 | force_sig(SIGSEGV, me); |