diff mbox series

[v2,2/3] kprobes: adjust kprobe addr for KPROBES_ON_FTRACE

Message ID 20190820114224.0c8963c4@xhacker.debian (mailing list archive)
State New, archived
Headers show
Series arm64: KPROBES_ON_FTRACE | expand

Commit Message

Jisheng Zhang Aug. 20, 2019, 3:53 a.m. UTC
For KPROBES_ON_FTRACE case, we need to adjust the kprobe's addr
correspondingly.

Signed-off-by: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
---
 kernel/kprobes.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

Comments

Naveen N. Rao Aug. 20, 2019, 10:15 a.m. UTC | #1
Jisheng Zhang wrote:
> For KPROBES_ON_FTRACE case, we need to adjust the kprobe's addr
> correspondingly.
> 
> Signed-off-by: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
> ---
>  kernel/kprobes.c | 10 +++++++---
>  1 file changed, 7 insertions(+), 3 deletions(-)
> 
> diff --git a/kernel/kprobes.c b/kernel/kprobes.c
> index 9873fc627d61..3fd2f68644da 100644
> --- a/kernel/kprobes.c
> +++ b/kernel/kprobes.c
> @@ -1484,15 +1484,19 @@ static inline int check_kprobe_rereg(struct kprobe *p)
>  
>  int __weak arch_check_ftrace_location(struct kprobe *p)
>  {
> -	unsigned long ftrace_addr;
> +	unsigned long ftrace_addr, addr = (unsigned long)p->addr;
>  
> -	ftrace_addr = ftrace_location((unsigned long)p->addr);
> +#ifdef CONFIG_KPROBES_ON_FTRACE
> +	addr = ftrace_call_adjust(addr);
> +#endif

Looking at the commit message for patch 3/3, it looks like you want the 
probe to be placed on ftrace entry by default, and this patch seems to 
be aimed at that.

If so, this is not the right approach. As I mentioned previously, you 
would want to over-ride kprobe_lookup_name(). This ensures that the 
address is changed only if the user provided a symbol, and not if the 
user wanted to probe at a very specific address. See commit 
24bd909e94776 ("powerpc/kprobes: Prefer ftrace when probing function 
entry").

If this patch is for some other purpose, then it isn't clear from the 
commit log. Please provide a better explanation.


- Naveen
Jisheng Zhang Aug. 20, 2019, 10:41 a.m. UTC | #2
On Tue, 20 Aug 2019 15:45:24 +0530 "Naveen N. Rao" wrote:

> 
> 
> Jisheng Zhang wrote:
> > For KPROBES_ON_FTRACE case, we need to adjust the kprobe's addr
> > correspondingly.
> >
> > Signed-off-by: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
> > ---
> >  kernel/kprobes.c | 10 +++++++---
> >  1 file changed, 7 insertions(+), 3 deletions(-)
> >
> > diff --git a/kernel/kprobes.c b/kernel/kprobes.c
> > index 9873fc627d61..3fd2f68644da 100644
> > --- a/kernel/kprobes.c
> > +++ b/kernel/kprobes.c
> > @@ -1484,15 +1484,19 @@ static inline int check_kprobe_rereg(struct kprobe *p)
> >
> >  int __weak arch_check_ftrace_location(struct kprobe *p)
> >  {
> > -     unsigned long ftrace_addr;
> > +     unsigned long ftrace_addr, addr = (unsigned long)p->addr;
> >
> > -     ftrace_addr = ftrace_location((unsigned long)p->addr);
> > +#ifdef CONFIG_KPROBES_ON_FTRACE
> > +     addr = ftrace_call_adjust(addr);
> > +#endif  
> 
> Looking at the commit message for patch 3/3, it looks like you want the
> probe to be placed on ftrace entry by default, and this patch seems to
> be aimed at that.

Yeah.

> 
> If so, this is not the right approach. As I mentioned previously, you
> would want to over-ride kprobe_lookup_name(). This ensures that the
> address is changed only if the user provided a symbol, and not if the
> user wanted to probe at a very specific address. See commit

Great! Now I understand the reason.

> 24bd909e94776 ("powerpc/kprobes: Prefer ftrace when probing function
> entry").

Now, I got your meaning. You are right. I will update the patch in newer
version.

Thanks a lot!

> 
> If this patch is for some other purpose, then it isn't clear from the
> commit log. Please provide a better explanation.
> 
> 
> - Naveen
>
Masami Hiramatsu (Google) Aug. 21, 2019, 2:07 a.m. UTC | #3
Hi Jisheng,

On Tue, 20 Aug 2019 03:53:31 +0000
Jisheng Zhang <Jisheng.Zhang@synaptics.com> wrote:

> For KPROBES_ON_FTRACE case, we need to adjust the kprobe's addr
> correspondingly.

Either KPROBES_ON_FTRACE=y or not, ftrace_location() check must be
done correctly. If it failed, kprobes can modify the instruction
which can be modified by ftrace.

> 
> Signed-off-by: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
> ---
>  kernel/kprobes.c | 10 +++++++---
>  1 file changed, 7 insertions(+), 3 deletions(-)
> 
> diff --git a/kernel/kprobes.c b/kernel/kprobes.c
> index 9873fc627d61..3fd2f68644da 100644
> --- a/kernel/kprobes.c
> +++ b/kernel/kprobes.c
> @@ -1484,15 +1484,19 @@ static inline int check_kprobe_rereg(struct kprobe *p)
>  
>  int __weak arch_check_ftrace_location(struct kprobe *p)
>  {
> -	unsigned long ftrace_addr;
> +	unsigned long ftrace_addr, addr = (unsigned long)p->addr;
>  
> -	ftrace_addr = ftrace_location((unsigned long)p->addr);
> +#ifdef CONFIG_KPROBES_ON_FTRACE
> +	addr = ftrace_call_adjust(addr);
> +#endif
> +	ftrace_addr = ftrace_location(addr);

No, this is not right way to do. If we always need to adjust address
before calling ftrace_location(), something wrong with ftrace_location()
interface.
ftrace_location(addr) must check the address is within the range which
can be changed by ftrace. (dyn->ip <= addr <= dyn->ip+MCOUNT_INSN_SIZE)


>  	if (ftrace_addr) {
>  #ifdef CONFIG_KPROBES_ON_FTRACE
>  		/* Given address is not on the instruction boundary */
> -		if ((unsigned long)p->addr != ftrace_addr)
> +		if (addr != ftrace_addr)
>  			return -EILSEQ;
>  		p->flags |= KPROBE_FLAG_FTRACE;
> +		p->addr = (kprobe_opcode_t *)addr;

And again, please don't change the p->addr silently.

Thank you,

>  #else	/* !CONFIG_KPROBES_ON_FTRACE */
>  		return -EINVAL;
>  #endif
> -- 
> 2.23.0.rc1
>
Jisheng Zhang Aug. 21, 2019, 2:50 a.m. UTC | #4
Hi,

On Wed, 21 Aug 2019 11:07:39 +0900 Masami Hiramatsu wrote:

> 
> 
> Hi Jisheng,
> 
> On Tue, 20 Aug 2019 03:53:31 +0000
> Jisheng Zhang <Jisheng.Zhang@synaptics.com> wrote:
> 
> > For KPROBES_ON_FTRACE case, we need to adjust the kprobe's addr
> > correspondingly.  
> 
> Either KPROBES_ON_FTRACE=y or not, ftrace_location() check must be
> done correctly. If it failed, kprobes can modify the instruction
> which can be modified by ftrace.
> 
> >
> > Signed-off-by: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
> > ---
> >  kernel/kprobes.c | 10 +++++++---
> >  1 file changed, 7 insertions(+), 3 deletions(-)
> >
> > diff --git a/kernel/kprobes.c b/kernel/kprobes.c
> > index 9873fc627d61..3fd2f68644da 100644
> > --- a/kernel/kprobes.c
> > +++ b/kernel/kprobes.c
> > @@ -1484,15 +1484,19 @@ static inline int check_kprobe_rereg(struct kprobe *p)
> >
> >  int __weak arch_check_ftrace_location(struct kprobe *p)
> >  {
> > -     unsigned long ftrace_addr;
> > +     unsigned long ftrace_addr, addr = (unsigned long)p->addr;
> >
> > -     ftrace_addr = ftrace_location((unsigned long)p->addr);
> > +#ifdef CONFIG_KPROBES_ON_FTRACE
> > +     addr = ftrace_call_adjust(addr);
> > +#endif
> > +     ftrace_addr = ftrace_location(addr);  
> 
> No, this is not right way to do. If we always need to adjust address
> before calling ftrace_location(), something wrong with ftrace_location()
> interface.
> ftrace_location(addr) must check the address is within the range which
> can be changed by ftrace. (dyn->ip <= addr <= dyn->ip+MCOUNT_INSN_SIZE)

yeah! I will try Naveen's suggestion, I.E patch kprobe_lookup_name() instead.

Thanks

> 
> 
> >       if (ftrace_addr) {
> >  #ifdef CONFIG_KPROBES_ON_FTRACE
> >               /* Given address is not on the instruction boundary */
> > -             if ((unsigned long)p->addr != ftrace_addr)
> > +             if (addr != ftrace_addr)
> >                       return -EILSEQ;
> >               p->flags |= KPROBE_FLAG_FTRACE;
> > +             p->addr = (kprobe_opcode_t *)addr;  
> 
> And again, please don't change the p->addr silently.
> 
> Thank you,
> 
> >  #else        /* !CONFIG_KPROBES_ON_FTRACE */
> >               return -EINVAL;
> >  #endif
> > --
> > 2.23.0.rc1
> >  
> 
> 
> --
> Masami Hiramatsu <mhiramat@kernel.org>
diff mbox series

Patch

diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 9873fc627d61..3fd2f68644da 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1484,15 +1484,19 @@  static inline int check_kprobe_rereg(struct kprobe *p)
 
 int __weak arch_check_ftrace_location(struct kprobe *p)
 {
-	unsigned long ftrace_addr;
+	unsigned long ftrace_addr, addr = (unsigned long)p->addr;
 
-	ftrace_addr = ftrace_location((unsigned long)p->addr);
+#ifdef CONFIG_KPROBES_ON_FTRACE
+	addr = ftrace_call_adjust(addr);
+#endif
+	ftrace_addr = ftrace_location(addr);
 	if (ftrace_addr) {
 #ifdef CONFIG_KPROBES_ON_FTRACE
 		/* Given address is not on the instruction boundary */
-		if ((unsigned long)p->addr != ftrace_addr)
+		if (addr != ftrace_addr)
 			return -EILSEQ;
 		p->flags |= KPROBE_FLAG_FTRACE;
+		p->addr = (kprobe_opcode_t *)addr;
 #else	/* !CONFIG_KPROBES_ON_FTRACE */
 		return -EINVAL;
 #endif