From: dave.long@linaro.org (David Long)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v13 09/10] arm64: Add kernel return probes support (kretprobes)
Date: Wed, 22 Jun 2016 14:16:25 -0400 [thread overview]
Message-ID: <576AD5F9.9090905@linaro.org> (raw)
In-Reply-To: <20160607192836.20d94e0838ef72ebc729a054@kernel.org>
On 06/07/2016 06:28 AM, Masami Hiramatsu wrote:
> On Thu, 2 Jun 2016 23:26:23 -0400
> David Long <dave.long@linaro.org> wrote:
>
>> From: Sandeepa Prabhu <sandeepa.s.prabhu@gmail.com>
>>
>> The pre-handler of this special 'trampoline' kprobe executes the return
>> probe handler functions and restores original return address in ELR_EL1.
>> This way the saved pt_regs still hold the original register context to be
>> carried back to the probed kernel function.
>>
>> Signed-off-by: Sandeepa Prabhu <sandeepa.s.prabhu@gmail.com>
>> Signed-off-by: David A. Long <dave.long@linaro.org>
>> ---
>> arch/arm64/Kconfig | 1 +
>> arch/arm64/kernel/kprobes.c | 75 ++++++++++++++++++++++++++++++++++++++++++++-
>> 2 files changed, 75 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 5496b75..47989eb 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -89,6 +89,7 @@ config ARM64
>> select HAVE_RCU_TABLE_FREE
>> select HAVE_SYSCALL_TRACEPOINTS
>> select HAVE_KPROBES
>> + select HAVE_KRETPROBES if HAVE_KPROBES
>> select IOMMU_DMA if IOMMU_SUPPORT
>> select IRQ_DOMAIN
>> select IRQ_FORCED_THREADING
>> diff --git a/arch/arm64/kernel/kprobes.c b/arch/arm64/kernel/kprobes.c
>> index b35f76f..c116904 100644
>> --- a/arch/arm64/kernel/kprobes.c
>> +++ b/arch/arm64/kernel/kprobes.c
>> @@ -577,7 +577,80 @@ bool arch_within_kprobe_blacklist(unsigned long addr)
>>
>> void __kprobes __used *trampoline_probe_handler(struct pt_regs *regs)
>> {
>> - return NULL;
>> + struct kretprobe_instance *ri = NULL;
>> + struct hlist_head *head, empty_rp;
>> + struct hlist_node *tmp;
>> + unsigned long flags, orig_ret_addr = 0;
>> + unsigned long trampoline_address =
>> + (unsigned long)&kretprobe_trampoline;
>> +
>> + INIT_HLIST_HEAD(&empty_rp);
>> + kretprobe_hash_lock(current, &head, &flags);
>> +
>> + /*
>> + * It is possible to have multiple instances associated with a given
>> + * task either because multiple functions in the call path have
>> + * a return probe installed on them, and/or more than one return
>> + * probe was registered for a target function.
>> + *
>> + * We can handle this because:
>> + * - instances are always inserted at the head of the list
>> + * - when multiple return probes are registered for the same
>> + * function, the first instance's ret_addr will point to the
>> + * real return address, and all the rest will point to
>> + * kretprobe_trampoline
>> + */
>> + hlist_for_each_entry_safe(ri, tmp, head, hlist) {
>> + if (ri->task != current)
>> + /* another task is sharing our hash bucket */
>> + continue;
>> +
>> + if (ri->rp && ri->rp->handler) {
>> + __this_cpu_write(current_kprobe, &ri->rp->kp);
>> + get_kprobe_ctlblk()->kprobe_status = KPROBE_HIT_ACTIVE;
>> + ri->rp->handler(ri, regs);
>> + __this_cpu_write(current_kprobe, NULL);
>> + }
>> +
>> + orig_ret_addr = (unsigned long)ri->ret_addr;
>> + recycle_rp_inst(ri, &empty_rp);
>> +
>> + if (orig_ret_addr != trampoline_address)
>> + /*
>> + * This is the real return address. Any other
>> + * instances associated with this task are for
>> + * other calls deeper on the call stack
>> + */
>> + break;
>> + }
>
> This looks not included an improvement done by Syuhei, see
> commit 737480a0d525 ("kprobes/x86: Fix the return address of multiple kretprobes")
>
> Thank you!
>
I've updated the relevant part of this function with the current x86
version of the code.
>> +
>> + kretprobe_assert(ri, orig_ret_addr, trampoline_address);
>> + /* restore the original return address */
>> + instruction_pointer(regs) = orig_ret_addr;
>> + reset_current_kprobe();
>> + kretprobe_hash_unlock(current, &flags);
>> +
>> + hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
>> + hlist_del(&ri->hlist);
>> + kfree(ri);
>> + }
>> +
>> + /* return 1 so that post handlers not called */
>> + return (void *) orig_ret_addr;
>> +}
>> +
>> +void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
>> + struct pt_regs *regs)
>> +{
>> + ri->ret_addr = (kprobe_opcode_t *)regs->regs[30];
>> +
>> + /* replace return addr (x30) with trampoline */
>> + regs->regs[30] = (long)&kretprobe_trampoline;
>> +}
>> +
>> +int __kprobes arch_trampoline_kprobe(struct kprobe *p)
>> +{
>> + return 0;
>> }
>>
>> int __init arch_init_kprobes(void)
>> --
>> 2.5.0
>>
>
>
Thanks,
-dl
WARNING: multiple messages have this Message-ID (diff)
From: David Long <dave.long@linaro.org>
To: Masami Hiramatsu <mhiramat@kernel.org>
Cc: "Catalin Marinas" <catalin.marinas@arm.com>,
"Huang Shijie" <shijie.huang@arm.com>,
"James Morse" <james.morse@arm.com>,
"Marc Zyngier" <marc.zyngier@arm.com>,
"Pratyush Anand" <panand@redhat.com>,
"Sandeepa Prabhu" <sandeepa.s.prabhu@gmail.com>,
"Will Deacon" <will.deacon@arm.com>,
"William Cohen" <wcohen@redhat.com>,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org,
"Steve Capper" <steve.capper@linaro.org>,
"Li Bin" <huawei.libin@huawei.com>,
"Adam Buchbinder" <adam.buchbinder@gmail.com>,
"Alex Bennée" <alex.bennee@linaro.org>,
"Andrew Morton" <akpm@linux-foundation.org>,
"Andrey Ryabinin" <ryabinin.a.a@gmail.com>,
"Ard Biesheuvel" <ard.biesheuvel@linaro.org>,
"Christoffer Dall" <christoffer.dall@linaro.org>,
"Daniel Thompson" <daniel.thompson@linaro.org>,
"Dave P Martin" <Dave.Martin@arm.com>,
"Jens Wiklander" <jens.wiklander@linaro.org>,
"Jisheng Zhang" <jszhang@marvell.com>,
"John Blackwood" <john.blackwood@ccur.com>,
"Mark Rutland" <mark.rutland@arm.com>,
"Petr Mladek" <pmladek@suse.com>,
"Robin Murphy" <robin.murphy@arm.com>,
"Suzuki K Poulose" <suzuki.poulose@arm.com>,
"Vladimir Murzin" <Vladimir.Murzin@arm.com>,
"Yang Shi" <yang.shi@linaro.org>,
"Zi Shen Lim" <zlim.lnx@gmail.com>,
"yalin wang" <yalin.wang2010@gmail.com>,
"Mark Brown" <broonie@kernel.org>
Subject: Re: [PATCH v13 09/10] arm64: Add kernel return probes support (kretprobes)
Date: Wed, 22 Jun 2016 14:16:25 -0400 [thread overview]
Message-ID: <576AD5F9.9090905@linaro.org> (raw)
In-Reply-To: <20160607192836.20d94e0838ef72ebc729a054@kernel.org>
On 06/07/2016 06:28 AM, Masami Hiramatsu wrote:
> On Thu, 2 Jun 2016 23:26:23 -0400
> David Long <dave.long@linaro.org> wrote:
>
>> From: Sandeepa Prabhu <sandeepa.s.prabhu@gmail.com>
>>
>> The pre-handler of this special 'trampoline' kprobe executes the return
>> probe handler functions and restores original return address in ELR_EL1.
>> This way the saved pt_regs still hold the original register context to be
>> carried back to the probed kernel function.
>>
>> Signed-off-by: Sandeepa Prabhu <sandeepa.s.prabhu@gmail.com>
>> Signed-off-by: David A. Long <dave.long@linaro.org>
>> ---
>> arch/arm64/Kconfig | 1 +
>> arch/arm64/kernel/kprobes.c | 75 ++++++++++++++++++++++++++++++++++++++++++++-
>> 2 files changed, 75 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 5496b75..47989eb 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -89,6 +89,7 @@ config ARM64
>> select HAVE_RCU_TABLE_FREE
>> select HAVE_SYSCALL_TRACEPOINTS
>> select HAVE_KPROBES
>> + select HAVE_KRETPROBES if HAVE_KPROBES
>> select IOMMU_DMA if IOMMU_SUPPORT
>> select IRQ_DOMAIN
>> select IRQ_FORCED_THREADING
>> diff --git a/arch/arm64/kernel/kprobes.c b/arch/arm64/kernel/kprobes.c
>> index b35f76f..c116904 100644
>> --- a/arch/arm64/kernel/kprobes.c
>> +++ b/arch/arm64/kernel/kprobes.c
>> @@ -577,7 +577,80 @@ bool arch_within_kprobe_blacklist(unsigned long addr)
>>
>> void __kprobes __used *trampoline_probe_handler(struct pt_regs *regs)
>> {
>> - return NULL;
>> + struct kretprobe_instance *ri = NULL;
>> + struct hlist_head *head, empty_rp;
>> + struct hlist_node *tmp;
>> + unsigned long flags, orig_ret_addr = 0;
>> + unsigned long trampoline_address =
>> + (unsigned long)&kretprobe_trampoline;
>> +
>> + INIT_HLIST_HEAD(&empty_rp);
>> + kretprobe_hash_lock(current, &head, &flags);
>> +
>> + /*
>> + * It is possible to have multiple instances associated with a given
>> + * task either because multiple functions in the call path have
>> + * a return probe installed on them, and/or more than one return
>> + * probe was registered for a target function.
>> + *
>> + * We can handle this because:
>> + * - instances are always inserted at the head of the list
>> + * - when multiple return probes are registered for the same
>> + * function, the first instance's ret_addr will point to the
>> + * real return address, and all the rest will point to
>> + * kretprobe_trampoline
>> + */
>> + hlist_for_each_entry_safe(ri, tmp, head, hlist) {
>> + if (ri->task != current)
>> + /* another task is sharing our hash bucket */
>> + continue;
>> +
>> + if (ri->rp && ri->rp->handler) {
>> + __this_cpu_write(current_kprobe, &ri->rp->kp);
>> + get_kprobe_ctlblk()->kprobe_status = KPROBE_HIT_ACTIVE;
>> + ri->rp->handler(ri, regs);
>> + __this_cpu_write(current_kprobe, NULL);
>> + }
>> +
>> + orig_ret_addr = (unsigned long)ri->ret_addr;
>> + recycle_rp_inst(ri, &empty_rp);
>> +
>> + if (orig_ret_addr != trampoline_address)
>> + /*
>> + * This is the real return address. Any other
>> + * instances associated with this task are for
>> + * other calls deeper on the call stack
>> + */
>> + break;
>> + }
>
> This looks not included an improvement done by Syuhei, see
> commit 737480a0d525 ("kprobes/x86: Fix the return address of multiple kretprobes")
>
> Thank you!
>
I've updated the relevant part of this function with the current x86
version of the code.
>> +
>> + kretprobe_assert(ri, orig_ret_addr, trampoline_address);
>> + /* restore the original return address */
>> + instruction_pointer(regs) = orig_ret_addr;
>> + reset_current_kprobe();
>> + kretprobe_hash_unlock(current, &flags);
>> +
>> + hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
>> + hlist_del(&ri->hlist);
>> + kfree(ri);
>> + }
>> +
>> + /* return 1 so that post handlers not called */
>> + return (void *) orig_ret_addr;
>> +}
>> +
>> +void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
>> + struct pt_regs *regs)
>> +{
>> + ri->ret_addr = (kprobe_opcode_t *)regs->regs[30];
>> +
>> + /* replace return addr (x30) with trampoline */
>> + regs->regs[30] = (long)&kretprobe_trampoline;
>> +}
>> +
>> +int __kprobes arch_trampoline_kprobe(struct kprobe *p)
>> +{
>> + return 0;
>> }
>>
>> int __init arch_init_kprobes(void)
>> --
>> 2.5.0
>>
>
>
Thanks,
-dl
next prev parent reply other threads:[~2016-06-22 18:16 UTC|newest]
Thread overview: 72+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-06-03 3:26 [PATCH v13 00/10] arm64: Add kernel probes (kprobes) support David Long
2016-06-03 3:26 ` David Long
2016-06-03 3:26 ` [PATCH v13 01/10] arm64: Add HAVE_REGS_AND_STACK_ACCESS_API feature David Long
2016-06-03 3:26 ` David Long
2016-06-03 11:36 ` Masami Hiramatsu
2016-06-03 11:36 ` Masami Hiramatsu
2016-06-20 2:43 ` Li Bin
2016-06-20 2:43 ` Li Bin
2016-06-23 13:48 ` David Long
2016-06-23 13:48 ` David Long
2016-06-03 3:26 ` [PATCH v13 02/10] arm64: Add more test functions to insn.c David Long
2016-06-03 3:26 ` David Long
2016-06-08 1:14 ` Masami Hiramatsu
2016-06-08 1:14 ` Masami Hiramatsu
2016-06-10 14:54 ` David Long
2016-06-10 14:54 ` David Long
2016-06-03 3:26 ` [PATCH v13 03/10] arm64: add conditional instruction simulation support David Long
2016-06-03 3:26 ` David Long
2016-06-04 3:53 ` Masami Hiramatsu
2016-06-04 3:53 ` Masami Hiramatsu
2016-06-13 4:19 ` David Long
2016-06-13 4:19 ` David Long
2016-06-03 3:26 ` [PATCH v13 04/10] arm64: Blacklist non-kprobe-able symbol David Long
2016-06-03 3:26 ` David Long
2016-06-04 3:40 ` Masami Hiramatsu
2016-06-04 3:40 ` Masami Hiramatsu
2016-06-07 3:52 ` David Long
2016-06-07 3:52 ` David Long
2016-06-10 19:16 ` David Long
2016-06-10 19:16 ` David Long
2016-06-03 3:26 ` [PATCH v13 05/10] arm64: Kprobes with single stepping support David Long
2016-06-03 3:26 ` David Long
2016-06-08 1:07 ` Masami Hiramatsu
2016-06-08 1:07 ` Masami Hiramatsu
2016-06-13 4:10 ` David Long
2016-06-13 4:10 ` David Long
2016-06-13 6:50 ` Masami Hiramatsu
2016-06-13 6:50 ` Masami Hiramatsu
2016-06-13 15:22 ` David Long
2016-06-13 15:22 ` David Long
2016-06-14 0:45 ` Masami Hiramatsu
2016-06-14 0:45 ` Masami Hiramatsu
2016-06-22 18:28 ` David Long
2016-06-22 18:28 ` David Long
2016-06-14 1:42 ` Masami Hiramatsu
2016-06-14 1:42 ` Masami Hiramatsu
2016-06-03 3:26 ` [PATCH v13 06/10] arm64: Treat all entry code as non-kprobe-able David Long
2016-06-03 3:26 ` David Long
2016-06-07 0:34 ` Masami Hiramatsu
2016-06-07 0:34 ` Masami Hiramatsu
2016-06-03 3:26 ` [PATCH v13 07/10] arm64: kprobes instruction simulation support David Long
2016-06-03 3:26 ` David Long
2016-06-03 3:26 ` [PATCH v13 08/10] arm64: Add trampoline code for kretprobes David Long
2016-06-03 3:26 ` David Long
2016-06-07 10:38 ` Masami Hiramatsu
2016-06-07 10:38 ` Masami Hiramatsu
2016-06-13 4:23 ` David Long
2016-06-13 4:23 ` David Long
2016-06-03 3:26 ` [PATCH v13 09/10] arm64: Add kernel return probes support (kretprobes) David Long
2016-06-03 3:26 ` David Long
2016-06-07 10:28 ` Masami Hiramatsu
2016-06-07 10:28 ` Masami Hiramatsu
2016-06-22 18:16 ` David Long [this message]
2016-06-22 18:16 ` David Long
2016-06-03 3:26 ` [PATCH v13 10/10] kprobes: Add arm64 case in kprobe example module David Long
2016-06-03 3:26 ` David Long
2016-06-07 10:12 ` Masami Hiramatsu
2016-06-07 10:12 ` Masami Hiramatsu
2016-06-08 5:49 ` Huang Shijie
2016-06-08 5:49 ` Huang Shijie
2016-06-27 2:54 ` David Long
2016-06-27 2:54 ` David Long
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=576AD5F9.9090905@linaro.org \
--to=dave.long@linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.