diff options
Diffstat (limited to 'arch/mips')
-rw-r--r-- | arch/mips/kernel/traps.c | 43 |
1 files changed, 22 insertions, 21 deletions
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 6eccfb49ae68..0ae19e1fa867 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c | |||
@@ -399,19 +399,6 @@ asmlinkage void do_be(struct pt_regs *regs) | |||
399 | force_sig(SIGBUS, current); | 399 | force_sig(SIGBUS, current); |
400 | } | 400 | } |
401 | 401 | ||
402 | static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode) | ||
403 | { | ||
404 | unsigned int __user *epc; | ||
405 | |||
406 | epc = (unsigned int __user *) regs->cp0_epc + | ||
407 | ((regs->cp0_cause & CAUSEF_BD) != 0); | ||
408 | if (!get_user(*opcode, epc)) | ||
409 | return 0; | ||
410 | |||
411 | force_sig(SIGSEGV, current); | ||
412 | return 1; | ||
413 | } | ||
414 | |||
415 | /* | 402 | /* |
416 | * ll/sc emulation | 403 | * ll/sc emulation |
417 | */ | 404 | */ |
@@ -546,8 +533,8 @@ static inline int simulate_llsc(struct pt_regs *regs) | |||
546 | { | 533 | { |
547 | unsigned int opcode; | 534 | unsigned int opcode; |
548 | 535 | ||
549 | if (unlikely(get_insn_opcode(regs, &opcode))) | 536 | if (get_user(opcode, (unsigned int __user *) exception_epc(regs))) |
550 | return -EFAULT; | 537 | goto out_sigsegv; |
551 | 538 | ||
552 | if ((opcode & OPCODE) == LL) { | 539 | if ((opcode & OPCODE) == LL) { |
553 | simulate_ll(regs, opcode); | 540 | simulate_ll(regs, opcode); |
@@ -559,6 +546,10 @@ static inline int simulate_llsc(struct pt_regs *regs) | |||
559 | } | 546 | } |
560 | 547 | ||
561 | return -EFAULT; /* Strange things going on ... */ | 548 | return -EFAULT; /* Strange things going on ... */ |
549 | |||
550 | out_sigsegv: | ||
551 | force_sig(SIGSEGV, current); | ||
552 | return -EFAULT; | ||
562 | } | 553 | } |
563 | 554 | ||
564 | /* | 555 | /* |
@@ -571,8 +562,8 @@ static inline int simulate_rdhwr(struct pt_regs *regs) | |||
571 | struct thread_info *ti = task_thread_info(current); | 562 | struct thread_info *ti = task_thread_info(current); |
572 | unsigned int opcode; | 563 | unsigned int opcode; |
573 | 564 | ||
574 | if (unlikely(get_insn_opcode(regs, &opcode))) | 565 | if (get_user(opcode, (unsigned int __user *) exception_epc(regs))) |
575 | return -EFAULT; | 566 | goto out_sigsegv; |
576 | 567 | ||
577 | if (unlikely(compute_return_epc(regs))) | 568 | if (unlikely(compute_return_epc(regs))) |
578 | return -EFAULT; | 569 | return -EFAULT; |
@@ -591,6 +582,10 @@ static inline int simulate_rdhwr(struct pt_regs *regs) | |||
591 | 582 | ||
592 | /* Not ours. */ | 583 | /* Not ours. */ |
593 | return -EFAULT; | 584 | return -EFAULT; |
585 | |||
586 | out_sigsegv: | ||
587 | force_sig(SIGSEGV, current); | ||
588 | return -EFAULT; | ||
594 | } | 589 | } |
595 | 590 | ||
596 | asmlinkage void do_ov(struct pt_regs *regs) | 591 | asmlinkage void do_ov(struct pt_regs *regs) |
@@ -676,8 +671,8 @@ asmlinkage void do_bp(struct pt_regs *regs) | |||
676 | 671 | ||
677 | die_if_kernel("Break instruction in kernel code", regs); | 672 | die_if_kernel("Break instruction in kernel code", regs); |
678 | 673 | ||
679 | if (get_insn_opcode(regs, &opcode)) | 674 | if (get_user(opcode, (unsigned int __user *) exception_epc(regs))) |
680 | return; | 675 | goto out_sigsegv; |
681 | 676 | ||
682 | /* | 677 | /* |
683 | * There is the ancient bug in the MIPS assemblers that the break | 678 | * There is the ancient bug in the MIPS assemblers that the break |
@@ -710,6 +705,9 @@ asmlinkage void do_bp(struct pt_regs *regs) | |||
710 | default: | 705 | default: |
711 | force_sig(SIGTRAP, current); | 706 | force_sig(SIGTRAP, current); |
712 | } | 707 | } |
708 | |||
709 | out_sigsegv: | ||
710 | force_sig(SIGSEGV, current); | ||
713 | } | 711 | } |
714 | 712 | ||
715 | asmlinkage void do_tr(struct pt_regs *regs) | 713 | asmlinkage void do_tr(struct pt_regs *regs) |
@@ -719,8 +717,8 @@ asmlinkage void do_tr(struct pt_regs *regs) | |||
719 | 717 | ||
720 | die_if_kernel("Trap instruction in kernel code", regs); | 718 | die_if_kernel("Trap instruction in kernel code", regs); |
721 | 719 | ||
722 | if (get_insn_opcode(regs, &opcode)) | 720 | if (get_user(opcode, (unsigned int __user *) exception_epc(regs))) |
723 | return; | 721 | goto out_sigsegv; |
724 | 722 | ||
725 | /* Immediate versions don't provide a code. */ | 723 | /* Immediate versions don't provide a code. */ |
726 | if (!(opcode & OPCODE)) | 724 | if (!(opcode & OPCODE)) |
@@ -747,6 +745,9 @@ asmlinkage void do_tr(struct pt_regs *regs) | |||
747 | default: | 745 | default: |
748 | force_sig(SIGTRAP, current); | 746 | force_sig(SIGTRAP, current); |
749 | } | 747 | } |
748 | |||
749 | out_sigsegv: | ||
750 | force_sig(SIGSEGV, current); | ||
750 | } | 751 | } |
751 | 752 | ||
752 | asmlinkage void do_ri(struct pt_regs *regs) | 753 | asmlinkage void do_ri(struct pt_regs *regs) |