.. | .. |
---|
| 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 |
---|