diff options
author | Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com> | 2008-11-24 21:23:12 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-11-25 23:11:53 -0500 |
commit | bfeb91a9435889ef4fe7bfbb4b673f625e69e790 (patch) | |
tree | 904f16d0eba56b7812b1462de6bc28df6c70371f /arch/x86/kernel/signal_32.c | |
parent | 2601657d223d82053d4e1fe1063091401e6b860a (diff) |
x86: signal: cosmetic unification of __setup_sigframe() and __setup_rt_sigframe()
Impact: cleanup
Add #ifdef directive to unify __setup_sigframe() and __setup_rt_sigframe().
Move them after {setup|restore}_sigcontext() declaration.
Signed-off-by: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/signal_32.c')
-rw-r--r-- | arch/x86/kernel/signal_32.c | 469 |
1 files changed, 280 insertions, 189 deletions
diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index b3f30d2a2178..e9f71298e746 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c | |||
@@ -48,28 +48,6 @@ | |||
48 | # define FIX_EFLAGS __FIX_EFLAGS | 48 | # define FIX_EFLAGS __FIX_EFLAGS |
49 | #endif | 49 | #endif |
50 | 50 | ||
51 | static const struct { | ||
52 | u16 poplmovl; | ||
53 | u32 val; | ||
54 | u16 int80; | ||
55 | } __attribute__((packed)) retcode = { | ||
56 | 0xb858, /* popl %eax; movl $..., %eax */ | ||
57 | __NR_sigreturn, | ||
58 | 0x80cd, /* int $0x80 */ | ||
59 | }; | ||
60 | |||
61 | static const struct { | ||
62 | u8 movl; | ||
63 | u32 val; | ||
64 | u16 int80; | ||
65 | u8 pad; | ||
66 | } __attribute__((packed)) rt_retcode = { | ||
67 | 0xb8, /* movl $..., %eax */ | ||
68 | __NR_rt_sigreturn, | ||
69 | 0x80cd, /* int $0x80 */ | ||
70 | 0 | ||
71 | }; | ||
72 | |||
73 | #define COPY(x) { \ | 51 | #define COPY(x) { \ |
74 | err |= __get_user(regs->x, &sc->x); \ | 52 | err |= __get_user(regs->x, &sc->x); \ |
75 | } | 53 | } |
@@ -207,176 +185,30 @@ setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate, | |||
207 | } | 185 | } |
208 | 186 | ||
209 | /* | 187 | /* |
210 | * Atomically swap in the new signal mask, and wait for a signal. | 188 | * Set up a signal frame. |
211 | */ | 189 | */ |
212 | asmlinkage int | ||
213 | sys_sigsuspend(int history0, int history1, old_sigset_t mask) | ||
214 | { | ||
215 | mask &= _BLOCKABLE; | ||
216 | spin_lock_irq(¤t->sighand->siglock); | ||
217 | current->saved_sigmask = current->blocked; | ||
218 | siginitset(¤t->blocked, mask); | ||
219 | recalc_sigpending(); | ||
220 | spin_unlock_irq(¤t->sighand->siglock); | ||
221 | |||
222 | current->state = TASK_INTERRUPTIBLE; | ||
223 | schedule(); | ||
224 | set_restore_sigmask(); | ||
225 | |||
226 | return -ERESTARTNOHAND; | ||
227 | } | ||
228 | |||
229 | asmlinkage int | ||
230 | sys_sigaction(int sig, const struct old_sigaction __user *act, | ||
231 | struct old_sigaction __user *oact) | ||
232 | { | ||
233 | struct k_sigaction new_ka, old_ka; | ||
234 | int ret; | ||
235 | |||
236 | if (act) { | ||
237 | old_sigset_t mask; | ||
238 | |||
239 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || | ||
240 | __get_user(new_ka.sa.sa_handler, &act->sa_handler) || | ||
241 | __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) | ||
242 | return -EFAULT; | ||
243 | |||
244 | __get_user(new_ka.sa.sa_flags, &act->sa_flags); | ||
245 | __get_user(mask, &act->sa_mask); | ||
246 | siginitset(&new_ka.sa.sa_mask, mask); | ||
247 | } | ||
248 | |||
249 | ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); | ||
250 | |||
251 | if (!ret && oact) { | ||
252 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || | ||
253 | __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || | ||
254 | __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) | ||
255 | return -EFAULT; | ||
256 | |||
257 | __put_user(old_ka.sa.sa_flags, &oact->sa_flags); | ||
258 | __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); | ||
259 | } | ||
260 | |||
261 | return ret; | ||
262 | } | ||
263 | |||
264 | #ifdef CONFIG_X86_32 | 190 | #ifdef CONFIG_X86_32 |
265 | asmlinkage int sys_sigaltstack(unsigned long bx) | 191 | static const struct { |
266 | { | 192 | u16 poplmovl; |
267 | /* | 193 | u32 val; |
268 | * This is needed to make gcc realize it doesn't own the | 194 | u16 int80; |
269 | * "struct pt_regs" | 195 | } __attribute__((packed)) retcode = { |
270 | */ | 196 | 0xb858, /* popl %eax; movl $..., %eax */ |
271 | struct pt_regs *regs = (struct pt_regs *)&bx; | 197 | __NR_sigreturn, |
272 | const stack_t __user *uss = (const stack_t __user *)bx; | 198 | 0x80cd, /* int $0x80 */ |
273 | stack_t __user *uoss = (stack_t __user *)regs->cx; | 199 | }; |
274 | |||
275 | return do_sigaltstack(uss, uoss, regs->sp); | ||
276 | } | ||
277 | #else /* !CONFIG_X86_32 */ | ||
278 | asmlinkage long | ||
279 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | ||
280 | struct pt_regs *regs) | ||
281 | { | ||
282 | return do_sigaltstack(uss, uoss, regs->sp); | ||
283 | } | ||
284 | #endif /* CONFIG_X86_32 */ | ||
285 | |||
286 | /* | ||
287 | * Do a signal return; undo the signal stack. | ||
288 | */ | ||
289 | asmlinkage unsigned long sys_sigreturn(unsigned long __unused) | ||
290 | { | ||
291 | struct sigframe __user *frame; | ||
292 | struct pt_regs *regs; | ||
293 | unsigned long ax; | ||
294 | sigset_t set; | ||
295 | |||
296 | regs = (struct pt_regs *) &__unused; | ||
297 | frame = (struct sigframe __user *)(regs->sp - 8); | ||
298 | |||
299 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | ||
300 | goto badframe; | ||
301 | if (__get_user(set.sig[0], &frame->sc.oldmask) || (_NSIG_WORDS > 1 | ||
302 | && __copy_from_user(&set.sig[1], &frame->extramask, | ||
303 | sizeof(frame->extramask)))) | ||
304 | goto badframe; | ||
305 | |||
306 | sigdelsetmask(&set, ~_BLOCKABLE); | ||
307 | spin_lock_irq(¤t->sighand->siglock); | ||
308 | current->blocked = set; | ||
309 | recalc_sigpending(); | ||
310 | spin_unlock_irq(¤t->sighand->siglock); | ||
311 | |||
312 | if (restore_sigcontext(regs, &frame->sc, &ax)) | ||
313 | goto badframe; | ||
314 | return ax; | ||
315 | |||
316 | badframe: | ||
317 | if (show_unhandled_signals && printk_ratelimit()) { | ||
318 | printk("%s%s[%d] bad frame in sigreturn frame:" | ||
319 | "%p ip:%lx sp:%lx oeax:%lx", | ||
320 | task_pid_nr(current) > 1 ? KERN_INFO : KERN_EMERG, | ||
321 | current->comm, task_pid_nr(current), frame, regs->ip, | ||
322 | regs->sp, regs->orig_ax); | ||
323 | print_vma_addr(" in ", regs->ip); | ||
324 | printk(KERN_CONT "\n"); | ||
325 | } | ||
326 | |||
327 | force_sig(SIGSEGV, current); | ||
328 | |||
329 | return 0; | ||
330 | } | ||
331 | |||
332 | static long do_rt_sigreturn(struct pt_regs *regs) | ||
333 | { | ||
334 | struct rt_sigframe __user *frame; | ||
335 | unsigned long ax; | ||
336 | sigset_t set; | ||
337 | |||
338 | frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long)); | ||
339 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | ||
340 | goto badframe; | ||
341 | if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) | ||
342 | goto badframe; | ||
343 | |||
344 | sigdelsetmask(&set, ~_BLOCKABLE); | ||
345 | spin_lock_irq(¤t->sighand->siglock); | ||
346 | current->blocked = set; | ||
347 | recalc_sigpending(); | ||
348 | spin_unlock_irq(¤t->sighand->siglock); | ||
349 | |||
350 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax)) | ||
351 | goto badframe; | ||
352 | |||
353 | if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT) | ||
354 | goto badframe; | ||
355 | |||
356 | return ax; | ||
357 | |||
358 | badframe: | ||
359 | signal_fault(regs, frame, "rt_sigreturn"); | ||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | #ifdef CONFIG_X86_32 | ||
364 | asmlinkage int sys_rt_sigreturn(unsigned long __unused) | ||
365 | { | ||
366 | struct pt_regs *regs = (struct pt_regs *)&__unused; | ||
367 | |||
368 | return do_rt_sigreturn(regs); | ||
369 | } | ||
370 | #else /* !CONFIG_X86_32 */ | ||
371 | asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) | ||
372 | { | ||
373 | return do_rt_sigreturn(regs); | ||
374 | } | ||
375 | #endif /* CONFIG_X86_32 */ | ||
376 | 200 | ||
377 | /* | 201 | static const struct { |
378 | * Set up a signal frame. | 202 | u8 movl; |
379 | */ | 203 | u32 val; |
204 | u16 int80; | ||
205 | u8 pad; | ||
206 | } __attribute__((packed)) rt_retcode = { | ||
207 | 0xb8, /* movl $..., %eax */ | ||
208 | __NR_rt_sigreturn, | ||
209 | 0x80cd, /* int $0x80 */ | ||
210 | 0 | ||
211 | }; | ||
380 | 212 | ||
381 | /* | 213 | /* |
382 | * Determine which stack to use.. | 214 | * Determine which stack to use.. |
@@ -557,6 +389,265 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
557 | 389 | ||
558 | return 0; | 390 | return 0; |
559 | } | 391 | } |
392 | #else /* !CONFIG_X86_32 */ | ||
393 | /* | ||
394 | * Determine which stack to use.. | ||
395 | */ | ||
396 | static void __user * | ||
397 | get_stack(struct k_sigaction *ka, unsigned long sp, unsigned long size) | ||
398 | { | ||
399 | /* Default to using normal stack - redzone*/ | ||
400 | sp -= 128; | ||
401 | |||
402 | /* This is the X/Open sanctioned signal stack switching. */ | ||
403 | if (ka->sa.sa_flags & SA_ONSTACK) { | ||
404 | if (sas_ss_flags(sp) == 0) | ||
405 | sp = current->sas_ss_sp + current->sas_ss_size; | ||
406 | } | ||
407 | |||
408 | return (void __user *)round_down(sp - size, 64); | ||
409 | } | ||
410 | |||
411 | static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | ||
412 | sigset_t *set, struct pt_regs *regs) | ||
413 | { | ||
414 | struct rt_sigframe __user *frame; | ||
415 | void __user *fp = NULL; | ||
416 | int err = 0; | ||
417 | struct task_struct *me = current; | ||
418 | |||
419 | if (used_math()) { | ||
420 | fp = get_stack(ka, regs->sp, sig_xstate_size); | ||
421 | frame = (void __user *)round_down( | ||
422 | (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8; | ||
423 | |||
424 | if (save_i387_xstate(fp) < 0) | ||
425 | return -EFAULT; | ||
426 | } else | ||
427 | frame = get_stack(ka, regs->sp, sizeof(struct rt_sigframe)) - 8; | ||
428 | |||
429 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | ||
430 | return -EFAULT; | ||
431 | |||
432 | if (ka->sa.sa_flags & SA_SIGINFO) { | ||
433 | if (copy_siginfo_to_user(&frame->info, info)) | ||
434 | return -EFAULT; | ||
435 | } | ||
436 | |||
437 | /* Create the ucontext. */ | ||
438 | if (cpu_has_xsave) | ||
439 | err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags); | ||
440 | else | ||
441 | err |= __put_user(0, &frame->uc.uc_flags); | ||
442 | err |= __put_user(0, &frame->uc.uc_link); | ||
443 | err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp); | ||
444 | err |= __put_user(sas_ss_flags(regs->sp), | ||
445 | &frame->uc.uc_stack.ss_flags); | ||
446 | err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size); | ||
447 | err |= setup_sigcontext(&frame->uc.uc_mcontext, fp, regs, set->sig[0]); | ||
448 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | ||
449 | |||
450 | /* Set up to return from userspace. If provided, use a stub | ||
451 | already in userspace. */ | ||
452 | /* x86-64 should always use SA_RESTORER. */ | ||
453 | if (ka->sa.sa_flags & SA_RESTORER) { | ||
454 | err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); | ||
455 | } else { | ||
456 | /* could use a vstub here */ | ||
457 | return -EFAULT; | ||
458 | } | ||
459 | |||
460 | if (err) | ||
461 | return -EFAULT; | ||
462 | |||
463 | /* Set up registers for signal handler */ | ||
464 | regs->di = sig; | ||
465 | /* In case the signal handler was declared without prototypes */ | ||
466 | regs->ax = 0; | ||
467 | |||
468 | /* This also works for non SA_SIGINFO handlers because they expect the | ||
469 | next argument after the signal number on the stack. */ | ||
470 | regs->si = (unsigned long)&frame->info; | ||
471 | regs->dx = (unsigned long)&frame->uc; | ||
472 | regs->ip = (unsigned long) ka->sa.sa_handler; | ||
473 | |||
474 | regs->sp = (unsigned long)frame; | ||
475 | |||
476 | /* Set up the CS register to run signal handlers in 64-bit mode, | ||
477 | even if the handler happens to be interrupting 32-bit code. */ | ||
478 | regs->cs = __USER_CS; | ||
479 | |||
480 | return 0; | ||
481 | } | ||
482 | #endif /* CONFIG_X86_32 */ | ||
483 | |||
484 | /* | ||
485 | * Atomically swap in the new signal mask, and wait for a signal. | ||
486 | */ | ||
487 | asmlinkage int | ||
488 | sys_sigsuspend(int history0, int history1, old_sigset_t mask) | ||
489 | { | ||
490 | mask &= _BLOCKABLE; | ||
491 | spin_lock_irq(¤t->sighand->siglock); | ||
492 | current->saved_sigmask = current->blocked; | ||
493 | siginitset(¤t->blocked, mask); | ||
494 | recalc_sigpending(); | ||
495 | spin_unlock_irq(¤t->sighand->siglock); | ||
496 | |||
497 | current->state = TASK_INTERRUPTIBLE; | ||
498 | schedule(); | ||
499 | set_restore_sigmask(); | ||
500 | |||
501 | return -ERESTARTNOHAND; | ||
502 | } | ||
503 | |||
504 | asmlinkage int | ||
505 | sys_sigaction(int sig, const struct old_sigaction __user *act, | ||
506 | struct old_sigaction __user *oact) | ||
507 | { | ||
508 | struct k_sigaction new_ka, old_ka; | ||
509 | int ret; | ||
510 | |||
511 | if (act) { | ||
512 | old_sigset_t mask; | ||
513 | |||
514 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || | ||
515 | __get_user(new_ka.sa.sa_handler, &act->sa_handler) || | ||
516 | __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) | ||
517 | return -EFAULT; | ||
518 | |||
519 | __get_user(new_ka.sa.sa_flags, &act->sa_flags); | ||
520 | __get_user(mask, &act->sa_mask); | ||
521 | siginitset(&new_ka.sa.sa_mask, mask); | ||
522 | } | ||
523 | |||
524 | ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); | ||
525 | |||
526 | if (!ret && oact) { | ||
527 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || | ||
528 | __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || | ||
529 | __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) | ||
530 | return -EFAULT; | ||
531 | |||
532 | __put_user(old_ka.sa.sa_flags, &oact->sa_flags); | ||
533 | __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); | ||
534 | } | ||
535 | |||
536 | return ret; | ||
537 | } | ||
538 | |||
539 | #ifdef CONFIG_X86_32 | ||
540 | asmlinkage int sys_sigaltstack(unsigned long bx) | ||
541 | { | ||
542 | /* | ||
543 | * This is needed to make gcc realize it doesn't own the | ||
544 | * "struct pt_regs" | ||
545 | */ | ||
546 | struct pt_regs *regs = (struct pt_regs *)&bx; | ||
547 | const stack_t __user *uss = (const stack_t __user *)bx; | ||
548 | stack_t __user *uoss = (stack_t __user *)regs->cx; | ||
549 | |||
550 | return do_sigaltstack(uss, uoss, regs->sp); | ||
551 | } | ||
552 | #else /* !CONFIG_X86_32 */ | ||
553 | asmlinkage long | ||
554 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | ||
555 | struct pt_regs *regs) | ||
556 | { | ||
557 | return do_sigaltstack(uss, uoss, regs->sp); | ||
558 | } | ||
559 | #endif /* CONFIG_X86_32 */ | ||
560 | |||
561 | /* | ||
562 | * Do a signal return; undo the signal stack. | ||
563 | */ | ||
564 | asmlinkage unsigned long sys_sigreturn(unsigned long __unused) | ||
565 | { | ||
566 | struct sigframe __user *frame; | ||
567 | struct pt_regs *regs; | ||
568 | unsigned long ax; | ||
569 | sigset_t set; | ||
570 | |||
571 | regs = (struct pt_regs *) &__unused; | ||
572 | frame = (struct sigframe __user *)(regs->sp - 8); | ||
573 | |||
574 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | ||
575 | goto badframe; | ||
576 | if (__get_user(set.sig[0], &frame->sc.oldmask) || (_NSIG_WORDS > 1 | ||
577 | && __copy_from_user(&set.sig[1], &frame->extramask, | ||
578 | sizeof(frame->extramask)))) | ||
579 | goto badframe; | ||
580 | |||
581 | sigdelsetmask(&set, ~_BLOCKABLE); | ||
582 | spin_lock_irq(¤t->sighand->siglock); | ||
583 | current->blocked = set; | ||
584 | recalc_sigpending(); | ||
585 | spin_unlock_irq(¤t->sighand->siglock); | ||
586 | |||
587 | if (restore_sigcontext(regs, &frame->sc, &ax)) | ||
588 | goto badframe; | ||
589 | return ax; | ||
590 | |||
591 | badframe: | ||
592 | if (show_unhandled_signals && printk_ratelimit()) { | ||
593 | printk("%s%s[%d] bad frame in sigreturn frame:" | ||
594 | "%p ip:%lx sp:%lx oeax:%lx", | ||
595 | task_pid_nr(current) > 1 ? KERN_INFO : KERN_EMERG, | ||
596 | current->comm, task_pid_nr(current), frame, regs->ip, | ||
597 | regs->sp, regs->orig_ax); | ||
598 | print_vma_addr(" in ", regs->ip); | ||
599 | printk(KERN_CONT "\n"); | ||
600 | } | ||
601 | |||
602 | force_sig(SIGSEGV, current); | ||
603 | |||
604 | return 0; | ||
605 | } | ||
606 | |||
607 | static long do_rt_sigreturn(struct pt_regs *regs) | ||
608 | { | ||
609 | struct rt_sigframe __user *frame; | ||
610 | unsigned long ax; | ||
611 | sigset_t set; | ||
612 | |||
613 | frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long)); | ||
614 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | ||
615 | goto badframe; | ||
616 | if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) | ||
617 | goto badframe; | ||
618 | |||
619 | sigdelsetmask(&set, ~_BLOCKABLE); | ||
620 | spin_lock_irq(¤t->sighand->siglock); | ||
621 | current->blocked = set; | ||
622 | recalc_sigpending(); | ||
623 | spin_unlock_irq(¤t->sighand->siglock); | ||
624 | |||
625 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax)) | ||
626 | goto badframe; | ||
627 | |||
628 | if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT) | ||
629 | goto badframe; | ||
630 | |||
631 | return ax; | ||
632 | |||
633 | badframe: | ||
634 | signal_fault(regs, frame, "rt_sigreturn"); | ||
635 | return 0; | ||
636 | } | ||
637 | |||
638 | #ifdef CONFIG_X86_32 | ||
639 | asmlinkage int sys_rt_sigreturn(unsigned long __unused) | ||
640 | { | ||
641 | struct pt_regs *regs = (struct pt_regs *)&__unused; | ||
642 | |||
643 | return do_rt_sigreturn(regs); | ||
644 | } | ||
645 | #else /* !CONFIG_X86_32 */ | ||
646 | asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) | ||
647 | { | ||
648 | return do_rt_sigreturn(regs); | ||
649 | } | ||
650 | #endif /* CONFIG_X86_32 */ | ||
560 | 651 | ||
561 | /* | 652 | /* |
562 | * OK, we're invoking a handler: | 653 | * OK, we're invoking a handler: |