aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2012-11-07 17:53:13 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2013-02-14 09:21:16 -0500
commit7e243643dffbe216dbcb10933c4cafde0f95f537 (patch)
tree9bde297bb075b0331aec04b9d944b0e612d413bd
parentcfd60c0789f395aa5564985177e3b4dab21974e1 (diff)
arm: switch to struct ksignal * passing
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--arch/arm/kernel/signal.c108
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
320static inline void __user * 320static inline void __user *
321get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, int framesize) 321get_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 */
343static 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
346static int 351static int
347setup_return(struct pt_regs *regs, struct k_sigaction *ka, 352setup_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
421static int 426static int
422setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *regs) 427setup_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
442static int 447static int
443setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, 448setup_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 */
478static void 482static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
479handle_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,
523static int do_signal(struct pt_regs *regs, int syscall) 512static 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
589asmlinkage int 575asmlinkage int