| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) |
|---|
| 3 | | - * |
|---|
| 4 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 5 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 6 | | - * published by the Free Software Foundation. |
|---|
| 7 | 4 | */ |
|---|
| 8 | 5 | |
|---|
| 9 | 6 | #include <linux/types.h> |
|---|
| .. | .. |
|---|
| 391 | 388 | { |
|---|
| 392 | 389 | |
|---|
| 393 | 390 | ri->ret_addr = (kprobe_opcode_t *) regs->blink; |
|---|
| 391 | + ri->fp = NULL; |
|---|
| 394 | 392 | |
|---|
| 395 | 393 | /* Replace the return addr with trampoline addr */ |
|---|
| 396 | 394 | regs->blink = (unsigned long)&kretprobe_trampoline; |
|---|
| .. | .. |
|---|
| 399 | 397 | static int __kprobes trampoline_probe_handler(struct kprobe *p, |
|---|
| 400 | 398 | struct pt_regs *regs) |
|---|
| 401 | 399 | { |
|---|
| 402 | | - struct kretprobe_instance *ri = NULL; |
|---|
| 403 | | - struct hlist_head *head, empty_rp; |
|---|
| 404 | | - struct hlist_node *tmp; |
|---|
| 405 | | - unsigned long flags, orig_ret_address = 0; |
|---|
| 406 | | - unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline; |
|---|
| 407 | | - |
|---|
| 408 | | - INIT_HLIST_HEAD(&empty_rp); |
|---|
| 409 | | - kretprobe_hash_lock(current, &head, &flags); |
|---|
| 410 | | - |
|---|
| 411 | | - /* |
|---|
| 412 | | - * It is possible to have multiple instances associated with a given |
|---|
| 413 | | - * task either because an multiple functions in the call path |
|---|
| 414 | | - * have a return probe installed on them, and/or more than one return |
|---|
| 415 | | - * return probe was registered for a target function. |
|---|
| 416 | | - * |
|---|
| 417 | | - * We can handle this because: |
|---|
| 418 | | - * - instances are always inserted at the head of the list |
|---|
| 419 | | - * - when multiple return probes are registered for the same |
|---|
| 420 | | - * function, the first instance's ret_addr will point to the |
|---|
| 421 | | - * real return address, and all the rest will point to |
|---|
| 422 | | - * kretprobe_trampoline |
|---|
| 423 | | - */ |
|---|
| 424 | | - hlist_for_each_entry_safe(ri, tmp, head, hlist) { |
|---|
| 425 | | - if (ri->task != current) |
|---|
| 426 | | - /* another task is sharing our hash bucket */ |
|---|
| 427 | | - continue; |
|---|
| 428 | | - |
|---|
| 429 | | - if (ri->rp && ri->rp->handler) |
|---|
| 430 | | - ri->rp->handler(ri, regs); |
|---|
| 431 | | - |
|---|
| 432 | | - orig_ret_address = (unsigned long)ri->ret_addr; |
|---|
| 433 | | - recycle_rp_inst(ri, &empty_rp); |
|---|
| 434 | | - |
|---|
| 435 | | - if (orig_ret_address != trampoline_address) { |
|---|
| 436 | | - /* |
|---|
| 437 | | - * This is the real return address. Any other |
|---|
| 438 | | - * instances associated with this task are for |
|---|
| 439 | | - * other calls deeper on the call stack |
|---|
| 440 | | - */ |
|---|
| 441 | | - break; |
|---|
| 442 | | - } |
|---|
| 443 | | - } |
|---|
| 444 | | - |
|---|
| 445 | | - kretprobe_assert(ri, orig_ret_address, trampoline_address); |
|---|
| 446 | | - regs->ret = orig_ret_address; |
|---|
| 447 | | - |
|---|
| 448 | | - kretprobe_hash_unlock(current, &flags); |
|---|
| 449 | | - |
|---|
| 450 | | - hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) { |
|---|
| 451 | | - hlist_del(&ri->hlist); |
|---|
| 452 | | - kfree(ri); |
|---|
| 453 | | - } |
|---|
| 400 | + regs->ret = __kretprobe_trampoline_handler(regs, &kretprobe_trampoline, NULL); |
|---|
| 454 | 401 | |
|---|
| 455 | 402 | /* By returning a non zero value, we are telling the kprobe handler |
|---|
| 456 | 403 | * that we don't want the post_handler to run |
|---|