From: Stephen Brennan <stephen.s.brennan@oracle.com>
To: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Steven Rostedt <rostedt@goodmis.org>,
Mark Rutland <mark.rutland@arm.com>, Guo Ren <guoren@kernel.org>,
Huacai Chen <chenhuacai@kernel.org>,
WANG Xuerui <kernel@xen0n.name>,
"James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>,
Helge Deller <deller@gmx.de>,
Michael Ellerman <mpe@ellerman.id.au>,
Nicholas Piggin <npiggin@gmail.com>,
Christophe Leroy <christophe.leroy@csgroup.eu>,
"Aneesh Kumar K.V" <aneesh.kumar@kernel.org>,
"Naveen N. Rao" <naveen.n.rao@linux.ibm.com>,
Paul Walmsley <paul.walmsley@sifive.com>,
Palmer Dabbelt <palmer@dabbelt.com>,
Albert Ou <aou@eecs.berkeley.edu>,
Heiko Carstens <hca@linux.ibm.com>,
Vasily Gorbik <gor@linux.ibm.com>,
Alexander Gordeev <agordeev@linux.ibm.com>,
Christian Borntraeger <borntraeger@linux.ibm.com>,
Sven Schnelle <svens@linux.ibm.com>,
Thomas Gleixner <tglx@linutronix.de>,
Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
Dave Hansen <dave.hansen@linux.intel.com>,
x86@kernel.org, "H. Peter Anvin" <hpa@zytor.com>,
linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org,
linux-csky@vger.kernel.org, loongarch@lists.linux.dev,
linux-parisc@vger.kernel.org, linuxppc-dev@lists.ozlabs.org,
linux-riscv@lists.infradead.org, linux-s390@vger.kernel.org
Subject: Re: [PATCH] kprobe/ftrace: bail out if ftrace was killed
Date: Mon, 29 Apr 2024 10:47:26 -0700 [thread overview]
Message-ID: <87jzkgawnl.fsf@oracle.com> (raw)
In-Reply-To: <20240429224803.49d420b514e22d51412e1602@kernel.org>
Masami Hiramatsu (Google) <mhiramat@kernel.org> writes:
> Hi Stephen,
>
> On Fri, 26 Apr 2024 15:58:34 -0700
> Stephen Brennan <stephen.s.brennan@oracle.com> wrote:
>
>> If an error happens in ftrace, ftrace_kill() will prevent disarming
>> kprobes. Eventually, the ftrace_ops associated with the kprobes will be
>> freed, yet the kprobes will still be active, and when triggered, they
>> will use the freed memory, likely resulting in a page fault and panic.
>
> Hmm, indeed.
>
>>
>> This behavior can be reproduced quite easily, by creating a kprobe and
>> then triggering a ftrace_kill(). For simplicity, we can simulate an
>> ftrace error with a kernel module like [1]:
>>
>> [1]: https://github.com/brenns10/kernel_stuff/tree/master/ftrace_killer
>>
>> sudo perf probe --add commit_creds
>> sudo perf trace -e probe:commit_creds
>> # In another terminal
>> make
>> sudo insmod ftrace_killer.ko # calls ftrace_kill(), simulating bug
>> # Back to perf terminal
>> # ctrl-c
>> sudo perf probe --del commit_creds
>>
>> After a short period, a page fault and panic would occur as the kprobe
>> continues to execute and uses the freed ftrace_ops. While ftrace_kill()
>> is supposed to be used only in extreme circumstances, it is invoked in
>> FTRACE_WARN_ON() and so there are many places where an unexpected bug
>> could be triggered, yet the system may continue operating, possibly
>> without the administrator noticing. If ftrace_kill() does not panic the
>> system, then we should do everything we can to continue operating,
>> rather than leave a ticking time bomb.
>
> OK, the patch looks good to me.
>
> Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
>
> Thanks!
Hi Masami,
Thank you! Sadly I took a second look at the patch and noticed I forgot
to remove the existing declarations of ftrace_is_dead() from
kernel/trace/trace.h. I've sent v2 in reply to v1 in order to correct
that. I'm sorry for the churn.
Thanks,
Stephen
>>
>> Signed-off-by: Stephen Brennan <stephen.s.brennan@oracle.com>
>> ---
>>
>> Apologies for the wide net cast here. I recognize that a change like this
>> may need to be split up and go through arch-specific trees. I hoped to get
>> feedback on the patch itself. If it's satisfactory and the architecture
>> maintainers prefer it split out, I'm glad to do it. Thanks!
>>
>> arch/csky/kernel/probes/ftrace.c | 3 +++
>> arch/loongarch/kernel/ftrace_dyn.c | 3 +++
>> arch/parisc/kernel/ftrace.c | 3 +++
>> arch/powerpc/kernel/kprobes-ftrace.c | 3 +++
>> arch/riscv/kernel/probes/ftrace.c | 3 +++
>> arch/s390/kernel/ftrace.c | 3 +++
>> arch/x86/kernel/kprobes/ftrace.c | 3 +++
>> include/linux/ftrace.h | 2 ++
>> 8 files changed, 23 insertions(+)
>>
>> diff --git a/arch/csky/kernel/probes/ftrace.c b/arch/csky/kernel/probes/ftrace.c
>> index 834cffcfbce3..3931bf9f707b 100644
>> --- a/arch/csky/kernel/probes/ftrace.c
>> +++ b/arch/csky/kernel/probes/ftrace.c
>> @@ -12,6 +12,9 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
>> struct kprobe_ctlblk *kcb;
>> struct pt_regs *regs;
>>
>> + if (unlikely(ftrace_is_dead()))
>> + return;
>> +
>> bit = ftrace_test_recursion_trylock(ip, parent_ip);
>> if (bit < 0)
>> return;
>> diff --git a/arch/loongarch/kernel/ftrace_dyn.c b/arch/loongarch/kernel/ftrace_dyn.c
>> index 73858c9029cc..82c952cb5be0 100644
>> --- a/arch/loongarch/kernel/ftrace_dyn.c
>> +++ b/arch/loongarch/kernel/ftrace_dyn.c
>> @@ -287,6 +287,9 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
>> struct kprobe *p;
>> struct kprobe_ctlblk *kcb;
>>
>> + if (unlikely(ftrace_is_dead()))
>> + return;
>> +
>> bit = ftrace_test_recursion_trylock(ip, parent_ip);
>> if (bit < 0)
>> return;
>> diff --git a/arch/parisc/kernel/ftrace.c b/arch/parisc/kernel/ftrace.c
>> index 621a4b386ae4..3660834f54c3 100644
>> --- a/arch/parisc/kernel/ftrace.c
>> +++ b/arch/parisc/kernel/ftrace.c
>> @@ -206,6 +206,9 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
>> struct kprobe *p;
>> int bit;
>>
>> + if (unlikely(ftrace_is_dead()))
>> + return;
>> +
>> bit = ftrace_test_recursion_trylock(ip, parent_ip);
>> if (bit < 0)
>> return;
>> diff --git a/arch/powerpc/kernel/kprobes-ftrace.c b/arch/powerpc/kernel/kprobes-ftrace.c
>> index 072ebe7f290b..85eb55aa1457 100644
>> --- a/arch/powerpc/kernel/kprobes-ftrace.c
>> +++ b/arch/powerpc/kernel/kprobes-ftrace.c
>> @@ -21,6 +21,9 @@ void kprobe_ftrace_handler(unsigned long nip, unsigned long parent_nip,
>> struct pt_regs *regs;
>> int bit;
>>
>> + if (unlikely(ftrace_is_dead()))
>> + return;
>> +
>> bit = ftrace_test_recursion_trylock(nip, parent_nip);
>> if (bit < 0)
>> return;
>> diff --git a/arch/riscv/kernel/probes/ftrace.c b/arch/riscv/kernel/probes/ftrace.c
>> index 7142ec42e889..8814fbe4c888 100644
>> --- a/arch/riscv/kernel/probes/ftrace.c
>> +++ b/arch/riscv/kernel/probes/ftrace.c
>> @@ -11,6 +11,9 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
>> struct kprobe_ctlblk *kcb;
>> int bit;
>>
>> + if (unlikely(ftrace_is_dead()))
>> + return;
>> +
>> bit = ftrace_test_recursion_trylock(ip, parent_ip);
>> if (bit < 0)
>> return;
>> diff --git a/arch/s390/kernel/ftrace.c b/arch/s390/kernel/ftrace.c
>> index c46381ea04ec..ccbe8ccf945b 100644
>> --- a/arch/s390/kernel/ftrace.c
>> +++ b/arch/s390/kernel/ftrace.c
>> @@ -296,6 +296,9 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
>> struct kprobe *p;
>> int bit;
>>
>> + if (unlikely(ftrace_is_dead()))
>> + return;
>> +
>> bit = ftrace_test_recursion_trylock(ip, parent_ip);
>> if (bit < 0)
>> return;
>> diff --git a/arch/x86/kernel/kprobes/ftrace.c b/arch/x86/kernel/kprobes/ftrace.c
>> index dd2ec14adb77..c73f9ab7ff50 100644
>> --- a/arch/x86/kernel/kprobes/ftrace.c
>> +++ b/arch/x86/kernel/kprobes/ftrace.c
>> @@ -21,6 +21,9 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
>> struct kprobe_ctlblk *kcb;
>> int bit;
>>
>> + if (unlikely(ftrace_is_dead()))
>> + return;
>> +
>> bit = ftrace_test_recursion_trylock(ip, parent_ip);
>> if (bit < 0)
>> return;
>> diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
>> index 54d53f345d14..ba83e99c1fbe 100644
>> --- a/include/linux/ftrace.h
>> +++ b/include/linux/ftrace.h
>> @@ -399,6 +399,7 @@ int ftrace_lookup_symbols(const char **sorted_syms, size_t cnt, unsigned long *a
>> #define register_ftrace_function(ops) ({ 0; })
>> #define unregister_ftrace_function(ops) ({ 0; })
>> static inline void ftrace_kill(void) { }
>> +static inline int ftrace_is_dead(void) { return 0; }
>> static inline void ftrace_free_init_mem(void) { }
>> static inline void ftrace_free_mem(struct module *mod, void *start, void *end) { }
>> static inline int ftrace_lookup_symbols(const char **sorted_syms, size_t cnt, unsigned long *addrs)
>> @@ -914,6 +915,7 @@ static inline bool is_ftrace_trampoline(unsigned long addr)
>>
>> /* totally disable ftrace - can not re-enable after this */
>> void ftrace_kill(void);
>> +int ftrace_is_dead(void);
>>
>> static inline void tracer_disable(void)
>> {
>> --
>> 2.39.3
>>
>
>
> --
> Masami Hiramatsu (Google) <mhiramat@kernel.org>
WARNING: multiple messages have this Message-ID (diff)
From: Stephen Brennan <stephen.s.brennan@oracle.com>
To: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Steven Rostedt <rostedt@goodmis.org>,
Mark Rutland <mark.rutland@arm.com>, Guo Ren <guoren@kernel.org>,
Huacai Chen <chenhuacai@kernel.org>,
WANG Xuerui <kernel@xen0n.name>,
"James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>,
Helge Deller <deller@gmx.de>,
Michael Ellerman <mpe@ellerman.id.au>,
Nicholas Piggin <npiggin@gmail.com>,
Christophe Leroy <christophe.leroy@csgroup.eu>,
"Aneesh Kumar K.V" <aneesh.kumar@kernel.org>,
"Naveen N. Rao" <naveen.n.rao@linux.ibm.com>,
Paul Walmsley <paul.walmsley@sifive.com>,
Palmer Dabbelt <palmer@dabbelt.com>,
Albert Ou <aou@eecs.berkeley.edu>,
Heiko Carstens <hca@linux.ibm.com>,
Vasily Gorbik <gor@linux.ibm.com>,
Alexander Gordeev <agordeev@linux.ibm.com>,
Christian Borntraeger <borntraeger@linux.ibm.com>,
Sven Schnelle <svens@linux.ibm.com>,
Thomas Gleixner <tglx@linutronix.de>,
Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
Dave Hansen <dave.hansen@linux.intel.com>,
x86@kernel.org, "H. Peter Anvin" <hpa@zytor.com>,
linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org,
linux-csky@vger.kernel.org, loongarch@lists.linux.dev,
linux-parisc@vger.kernel.org, linuxppc-dev@lists.ozlabs.org,
linux-riscv@lists.infradead.org, linux-s390@vger.kernel.org
Subject: Re: [PATCH] kprobe/ftrace: bail out if ftrace was killed
Date: Mon, 29 Apr 2024 10:47:26 -0700 [thread overview]
Message-ID: <87jzkgawnl.fsf@oracle.com> (raw)
In-Reply-To: <20240429224803.49d420b514e22d51412e1602@kernel.org>
Masami Hiramatsu (Google) <mhiramat@kernel.org> writes:
> Hi Stephen,
>
> On Fri, 26 Apr 2024 15:58:34 -0700
> Stephen Brennan <stephen.s.brennan@oracle.com> wrote:
>
>> If an error happens in ftrace, ftrace_kill() will prevent disarming
>> kprobes. Eventually, the ftrace_ops associated with the kprobes will be
>> freed, yet the kprobes will still be active, and when triggered, they
>> will use the freed memory, likely resulting in a page fault and panic.
>
> Hmm, indeed.
>
>>
>> This behavior can be reproduced quite easily, by creating a kprobe and
>> then triggering a ftrace_kill(). For simplicity, we can simulate an
>> ftrace error with a kernel module like [1]:
>>
>> [1]: https://github.com/brenns10/kernel_stuff/tree/master/ftrace_killer
>>
>> sudo perf probe --add commit_creds
>> sudo perf trace -e probe:commit_creds
>> # In another terminal
>> make
>> sudo insmod ftrace_killer.ko # calls ftrace_kill(), simulating bug
>> # Back to perf terminal
>> # ctrl-c
>> sudo perf probe --del commit_creds
>>
>> After a short period, a page fault and panic would occur as the kprobe
>> continues to execute and uses the freed ftrace_ops. While ftrace_kill()
>> is supposed to be used only in extreme circumstances, it is invoked in
>> FTRACE_WARN_ON() and so there are many places where an unexpected bug
>> could be triggered, yet the system may continue operating, possibly
>> without the administrator noticing. If ftrace_kill() does not panic the
>> system, then we should do everything we can to continue operating,
>> rather than leave a ticking time bomb.
>
> OK, the patch looks good to me.
>
> Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
>
> Thanks!
Hi Masami,
Thank you! Sadly I took a second look at the patch and noticed I forgot
to remove the existing declarations of ftrace_is_dead() from
kernel/trace/trace.h. I've sent v2 in reply to v1 in order to correct
that. I'm sorry for the churn.
Thanks,
Stephen
>>
>> Signed-off-by: Stephen Brennan <stephen.s.brennan@oracle.com>
>> ---
>>
>> Apologies for the wide net cast here. I recognize that a change like this
>> may need to be split up and go through arch-specific trees. I hoped to get
>> feedback on the patch itself. If it's satisfactory and the architecture
>> maintainers prefer it split out, I'm glad to do it. Thanks!
>>
>> arch/csky/kernel/probes/ftrace.c | 3 +++
>> arch/loongarch/kernel/ftrace_dyn.c | 3 +++
>> arch/parisc/kernel/ftrace.c | 3 +++
>> arch/powerpc/kernel/kprobes-ftrace.c | 3 +++
>> arch/riscv/kernel/probes/ftrace.c | 3 +++
>> arch/s390/kernel/ftrace.c | 3 +++
>> arch/x86/kernel/kprobes/ftrace.c | 3 +++
>> include/linux/ftrace.h | 2 ++
>> 8 files changed, 23 insertions(+)
>>
>> diff --git a/arch/csky/kernel/probes/ftrace.c b/arch/csky/kernel/probes/ftrace.c
>> index 834cffcfbce3..3931bf9f707b 100644
>> --- a/arch/csky/kernel/probes/ftrace.c
>> +++ b/arch/csky/kernel/probes/ftrace.c
>> @@ -12,6 +12,9 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
>> struct kprobe_ctlblk *kcb;
>> struct pt_regs *regs;
>>
>> + if (unlikely(ftrace_is_dead()))
>> + return;
>> +
>> bit = ftrace_test_recursion_trylock(ip, parent_ip);
>> if (bit < 0)
>> return;
>> diff --git a/arch/loongarch/kernel/ftrace_dyn.c b/arch/loongarch/kernel/ftrace_dyn.c
>> index 73858c9029cc..82c952cb5be0 100644
>> --- a/arch/loongarch/kernel/ftrace_dyn.c
>> +++ b/arch/loongarch/kernel/ftrace_dyn.c
>> @@ -287,6 +287,9 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
>> struct kprobe *p;
>> struct kprobe_ctlblk *kcb;
>>
>> + if (unlikely(ftrace_is_dead()))
>> + return;
>> +
>> bit = ftrace_test_recursion_trylock(ip, parent_ip);
>> if (bit < 0)
>> return;
>> diff --git a/arch/parisc/kernel/ftrace.c b/arch/parisc/kernel/ftrace.c
>> index 621a4b386ae4..3660834f54c3 100644
>> --- a/arch/parisc/kernel/ftrace.c
>> +++ b/arch/parisc/kernel/ftrace.c
>> @@ -206,6 +206,9 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
>> struct kprobe *p;
>> int bit;
>>
>> + if (unlikely(ftrace_is_dead()))
>> + return;
>> +
>> bit = ftrace_test_recursion_trylock(ip, parent_ip);
>> if (bit < 0)
>> return;
>> diff --git a/arch/powerpc/kernel/kprobes-ftrace.c b/arch/powerpc/kernel/kprobes-ftrace.c
>> index 072ebe7f290b..85eb55aa1457 100644
>> --- a/arch/powerpc/kernel/kprobes-ftrace.c
>> +++ b/arch/powerpc/kernel/kprobes-ftrace.c
>> @@ -21,6 +21,9 @@ void kprobe_ftrace_handler(unsigned long nip, unsigned long parent_nip,
>> struct pt_regs *regs;
>> int bit;
>>
>> + if (unlikely(ftrace_is_dead()))
>> + return;
>> +
>> bit = ftrace_test_recursion_trylock(nip, parent_nip);
>> if (bit < 0)
>> return;
>> diff --git a/arch/riscv/kernel/probes/ftrace.c b/arch/riscv/kernel/probes/ftrace.c
>> index 7142ec42e889..8814fbe4c888 100644
>> --- a/arch/riscv/kernel/probes/ftrace.c
>> +++ b/arch/riscv/kernel/probes/ftrace.c
>> @@ -11,6 +11,9 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
>> struct kprobe_ctlblk *kcb;
>> int bit;
>>
>> + if (unlikely(ftrace_is_dead()))
>> + return;
>> +
>> bit = ftrace_test_recursion_trylock(ip, parent_ip);
>> if (bit < 0)
>> return;
>> diff --git a/arch/s390/kernel/ftrace.c b/arch/s390/kernel/ftrace.c
>> index c46381ea04ec..ccbe8ccf945b 100644
>> --- a/arch/s390/kernel/ftrace.c
>> +++ b/arch/s390/kernel/ftrace.c
>> @@ -296,6 +296,9 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
>> struct kprobe *p;
>> int bit;
>>
>> + if (unlikely(ftrace_is_dead()))
>> + return;
>> +
>> bit = ftrace_test_recursion_trylock(ip, parent_ip);
>> if (bit < 0)
>> return;
>> diff --git a/arch/x86/kernel/kprobes/ftrace.c b/arch/x86/kernel/kprobes/ftrace.c
>> index dd2ec14adb77..c73f9ab7ff50 100644
>> --- a/arch/x86/kernel/kprobes/ftrace.c
>> +++ b/arch/x86/kernel/kprobes/ftrace.c
>> @@ -21,6 +21,9 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
>> struct kprobe_ctlblk *kcb;
>> int bit;
>>
>> + if (unlikely(ftrace_is_dead()))
>> + return;
>> +
>> bit = ftrace_test_recursion_trylock(ip, parent_ip);
>> if (bit < 0)
>> return;
>> diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
>> index 54d53f345d14..ba83e99c1fbe 100644
>> --- a/include/linux/ftrace.h
>> +++ b/include/linux/ftrace.h
>> @@ -399,6 +399,7 @@ int ftrace_lookup_symbols(const char **sorted_syms, size_t cnt, unsigned long *a
>> #define register_ftrace_function(ops) ({ 0; })
>> #define unregister_ftrace_function(ops) ({ 0; })
>> static inline void ftrace_kill(void) { }
>> +static inline int ftrace_is_dead(void) { return 0; }
>> static inline void ftrace_free_init_mem(void) { }
>> static inline void ftrace_free_mem(struct module *mod, void *start, void *end) { }
>> static inline int ftrace_lookup_symbols(const char **sorted_syms, size_t cnt, unsigned long *addrs)
>> @@ -914,6 +915,7 @@ static inline bool is_ftrace_trampoline(unsigned long addr)
>>
>> /* totally disable ftrace - can not re-enable after this */
>> void ftrace_kill(void);
>> +int ftrace_is_dead(void);
>>
>> static inline void tracer_disable(void)
>> {
>> --
>> 2.39.3
>>
>
>
> --
> Masami Hiramatsu (Google) <mhiramat@kernel.org>
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
WARNING: multiple messages have this Message-ID (diff)
From: Stephen Brennan <stephen.s.brennan@oracle.com>
To: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>,
x86@kernel.org, Dave Hansen <dave.hansen@linux.intel.com>,
"James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>,
Guo Ren <guoren@kernel.org>,
linux-csky@vger.kernel.org, "H. Peter Anvin" <hpa@zytor.com>,
Alexander Gordeev <agordeev@linux.ibm.com>,
WANG Xuerui <kernel@xen0n.name>,
linux-s390@vger.kernel.org, Helge Deller <deller@gmx.de>,
Huacai Chen <chenhuacai@kernel.org>,
"Aneesh Kumar K.V" <aneesh.kumar@kernel.org>,
Ingo Molnar <mingo@redhat.com>,
"Naveen N. Rao" <naveen.n.rao@linux.ibm.com>,
Christian Borntraeger <borntraeger@linux.ibm.com>,
linux-trace-kernel@vger.kernel.org,
Albert Ou <aou@eecs.berkeley.edu>,
Vasily Gorbik <gor@linux.ibm.com>,
Heiko Carstens <hca@linux.ibm.com>,
Steven Rostedt <rostedt@goodmis.org>,
Borislav Petkov <bp@alien8.de>,
Nicholas Piggin <npiggin@gmail.com>,
loongarch@lists.linux.dev,
Paul Walmsley <paul.walmsley@sifive.com>,
Thomas Gleixner <tglx@linutronix.de>,
linux-parisc@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-riscv@lists.infradead.org,
Palmer Dabbelt <palmer@dabbelt.com>,
Sven Schnelle <svens@ linux.ibm.com>,
linuxppc-dev@lists.ozlabs.org
Subject: Re: [PATCH] kprobe/ftrace: bail out if ftrace was killed
Date: Mon, 29 Apr 2024 10:47:26 -0700 [thread overview]
Message-ID: <87jzkgawnl.fsf@oracle.com> (raw)
In-Reply-To: <20240429224803.49d420b514e22d51412e1602@kernel.org>
Masami Hiramatsu (Google) <mhiramat@kernel.org> writes:
> Hi Stephen,
>
> On Fri, 26 Apr 2024 15:58:34 -0700
> Stephen Brennan <stephen.s.brennan@oracle.com> wrote:
>
>> If an error happens in ftrace, ftrace_kill() will prevent disarming
>> kprobes. Eventually, the ftrace_ops associated with the kprobes will be
>> freed, yet the kprobes will still be active, and when triggered, they
>> will use the freed memory, likely resulting in a page fault and panic.
>
> Hmm, indeed.
>
>>
>> This behavior can be reproduced quite easily, by creating a kprobe and
>> then triggering a ftrace_kill(). For simplicity, we can simulate an
>> ftrace error with a kernel module like [1]:
>>
>> [1]: https://github.com/brenns10/kernel_stuff/tree/master/ftrace_killer
>>
>> sudo perf probe --add commit_creds
>> sudo perf trace -e probe:commit_creds
>> # In another terminal
>> make
>> sudo insmod ftrace_killer.ko # calls ftrace_kill(), simulating bug
>> # Back to perf terminal
>> # ctrl-c
>> sudo perf probe --del commit_creds
>>
>> After a short period, a page fault and panic would occur as the kprobe
>> continues to execute and uses the freed ftrace_ops. While ftrace_kill()
>> is supposed to be used only in extreme circumstances, it is invoked in
>> FTRACE_WARN_ON() and so there are many places where an unexpected bug
>> could be triggered, yet the system may continue operating, possibly
>> without the administrator noticing. If ftrace_kill() does not panic the
>> system, then we should do everything we can to continue operating,
>> rather than leave a ticking time bomb.
>
> OK, the patch looks good to me.
>
> Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
>
> Thanks!
Hi Masami,
Thank you! Sadly I took a second look at the patch and noticed I forgot
to remove the existing declarations of ftrace_is_dead() from
kernel/trace/trace.h. I've sent v2 in reply to v1 in order to correct
that. I'm sorry for the churn.
Thanks,
Stephen
>>
>> Signed-off-by: Stephen Brennan <stephen.s.brennan@oracle.com>
>> ---
>>
>> Apologies for the wide net cast here. I recognize that a change like this
>> may need to be split up and go through arch-specific trees. I hoped to get
>> feedback on the patch itself. If it's satisfactory and the architecture
>> maintainers prefer it split out, I'm glad to do it. Thanks!
>>
>> arch/csky/kernel/probes/ftrace.c | 3 +++
>> arch/loongarch/kernel/ftrace_dyn.c | 3 +++
>> arch/parisc/kernel/ftrace.c | 3 +++
>> arch/powerpc/kernel/kprobes-ftrace.c | 3 +++
>> arch/riscv/kernel/probes/ftrace.c | 3 +++
>> arch/s390/kernel/ftrace.c | 3 +++
>> arch/x86/kernel/kprobes/ftrace.c | 3 +++
>> include/linux/ftrace.h | 2 ++
>> 8 files changed, 23 insertions(+)
>>
>> diff --git a/arch/csky/kernel/probes/ftrace.c b/arch/csky/kernel/probes/ftrace.c
>> index 834cffcfbce3..3931bf9f707b 100644
>> --- a/arch/csky/kernel/probes/ftrace.c
>> +++ b/arch/csky/kernel/probes/ftrace.c
>> @@ -12,6 +12,9 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
>> struct kprobe_ctlblk *kcb;
>> struct pt_regs *regs;
>>
>> + if (unlikely(ftrace_is_dead()))
>> + return;
>> +
>> bit = ftrace_test_recursion_trylock(ip, parent_ip);
>> if (bit < 0)
>> return;
>> diff --git a/arch/loongarch/kernel/ftrace_dyn.c b/arch/loongarch/kernel/ftrace_dyn.c
>> index 73858c9029cc..82c952cb5be0 100644
>> --- a/arch/loongarch/kernel/ftrace_dyn.c
>> +++ b/arch/loongarch/kernel/ftrace_dyn.c
>> @@ -287,6 +287,9 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
>> struct kprobe *p;
>> struct kprobe_ctlblk *kcb;
>>
>> + if (unlikely(ftrace_is_dead()))
>> + return;
>> +
>> bit = ftrace_test_recursion_trylock(ip, parent_ip);
>> if (bit < 0)
>> return;
>> diff --git a/arch/parisc/kernel/ftrace.c b/arch/parisc/kernel/ftrace.c
>> index 621a4b386ae4..3660834f54c3 100644
>> --- a/arch/parisc/kernel/ftrace.c
>> +++ b/arch/parisc/kernel/ftrace.c
>> @@ -206,6 +206,9 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
>> struct kprobe *p;
>> int bit;
>>
>> + if (unlikely(ftrace_is_dead()))
>> + return;
>> +
>> bit = ftrace_test_recursion_trylock(ip, parent_ip);
>> if (bit < 0)
>> return;
>> diff --git a/arch/powerpc/kernel/kprobes-ftrace.c b/arch/powerpc/kernel/kprobes-ftrace.c
>> index 072ebe7f290b..85eb55aa1457 100644
>> --- a/arch/powerpc/kernel/kprobes-ftrace.c
>> +++ b/arch/powerpc/kernel/kprobes-ftrace.c
>> @@ -21,6 +21,9 @@ void kprobe_ftrace_handler(unsigned long nip, unsigned long parent_nip,
>> struct pt_regs *regs;
>> int bit;
>>
>> + if (unlikely(ftrace_is_dead()))
>> + return;
>> +
>> bit = ftrace_test_recursion_trylock(nip, parent_nip);
>> if (bit < 0)
>> return;
>> diff --git a/arch/riscv/kernel/probes/ftrace.c b/arch/riscv/kernel/probes/ftrace.c
>> index 7142ec42e889..8814fbe4c888 100644
>> --- a/arch/riscv/kernel/probes/ftrace.c
>> +++ b/arch/riscv/kernel/probes/ftrace.c
>> @@ -11,6 +11,9 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
>> struct kprobe_ctlblk *kcb;
>> int bit;
>>
>> + if (unlikely(ftrace_is_dead()))
>> + return;
>> +
>> bit = ftrace_test_recursion_trylock(ip, parent_ip);
>> if (bit < 0)
>> return;
>> diff --git a/arch/s390/kernel/ftrace.c b/arch/s390/kernel/ftrace.c
>> index c46381ea04ec..ccbe8ccf945b 100644
>> --- a/arch/s390/kernel/ftrace.c
>> +++ b/arch/s390/kernel/ftrace.c
>> @@ -296,6 +296,9 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
>> struct kprobe *p;
>> int bit;
>>
>> + if (unlikely(ftrace_is_dead()))
>> + return;
>> +
>> bit = ftrace_test_recursion_trylock(ip, parent_ip);
>> if (bit < 0)
>> return;
>> diff --git a/arch/x86/kernel/kprobes/ftrace.c b/arch/x86/kernel/kprobes/ftrace.c
>> index dd2ec14adb77..c73f9ab7ff50 100644
>> --- a/arch/x86/kernel/kprobes/ftrace.c
>> +++ b/arch/x86/kernel/kprobes/ftrace.c
>> @@ -21,6 +21,9 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
>> struct kprobe_ctlblk *kcb;
>> int bit;
>>
>> + if (unlikely(ftrace_is_dead()))
>> + return;
>> +
>> bit = ftrace_test_recursion_trylock(ip, parent_ip);
>> if (bit < 0)
>> return;
>> diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
>> index 54d53f345d14..ba83e99c1fbe 100644
>> --- a/include/linux/ftrace.h
>> +++ b/include/linux/ftrace.h
>> @@ -399,6 +399,7 @@ int ftrace_lookup_symbols(const char **sorted_syms, size_t cnt, unsigned long *a
>> #define register_ftrace_function(ops) ({ 0; })
>> #define unregister_ftrace_function(ops) ({ 0; })
>> static inline void ftrace_kill(void) { }
>> +static inline int ftrace_is_dead(void) { return 0; }
>> static inline void ftrace_free_init_mem(void) { }
>> static inline void ftrace_free_mem(struct module *mod, void *start, void *end) { }
>> static inline int ftrace_lookup_symbols(const char **sorted_syms, size_t cnt, unsigned long *addrs)
>> @@ -914,6 +915,7 @@ static inline bool is_ftrace_trampoline(unsigned long addr)
>>
>> /* totally disable ftrace - can not re-enable after this */
>> void ftrace_kill(void);
>> +int ftrace_is_dead(void);
>>
>> static inline void tracer_disable(void)
>> {
>> --
>> 2.39.3
>>
>
>
> --
> Masami Hiramatsu (Google) <mhiramat@kernel.org>
next prev parent reply other threads:[~2024-04-29 17:48 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-04-26 22:58 [PATCH] kprobe/ftrace: bail out if ftrace was killed Stephen Brennan
2024-04-26 22:58 ` Stephen Brennan
2024-04-26 22:58 ` Stephen Brennan
2024-04-29 13:48 ` Masami Hiramatsu
2024-04-29 13:48 ` Masami Hiramatsu
2024-04-29 13:48 ` Masami Hiramatsu
2024-04-29 17:47 ` Stephen Brennan [this message]
2024-04-29 17:47 ` Stephen Brennan
2024-04-29 17:47 ` Stephen Brennan
2024-04-29 17:47 ` [PATCH v2] " Stephen Brennan
2024-04-29 17:47 ` Stephen Brennan
2024-04-29 17:47 ` Stephen Brennan
2024-04-30 1:29 ` Steven Rostedt
2024-04-30 1:29 ` Steven Rostedt
2024-04-30 1:29 ` Steven Rostedt
2024-04-30 23:01 ` Stephen Brennan
2024-04-30 23:01 ` Stephen Brennan
2024-04-30 23:01 ` Stephen Brennan
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=87jzkgawnl.fsf@oracle.com \
--to=stephen.s.brennan@oracle.com \
--cc=James.Bottomley@HansenPartnership.com \
--cc=agordeev@linux.ibm.com \
--cc=aneesh.kumar@kernel.org \
--cc=aou@eecs.berkeley.edu \
--cc=borntraeger@linux.ibm.com \
--cc=bp@alien8.de \
--cc=chenhuacai@kernel.org \
--cc=christophe.leroy@csgroup.eu \
--cc=dave.hansen@linux.intel.com \
--cc=deller@gmx.de \
--cc=gor@linux.ibm.com \
--cc=guoren@kernel.org \
--cc=hca@linux.ibm.com \
--cc=hpa@zytor.com \
--cc=kernel@xen0n.name \
--cc=linux-csky@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-parisc@vger.kernel.org \
--cc=linux-riscv@lists.infradead.org \
--cc=linux-s390@vger.kernel.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=linuxppc-dev@lists.ozlabs.org \
--cc=loongarch@lists.linux.dev \
--cc=mark.rutland@arm.com \
--cc=mhiramat@kernel.org \
--cc=mingo@redhat.com \
--cc=mpe@ellerman.id.au \
--cc=naveen.n.rao@linux.ibm.com \
--cc=npiggin@gmail.com \
--cc=palmer@dabbelt.com \
--cc=paul.walmsley@sifive.com \
--cc=rostedt@goodmis.org \
--cc=svens@linux.ibm.com \
--cc=tglx@linutronix.de \
--cc=x86@kernel.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.