diff options
| -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) |
