| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Kernel Probes (KProbes) |
|---|
| 3 | 4 | * arch/mips/kernel/kprobes.c |
|---|
| .. | .. |
|---|
| 8 | 9 | * Some portions copied from the powerpc version. |
|---|
| 9 | 10 | * |
|---|
| 10 | 11 | * Copyright (C) IBM Corporation, 2002, 2004 |
|---|
| 11 | | - * |
|---|
| 12 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 13 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 14 | | - * the Free Software Foundation; version 2 of the License. |
|---|
| 15 | | - * |
|---|
| 16 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 17 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 18 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 19 | | - * GNU General Public License for more details. |
|---|
| 20 | | - * |
|---|
| 21 | | - * You should have received a copy of the GNU General Public License |
|---|
| 22 | | - * along with this program; if not, write to the Free Software |
|---|
| 23 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 24 | 12 | */ |
|---|
| 25 | 13 | |
|---|
| 26 | 14 | #include <linux/kprobes.h> |
|---|
| .. | .. |
|---|
| 98 | 86 | goto out; |
|---|
| 99 | 87 | } |
|---|
| 100 | 88 | |
|---|
| 101 | | - if ((probe_kernel_read(&prev_insn, p->addr - 1, |
|---|
| 102 | | - sizeof(mips_instruction)) == 0) && |
|---|
| 103 | | - insn_has_delayslot(prev_insn)) { |
|---|
| 89 | + if (copy_from_kernel_nofault(&prev_insn, p->addr - 1, |
|---|
| 90 | + sizeof(mips_instruction)) == 0 && |
|---|
| 91 | + insn_has_delayslot(prev_insn)) { |
|---|
| 104 | 92 | pr_notice("Kprobes for branch delayslot are not supported\n"); |
|---|
| 105 | 93 | ret = -EINVAL; |
|---|
| 106 | 94 | goto out; |
|---|
| .. | .. |
|---|
| 232 | 220 | |
|---|
| 233 | 221 | unaligned: |
|---|
| 234 | 222 | pr_notice("%s: unaligned epc - sending SIGBUS.\n", current->comm); |
|---|
| 235 | | - force_sig(SIGBUS, current); |
|---|
| 223 | + force_sig(SIGBUS); |
|---|
| 236 | 224 | return -EFAULT; |
|---|
| 237 | 225 | |
|---|
| 238 | 226 | } |
|---|
| .. | .. |
|---|
| 410 | 398 | return 1; |
|---|
| 411 | 399 | } |
|---|
| 412 | 400 | |
|---|
| 413 | | -static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr) |
|---|
| 401 | +int kprobe_fault_handler(struct pt_regs *regs, int trapnr) |
|---|
| 414 | 402 | { |
|---|
| 415 | 403 | struct kprobe *cur = kprobe_running(); |
|---|
| 416 | 404 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
|---|
| .. | .. |
|---|
| 489 | 477 | struct pt_regs *regs) |
|---|
| 490 | 478 | { |
|---|
| 491 | 479 | ri->ret_addr = (kprobe_opcode_t *) regs->regs[31]; |
|---|
| 480 | + ri->fp = NULL; |
|---|
| 492 | 481 | |
|---|
| 493 | 482 | /* Replace the return addr with trampoline addr */ |
|---|
| 494 | 483 | regs->regs[31] = (unsigned long)kretprobe_trampoline; |
|---|
| .. | .. |
|---|
| 500 | 489 | static int __kprobes trampoline_probe_handler(struct kprobe *p, |
|---|
| 501 | 490 | struct pt_regs *regs) |
|---|
| 502 | 491 | { |
|---|
| 503 | | - struct kretprobe_instance *ri = NULL; |
|---|
| 504 | | - struct hlist_head *head, empty_rp; |
|---|
| 505 | | - struct hlist_node *tmp; |
|---|
| 506 | | - unsigned long flags, orig_ret_address = 0; |
|---|
| 507 | | - unsigned long trampoline_address = (unsigned long)kretprobe_trampoline; |
|---|
| 508 | | - |
|---|
| 509 | | - INIT_HLIST_HEAD(&empty_rp); |
|---|
| 510 | | - kretprobe_hash_lock(current, &head, &flags); |
|---|
| 511 | | - |
|---|
| 512 | | - /* |
|---|
| 513 | | - * It is possible to have multiple instances associated with a given |
|---|
| 514 | | - * task either because an multiple functions in the call path |
|---|
| 515 | | - * have a return probe installed on them, and/or more than one return |
|---|
| 516 | | - * return probe was registered for a target function. |
|---|
| 517 | | - * |
|---|
| 518 | | - * We can handle this because: |
|---|
| 519 | | - * - instances are always inserted at the head of the list |
|---|
| 520 | | - * - when multiple return probes are registered for the same |
|---|
| 521 | | - * function, the first instance's ret_addr will point to the |
|---|
| 522 | | - * real return address, and all the rest will point to |
|---|
| 523 | | - * kretprobe_trampoline |
|---|
| 524 | | - */ |
|---|
| 525 | | - hlist_for_each_entry_safe(ri, tmp, head, hlist) { |
|---|
| 526 | | - if (ri->task != current) |
|---|
| 527 | | - /* another task is sharing our hash bucket */ |
|---|
| 528 | | - continue; |
|---|
| 529 | | - |
|---|
| 530 | | - if (ri->rp && ri->rp->handler) |
|---|
| 531 | | - ri->rp->handler(ri, regs); |
|---|
| 532 | | - |
|---|
| 533 | | - orig_ret_address = (unsigned long)ri->ret_addr; |
|---|
| 534 | | - recycle_rp_inst(ri, &empty_rp); |
|---|
| 535 | | - |
|---|
| 536 | | - if (orig_ret_address != trampoline_address) |
|---|
| 537 | | - /* |
|---|
| 538 | | - * This is the real return address. Any other |
|---|
| 539 | | - * instances associated with this task are for |
|---|
| 540 | | - * other calls deeper on the call stack |
|---|
| 541 | | - */ |
|---|
| 542 | | - break; |
|---|
| 543 | | - } |
|---|
| 544 | | - |
|---|
| 545 | | - kretprobe_assert(ri, orig_ret_address, trampoline_address); |
|---|
| 546 | | - instruction_pointer(regs) = orig_ret_address; |
|---|
| 547 | | - |
|---|
| 548 | | - kretprobe_hash_unlock(current, &flags); |
|---|
| 549 | | - |
|---|
| 550 | | - hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) { |
|---|
| 551 | | - hlist_del(&ri->hlist); |
|---|
| 552 | | - kfree(ri); |
|---|
| 553 | | - } |
|---|
| 492 | + instruction_pointer(regs) = __kretprobe_trampoline_handler(regs, |
|---|
| 493 | + kretprobe_trampoline, NULL); |
|---|
| 554 | 494 | /* |
|---|
| 555 | 495 | * By returning a non-zero value, we are telling |
|---|
| 556 | 496 | * kprobe_handler() that we don't want the post_handler |
|---|