diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-11-07 17:53:13 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-02-14 09:21:16 -0500 |
commit | 7e243643dffbe216dbcb10933c4cafde0f95f537 (patch) | |
tree | 9bde297bb075b0331aec04b9d944b0e612d413bd | |
parent | cfd60c0789f395aa5564985177e3b4dab21974e1 (diff) |
arm: switch to struct ksignal * passing
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | arch/arm/kernel/signal.c | 108 |
1 files changed, 47 insertions, 61 deletions
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index 07429a23c720..296786bdbb73 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c | |||
@@ -318,18 +318,12 @@ setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs, sigset_t *set) | |||
318 | } | 318 | } |
319 | 319 | ||
320 | static inline void __user * | 320 | static inline void __user * |
321 | get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, int framesize) | 321 | get_sigframe(struct ksignal *ksig, struct pt_regs *regs, int framesize) |
322 | { | 322 | { |
323 | unsigned long sp = regs->ARM_sp; | 323 | unsigned long sp = sigsp(regs->ARM_sp, ksig); |
324 | void __user *frame; | 324 | void __user *frame; |
325 | 325 | ||
326 | /* | 326 | /* |
327 | * This is the X/Open sanctioned signal stack switching. | ||
328 | */ | ||
329 | if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) | ||
330 | sp = current->sas_ss_sp + current->sas_ss_size; | ||
331 | |||
332 | /* | ||
333 | * ATPCS B01 mandates 8-byte alignment | 327 | * ATPCS B01 mandates 8-byte alignment |
334 | */ | 328 | */ |
335 | frame = (void __user *)((sp - framesize) & ~7); | 329 | frame = (void __user *)((sp - framesize) & ~7); |
@@ -343,11 +337,22 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, int framesize) | |||
343 | return frame; | 337 | return frame; |
344 | } | 338 | } |
345 | 339 | ||
340 | /* | ||
341 | * translate the signal | ||
342 | */ | ||
343 | static inline int map_sig(int sig) | ||
344 | { | ||
345 | struct thread_info *thread = current_thread_info(); | ||
346 | if (sig < 32 && thread->exec_domain && thread->exec_domain->signal_invmap) | ||
347 | sig = thread->exec_domain->signal_invmap[sig]; | ||
348 | return sig; | ||
349 | } | ||
350 | |||
346 | static int | 351 | static int |
347 | setup_return(struct pt_regs *regs, struct k_sigaction *ka, | 352 | setup_return(struct pt_regs *regs, struct ksignal *ksig, |
348 | unsigned long __user *rc, void __user *frame, int usig) | 353 | unsigned long __user *rc, void __user *frame) |
349 | { | 354 | { |
350 | unsigned long handler = (unsigned long)ka->sa.sa_handler; | 355 | unsigned long handler = (unsigned long)ksig->ka.sa.sa_handler; |
351 | unsigned long retcode; | 356 | unsigned long retcode; |
352 | int thumb = 0; | 357 | int thumb = 0; |
353 | unsigned long cpsr = regs->ARM_cpsr & ~(PSR_f | PSR_E_BIT); | 358 | unsigned long cpsr = regs->ARM_cpsr & ~(PSR_f | PSR_E_BIT); |
@@ -357,7 +362,7 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka, | |||
357 | /* | 362 | /* |
358 | * Maybe we need to deliver a 32-bit signal to a 26-bit task. | 363 | * Maybe we need to deliver a 32-bit signal to a 26-bit task. |
359 | */ | 364 | */ |
360 | if (ka->sa.sa_flags & SA_THIRTYTWO) | 365 | if (ksig->ka.sa.sa_flags & SA_THIRTYTWO) |
361 | cpsr = (cpsr & ~MODE_MASK) | USR_MODE; | 366 | cpsr = (cpsr & ~MODE_MASK) | USR_MODE; |
362 | 367 | ||
363 | #ifdef CONFIG_ARM_THUMB | 368 | #ifdef CONFIG_ARM_THUMB |
@@ -379,12 +384,12 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka, | |||
379 | } | 384 | } |
380 | #endif | 385 | #endif |
381 | 386 | ||
382 | if (ka->sa.sa_flags & SA_RESTORER) { | 387 | if (ksig->ka.sa.sa_flags & SA_RESTORER) { |
383 | retcode = (unsigned long)ka->sa.sa_restorer; | 388 | retcode = (unsigned long)ksig->ka.sa.sa_restorer; |
384 | } else { | 389 | } else { |
385 | unsigned int idx = thumb << 1; | 390 | unsigned int idx = thumb << 1; |
386 | 391 | ||
387 | if (ka->sa.sa_flags & SA_SIGINFO) | 392 | if (ksig->ka.sa.sa_flags & SA_SIGINFO) |
388 | idx += 3; | 393 | idx += 3; |
389 | 394 | ||
390 | if (__put_user(sigreturn_codes[idx], rc) || | 395 | if (__put_user(sigreturn_codes[idx], rc) || |
@@ -409,7 +414,7 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka, | |||
409 | } | 414 | } |
410 | } | 415 | } |
411 | 416 | ||
412 | regs->ARM_r0 = usig; | 417 | regs->ARM_r0 = map_sig(ksig->sig); |
413 | regs->ARM_sp = (unsigned long)frame; | 418 | regs->ARM_sp = (unsigned long)frame; |
414 | regs->ARM_lr = retcode; | 419 | regs->ARM_lr = retcode; |
415 | regs->ARM_pc = handler; | 420 | regs->ARM_pc = handler; |
@@ -419,9 +424,9 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka, | |||
419 | } | 424 | } |
420 | 425 | ||
421 | static int | 426 | static int |
422 | setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *regs) | 427 | setup_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) |
423 | { | 428 | { |
424 | struct sigframe __user *frame = get_sigframe(ka, regs, sizeof(*frame)); | 429 | struct sigframe __user *frame = get_sigframe(ksig, regs, sizeof(*frame)); |
425 | int err = 0; | 430 | int err = 0; |
426 | 431 | ||
427 | if (!frame) | 432 | if (!frame) |
@@ -434,22 +439,21 @@ setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *reg | |||
434 | 439 | ||
435 | err |= setup_sigframe(frame, regs, set); | 440 | err |= setup_sigframe(frame, regs, set); |
436 | if (err == 0) | 441 | if (err == 0) |
437 | err = setup_return(regs, ka, frame->retcode, frame, usig); | 442 | err = setup_return(regs, ksig, frame->retcode, frame); |
438 | 443 | ||
439 | return err; | 444 | return err; |
440 | } | 445 | } |
441 | 446 | ||
442 | static int | 447 | static int |
443 | setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, | 448 | setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) |
444 | sigset_t *set, struct pt_regs *regs) | ||
445 | { | 449 | { |
446 | struct rt_sigframe __user *frame = get_sigframe(ka, regs, sizeof(*frame)); | 450 | struct rt_sigframe __user *frame = get_sigframe(ksig, regs, sizeof(*frame)); |
447 | int err = 0; | 451 | int err = 0; |
448 | 452 | ||
449 | if (!frame) | 453 | if (!frame) |
450 | return 1; | 454 | return 1; |
451 | 455 | ||
452 | err |= copy_siginfo_to_user(&frame->info, info); | 456 | err |= copy_siginfo_to_user(&frame->info, &ksig->info); |
453 | 457 | ||
454 | __put_user_error(0, &frame->sig.uc.uc_flags, err); | 458 | __put_user_error(0, &frame->sig.uc.uc_flags, err); |
455 | __put_user_error(NULL, &frame->sig.uc.uc_link, err); | 459 | __put_user_error(NULL, &frame->sig.uc.uc_link, err); |
@@ -457,7 +461,7 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, | |||
457 | err |= __save_altstack(&frame->sig.uc.uc_stack, regs->ARM_sp); | 461 | err |= __save_altstack(&frame->sig.uc.uc_stack, regs->ARM_sp); |
458 | err |= setup_sigframe(&frame->sig, regs, set); | 462 | err |= setup_sigframe(&frame->sig, regs, set); |
459 | if (err == 0) | 463 | if (err == 0) |
460 | err = setup_return(regs, ka, frame->sig.retcode, frame, usig); | 464 | err = setup_return(regs, ksig, frame->sig.retcode, frame); |
461 | 465 | ||
462 | if (err == 0) { | 466 | if (err == 0) { |
463 | /* | 467 | /* |
@@ -475,40 +479,25 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, | |||
475 | /* | 479 | /* |
476 | * OK, we're invoking a handler | 480 | * OK, we're invoking a handler |
477 | */ | 481 | */ |
478 | static void | 482 | static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) |
479 | handle_signal(unsigned long sig, struct k_sigaction *ka, | ||
480 | siginfo_t *info, struct pt_regs *regs) | ||
481 | { | 483 | { |
482 | struct thread_info *thread = current_thread_info(); | ||
483 | struct task_struct *tsk = current; | ||
484 | sigset_t *oldset = sigmask_to_save(); | 484 | sigset_t *oldset = sigmask_to_save(); |
485 | int usig = sig; | ||
486 | int ret; | 485 | int ret; |
487 | 486 | ||
488 | /* | 487 | /* |
489 | * translate the signal | ||
490 | */ | ||
491 | if (usig < 32 && thread->exec_domain && thread->exec_domain->signal_invmap) | ||
492 | usig = thread->exec_domain->signal_invmap[usig]; | ||
493 | |||
494 | /* | ||
495 | * Set up the stack frame | 488 | * Set up the stack frame |
496 | */ | 489 | */ |
497 | if (ka->sa.sa_flags & SA_SIGINFO) | 490 | if (ksig->ka.sa.sa_flags & SA_SIGINFO) |
498 | ret = setup_rt_frame(usig, ka, info, oldset, regs); | 491 | ret = setup_rt_frame(ksig, oldset, regs); |
499 | else | 492 | else |
500 | ret = setup_frame(usig, ka, oldset, regs); | 493 | ret = setup_frame(ksig, oldset, regs); |
501 | 494 | ||
502 | /* | 495 | /* |
503 | * Check that the resulting registers are actually sane. | 496 | * Check that the resulting registers are actually sane. |
504 | */ | 497 | */ |
505 | ret |= !valid_user_regs(regs); | 498 | ret |= !valid_user_regs(regs); |
506 | 499 | ||
507 | if (ret != 0) { | 500 | signal_setup_done(ret, ksig, 0); |
508 | force_sigsegv(sig, tsk); | ||
509 | return; | ||
510 | } | ||
511 | signal_delivered(sig, info, ka, regs, 0); | ||
512 | } | 501 | } |
513 | 502 | ||
514 | /* | 503 | /* |
@@ -523,9 +512,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, | |||
523 | static int do_signal(struct pt_regs *regs, int syscall) | 512 | static int do_signal(struct pt_regs *regs, int syscall) |
524 | { | 513 | { |
525 | unsigned int retval = 0, continue_addr = 0, restart_addr = 0; | 514 | unsigned int retval = 0, continue_addr = 0, restart_addr = 0; |
526 | struct k_sigaction ka; | 515 | struct ksignal ksig; |
527 | siginfo_t info; | ||
528 | int signr; | ||
529 | int restart = 0; | 516 | int restart = 0; |
530 | 517 | ||
531 | /* | 518 | /* |
@@ -557,33 +544,32 @@ static int do_signal(struct pt_regs *regs, int syscall) | |||
557 | * Get the signal to deliver. When running under ptrace, at this | 544 | * Get the signal to deliver. When running under ptrace, at this |
558 | * point the debugger may change all our registers ... | 545 | * point the debugger may change all our registers ... |
559 | */ | 546 | */ |
560 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | ||
561 | /* | 547 | /* |
562 | * Depending on the signal settings we may need to revert the | 548 | * Depending on the signal settings we may need to revert the |
563 | * decision to restart the system call. But skip this if a | 549 | * decision to restart the system call. But skip this if a |
564 | * debugger has chosen to restart at a different PC. | 550 | * debugger has chosen to restart at a different PC. |
565 | */ | 551 | */ |
566 | if (regs->ARM_pc != restart_addr) | 552 | if (get_signal(&ksig)) { |
567 | restart = 0; | 553 | /* handler */ |
568 | if (signr > 0) { | 554 | if (unlikely(restart) && regs->ARM_pc == restart_addr) { |
569 | if (unlikely(restart)) { | ||
570 | if (retval == -ERESTARTNOHAND || | 555 | if (retval == -ERESTARTNOHAND || |
571 | retval == -ERESTART_RESTARTBLOCK | 556 | retval == -ERESTART_RESTARTBLOCK |
572 | || (retval == -ERESTARTSYS | 557 | || (retval == -ERESTARTSYS |
573 | && !(ka.sa.sa_flags & SA_RESTART))) { | 558 | && !(ksig.ka.sa.sa_flags & SA_RESTART))) { |
574 | regs->ARM_r0 = -EINTR; | 559 | regs->ARM_r0 = -EINTR; |
575 | regs->ARM_pc = continue_addr; | 560 | regs->ARM_pc = continue_addr; |
576 | } | 561 | } |
577 | } | 562 | } |
578 | 563 | handle_signal(&ksig, regs); | |
579 | handle_signal(signr, &ka, &info, regs); | 564 | } else { |
580 | return 0; | 565 | /* no handler */ |
566 | restore_saved_sigmask(); | ||
567 | if (unlikely(restart) && regs->ARM_pc == restart_addr) { | ||
568 | regs->ARM_pc = continue_addr; | ||
569 | return restart; | ||
570 | } | ||
581 | } | 571 | } |
582 | 572 | return 0; | |
583 | restore_saved_sigmask(); | ||
584 | if (unlikely(restart)) | ||
585 | regs->ARM_pc = continue_addr; | ||
586 | return restart; | ||
587 | } | 573 | } |
588 | 574 | ||
589 | asmlinkage int | 575 | asmlinkage int |