* [PATCH 0/2] tracing/perf: Prevent double unregister of perf and tracepoint probes
@ 2025-07-09 5:41 Aditya Chillara
2025-07-09 5:41 ` [PATCH 1/2] tracing/perf: Prevent double unregister of perf probes Aditya Chillara
2025-07-09 5:41 ` [PATCH 2/2] tracing: Prevent double unregister of tracepoint probes Aditya Chillara
0 siblings, 2 replies; 11+ messages in thread
From: Aditya Chillara @ 2025-07-09 5:41 UTC (permalink / raw)
To: Steven Rostedt, Ingo Molnar; +Cc: linux-kernel, Aditya Chillara
Double perf_trace_event_unreg is allowed causing perf_refcount to go
negative. total_ref_count also goes negative because the return value
of tracepoint_probe_unregister is ignored.
Once total_ref_count is negative, the next call to perf_trace_event_reg
will register perf_probe but will not allocate perf_trace_buf and sets
it to NULL instead.
The subsequent trace_##call() will mem abort in perf_trace_buf_alloc
because memset will be called on the NULL perf_trace_buf.
tracepoint_remove_func returns error after the warning:
[ 111.552262][ T8418] WARNING: CPU: 4 PID: 8418 at kernel/tracepoint.c:405 tracepoint_probe_unregister+0xb0/0x468
.
.
[ 111.552831][ T8418] CPU: 4 UID: 1779017056 PID: 8418 Comm: trinity-c19 Tainted: G W OE 6.12.23-android16-5-maybe-dirty-debug #1 2362fed3965ed146e5e20aa901c0fae1990ed57d
.
.
[ 111.552881][ T8418] Call trace:
[ 111.552882][ T8418] tracepoint_probe_unregister+0xb0/0x468
[ 111.552885][ T8418] trace_event_reg+0x5c/0xa4
[ 111.552887][ T8418] perf_trace_event_unreg+0x58/0xd4
[ 111.552889][ T8418] perf_trace_destroy+0x5c/0x94
[ 111.552891][ T8418] tp_perf_event_destroy+0x10/0x20
[ 111.552895][ T8418] __free_event+0x90/0x154
[ 111.552896][ T8418] perf_event_alloc+0x478/0x684
[ 111.552898][ T8418] __arm64_sys_perf_event_open+0x278/0x7d8
[ 111.552900][ T8418] invoke_syscall+0x58/0x10c
and then mem abort on trace_##call():
[ 189.790824][ C4] CPU: 4 UID: 8388678 PID: 8422 Comm: trinity-c23 Tainted: G W OE 6.12.23-android16-5-maybe-dirty-debug #1 2362fed3965ed146e5e20aa901c0fae1990ed57d
.
.
[ 189.790862][ C4] Call trace:
[ 189.790863][ C4] perf_trace_buf_alloc+0xb4/0x104
.
.
[ 189.790894][ C4] trace_preempt_off+0x138/0x140
[ 189.790895][ C4] preempt_count_add+0xa8/0x13c
[ 189.790897][ C4] copy_page_from_iter_atomic+0xa4/0x7e4
[ 189.790900][ C4] generic_perform_write+0x170/0x350
[ 189.790904][ C4] f2fs_file_write_iter+0x268/0xb64
[ 189.790908][ C4] vfs_write+0x340/0x3ac
[ 189.790910][ C4] ksys_write+0x78/0xe8
[ 189.790911][ C4] __arm64_sys_write+0x1c/0x2c
[ 189.790912][ C4] invoke_syscall+0x58/0x10c
.
.
[ 189.797921][ C4] ---[ end trace 0000000000000000 ]---
[ 189.797923][ C4] Kernel panic - not syncing: Oops: Fatal exception
in interrupt
Fix the issue by preventing double remove in tracepoint_remove_func
and gracefully handling the error in perf_trace_event_unreg.
Signed-off-by: Aditya Chillara <quic_achillar@quicinc.com>
---
---
Aditya Chillara (2):
tracing/perf: Prevent double unregister of perf probes
tracing: Prevent double unregister of tracepoint probes
kernel/trace/trace_event_perf.c | 8 ++++++--
kernel/trace/trace_events.c | 3 +--
kernel/tracepoint.c | 11 +++++++++--
3 files changed, 16 insertions(+), 6 deletions(-)
---
base-commit: 70575e77839f4c5337ce2653b39b86bb365a870e
change-id: 20250704-fix-double-perf-probe-unregister-ab98912f521b
Best regards,
--
Aditya Chillara <quic_achillar@quicinc.com>
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH 1/2] tracing/perf: Prevent double unregister of perf probes 2025-07-09 5:41 [PATCH 0/2] tracing/perf: Prevent double unregister of perf and tracepoint probes Aditya Chillara @ 2025-07-09 5:41 ` Aditya Chillara 2025-07-09 14:23 ` Steven Rostedt 2025-07-09 5:41 ` [PATCH 2/2] tracing: Prevent double unregister of tracepoint probes Aditya Chillara 1 sibling, 1 reply; 11+ messages in thread From: Aditya Chillara @ 2025-07-09 5:41 UTC (permalink / raw) To: Steven Rostedt, Ingo Molnar; +Cc: linux-kernel, Aditya Chillara Double perf_trace_event_unreg is allowed causing perf_refcount to go negative. total_ref_count also goes negative because the return value of tracepoint_probe_unregister is ignored. Once total_ref_count is negative, the next call to perf_trace_event_reg will register perf_probe but will not allocate perf_trace_buf and sets it to NULL instead. The subsequent trace_##call() will mem abort in perf_trace_buf_alloc because memset will be called on the NULL perf_trace_buf. Gracefully handle the error in perf_trace_event_unreg to prevent double unregister. Signed-off-by: Aditya Chillara <quic_achillar@quicinc.com> --- kernel/trace/trace_event_perf.c | 8 ++++++-- kernel/trace/trace_events.c | 3 +-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c index 61e3a2620fa3c9417ac23cf5a18aeb86e7393dcc..247db88accd88eb0acf3692ea593d576519ce8b1 100644 --- a/kernel/trace/trace_event_perf.c +++ b/kernel/trace/trace_event_perf.c @@ -154,12 +154,16 @@ static int perf_trace_event_reg(struct trace_event_call *tp_event, static void perf_trace_event_unreg(struct perf_event *p_event) { struct trace_event_call *tp_event = p_event->tp_event; - int i; + int i, ret; if (--tp_event->perf_refcount > 0) return; - tp_event->class->reg(tp_event, TRACE_REG_PERF_UNREGISTER, NULL); + ret = tp_event->class->reg(tp_event, TRACE_REG_PERF_UNREGISTER, NULL); + if (ret) { + ++tp_event->perf_refcount; + return; + } /* * Ensure our callback won't be called anymore. The buffers diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 0356cae0cf74e79075f607bc841df05568688baa..50e0e08b29aa6617a04b191419ad1e587adf69fe 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -530,10 +530,9 @@ int trace_event_reg(struct trace_event_call *call, call->class->perf_probe, call); case TRACE_REG_PERF_UNREGISTER: - tracepoint_probe_unregister(call->tp, + return tracepoint_probe_unregister(call->tp, call->class->perf_probe, call); - return 0; case TRACE_REG_PERF_OPEN: case TRACE_REG_PERF_CLOSE: case TRACE_REG_PERF_ADD: -- 2.34.1 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 1/2] tracing/perf: Prevent double unregister of perf probes 2025-07-09 5:41 ` [PATCH 1/2] tracing/perf: Prevent double unregister of perf probes Aditya Chillara @ 2025-07-09 14:23 ` Steven Rostedt 2025-07-09 16:50 ` Aditya Chillara 0 siblings, 1 reply; 11+ messages in thread From: Steven Rostedt @ 2025-07-09 14:23 UTC (permalink / raw) To: Aditya Chillara; +Cc: Ingo Molnar, linux-kernel On Wed, 9 Jul 2025 11:11:09 +0530 Aditya Chillara <quic_achillar@quicinc.com> wrote: > Double perf_trace_event_unreg is allowed causing perf_refcount to go > negative. total_ref_count also goes negative because the return value > of tracepoint_probe_unregister is ignored. > > Once total_ref_count is negative, the next call to perf_trace_event_reg > will register perf_probe but will not allocate perf_trace_buf and sets > it to NULL instead. > > The subsequent trace_##call() will mem abort in perf_trace_buf_alloc > because memset will be called on the NULL perf_trace_buf. > > Gracefully handle the error in perf_trace_event_unreg to prevent > double unregister. > > Signed-off-by: Aditya Chillara <quic_achillar@quicinc.com> > --- > kernel/trace/trace_event_perf.c | 8 ++++++-- > kernel/trace/trace_events.c | 3 +-- > 2 files changed, 7 insertions(+), 4 deletions(-) > > diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c > index 61e3a2620fa3c9417ac23cf5a18aeb86e7393dcc..247db88accd88eb0acf3692ea593d576519ce8b1 100644 > --- a/kernel/trace/trace_event_perf.c > +++ b/kernel/trace/trace_event_perf.c > @@ -154,12 +154,16 @@ static int perf_trace_event_reg(struct trace_event_call *tp_event, > static void perf_trace_event_unreg(struct perf_event *p_event) > { > struct trace_event_call *tp_event = p_event->tp_event; > - int i; > + int i, ret; > > if (--tp_event->perf_refcount > 0) > return; > > - tp_event->class->reg(tp_event, TRACE_REG_PERF_UNREGISTER, NULL); > + ret = tp_event->class->reg(tp_event, TRACE_REG_PERF_UNREGISTER, NULL); The only time unreg() fails is when it doesn't find a tracepoint to unregister. There should be no reason to check the return value of unregister if you have your accounting correct. Thus I think you are fixing a symptom of a bug elsewhere. -- Steve > + if (ret) { > + ++tp_event->perf_refcount; > + return; > + } > ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/2] tracing/perf: Prevent double unregister of perf probes 2025-07-09 14:23 ` Steven Rostedt @ 2025-07-09 16:50 ` Aditya Chillara 2025-07-09 17:18 ` Steven Rostedt 0 siblings, 1 reply; 11+ messages in thread From: Aditya Chillara @ 2025-07-09 16:50 UTC (permalink / raw) To: Steven Rostedt; +Cc: Ingo Molnar, linux-kernel On 7/9/2025 7:53 PM, Steven Rostedt wrote: > On Wed, 9 Jul 2025 11:11:09 +0530 > Aditya Chillara <quic_achillar@quicinc.com> wrote: > >> Double perf_trace_event_unreg is allowed causing perf_refcount to go >> negative. total_ref_count also goes negative because the return value >> of tracepoint_probe_unregister is ignored. >> >> Once total_ref_count is negative, the next call to perf_trace_event_reg >> will register perf_probe but will not allocate perf_trace_buf and sets >> it to NULL instead. >> >> The subsequent trace_##call() will mem abort in perf_trace_buf_alloc >> because memset will be called on the NULL perf_trace_buf. >> >> Gracefully handle the error in perf_trace_event_unreg to prevent >> double unregister. >> >> Signed-off-by: Aditya Chillara <quic_achillar@quicinc.com> >> --- >> kernel/trace/trace_event_perf.c | 8 ++++++-- >> kernel/trace/trace_events.c | 3 +-- >> 2 files changed, 7 insertions(+), 4 deletions(-) >> >> diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c >> index 61e3a2620fa3c9417ac23cf5a18aeb86e7393dcc..247db88accd88eb0acf3692ea593d576519ce8b1 100644 >> --- a/kernel/trace/trace_event_perf.c >> +++ b/kernel/trace/trace_event_perf.c >> @@ -154,12 +154,16 @@ static int perf_trace_event_reg(struct trace_event_call *tp_event, >> static void perf_trace_event_unreg(struct perf_event *p_event) >> { >> struct trace_event_call *tp_event = p_event->tp_event; >> - int i; >> + int i, ret; >> >> if (--tp_event->perf_refcount > 0) >> return; >> >> - tp_event->class->reg(tp_event, TRACE_REG_PERF_UNREGISTER, NULL); >> + ret = tp_event->class->reg(tp_event, TRACE_REG_PERF_UNREGISTER, NULL); > > The only time unreg() fails is when it doesn't find a tracepoint to > unregister. > > There should be no reason to check the return value of unregister if > you have your accounting correct. Thus I think you are fixing a symptom > of a bug elsewhere. The exact problem was introduced by: https://github.com/torvalds/linux/commit/7ef5aa081f989ecfecc1df02068a80aebbd3ec31 (perf/core: Simplify the perf_event_alloc() error path) where __free_event was calling event->destroy() even though it would have been called by perf_try_init_event in case it failed. This was fixed by: https://github.com/torvalds/linux/commit/da02f54e81db2f7bf6af9d1d0cfc5b41ec6d0dcb (perf/core: Clean up perf_try_init_event()) This patch prevents from crashing even if that happens, and there will be a warning anyway to notice the double unregister. > > -- Steve > > >> + if (ret) { >> + ++tp_event->perf_refcount; >> + return; >> + } >> Best Regards, Aditya ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/2] tracing/perf: Prevent double unregister of perf probes 2025-07-09 16:50 ` Aditya Chillara @ 2025-07-09 17:18 ` Steven Rostedt 2025-07-11 18:40 ` Aditya Chillara 2025-07-18 7:35 ` Aditya Chillara 0 siblings, 2 replies; 11+ messages in thread From: Steven Rostedt @ 2025-07-09 17:18 UTC (permalink / raw) To: Aditya Chillara; +Cc: Ingo Molnar, linux-kernel On Wed, 9 Jul 2025 22:20:00 +0530 Aditya Chillara <quic_achillar@quicinc.com> wrote: > The exact problem was introduced by: > https://github.com/torvalds/linux/commit/7ef5aa081f989ecfecc1df02068a80aebbd3ec31 > (perf/core: Simplify the perf_event_alloc() error path) > where __free_event was calling event->destroy() even though it would > have been called by perf_try_init_event in case it failed. Then I rather have it trigger a WARN_ON() and disable that event permanently until reboot. It's a bug, no need to continue using the event when it's in an a bad state. -- Steve ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/2] tracing/perf: Prevent double unregister of perf probes 2025-07-09 17:18 ` Steven Rostedt @ 2025-07-11 18:40 ` Aditya Chillara 2025-07-18 7:35 ` Aditya Chillara 1 sibling, 0 replies; 11+ messages in thread From: Aditya Chillara @ 2025-07-11 18:40 UTC (permalink / raw) To: Steven Rostedt; +Cc: Ingo Molnar, linux-kernel On 7/9/2025 10:48 PM, Steven Rostedt wrote: >> The exact problem was introduced by: >> https://github.com/torvalds/linux/commit/7ef5aa081f989ecfecc1df02068a80aebbd3ec31 >> (perf/core: Simplify the perf_event_alloc() error path) >> where __free_event was calling event->destroy() even though it would >> have been called by perf_try_init_event in case it failed. > Then I rather have it trigger a WARN_ON() and disable that event > permanently until reboot. It's a bug, no need to continue using the > event when it's in an a bad state. Acknowledged, will update in v3. Best Regards, Aditya ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/2] tracing/perf: Prevent double unregister of perf probes 2025-07-09 17:18 ` Steven Rostedt 2025-07-11 18:40 ` Aditya Chillara @ 2025-07-18 7:35 ` Aditya Chillara 1 sibling, 0 replies; 11+ messages in thread From: Aditya Chillara @ 2025-07-18 7:35 UTC (permalink / raw) To: Steven Rostedt, Peter Zijlstra; +Cc: Ingo Molnar, linux-kernel [ Added Peter for 7ef5aa081f98 and kernel/events/core.c ] On 7/9/2025 10:48 PM, Steven Rostedt wrote: > On Wed, 9 Jul 2025 22:20:00 +0530 > Aditya Chillara <quic_achillar@quicinc.com> wrote: > >> The exact problem was introduced by: >> https://github.com/torvalds/linux/commit/7ef5aa081f989ecfecc1df02068a80aebbd3ec31 >> (perf/core: Simplify the perf_event_alloc() error path) >> where __free_event was calling event->destroy() even though it would >> have been called by perf_try_init_event in case it failed. > > Then I rather have it trigger a WARN_ON() and disable that event > permanently until reboot. It's a bug, no need to continue using the > event when it's in an a bad state. perf_trace_event_unreg is called only in event->destroy(), and this is called in event free path; either after the event is removed from its context, or before the event is installed in a context. I believe there is no need to explicitly disable the perf event here because it must have been disabled already. Please let me know if I'm missing anything. Best Regards, Aditya ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 2/2] tracing: Prevent double unregister of tracepoint probes 2025-07-09 5:41 [PATCH 0/2] tracing/perf: Prevent double unregister of perf and tracepoint probes Aditya Chillara 2025-07-09 5:41 ` [PATCH 1/2] tracing/perf: Prevent double unregister of perf probes Aditya Chillara @ 2025-07-09 5:41 ` Aditya Chillara 2025-07-09 14:40 ` Steven Rostedt 1 sibling, 1 reply; 11+ messages in thread From: Aditya Chillara @ 2025-07-09 5:41 UTC (permalink / raw) To: Steven Rostedt, Ingo Molnar; +Cc: linux-kernel, Aditya Chillara Prevent tracepoint_probe_unregister from being executed multiple times for the same probe, which can cause issues with perf due to the lack of error handling. Return an error if the probe is not present in the list of probes. Signed-off-by: Aditya Chillara <quic_achillar@quicinc.com> --- kernel/tracepoint.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c index ef42c1a1192053cc05b45ccb61358a4996453add..e6eee7e44a9d6f4f19114fbcf8fd9e5c85075324 100644 --- a/kernel/tracepoint.c +++ b/kernel/tracepoint.c @@ -232,7 +232,7 @@ func_add(struct tracepoint_func **funcs, struct tracepoint_func *tp_func, static void *func_remove(struct tracepoint_func **funcs, struct tracepoint_func *tp_func) { - int nr_probes = 0, nr_del = 0, i; + int nr_probes = 0, nr_del = 0, nr_tp_stub_del = 0, i; struct tracepoint_func *old, *new; old = *funcs; @@ -246,11 +246,18 @@ static void *func_remove(struct tracepoint_func **funcs, for (nr_probes = 0; old[nr_probes].func; nr_probes++) { if ((old[nr_probes].func == tp_func->func && old[nr_probes].data == tp_func->data) || - old[nr_probes].func == tp_stub_func) + old[nr_probes].func == tp_stub_func) { + if (old[nr_probes].func == tp_stub_func) + nr_tp_stub_del++; nr_del++; + } } } + /* If there is nothing to delete, do not allow */ + if (nr_del - nr_tp_stub_del == 0) + return ERR_PTR(-ENOENT); + /* * If probe is NULL, then nr_probes = nr_del = 0, and then the * entire entry will be removed. -- 2.34.1 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 2/2] tracing: Prevent double unregister of tracepoint probes 2025-07-09 5:41 ` [PATCH 2/2] tracing: Prevent double unregister of tracepoint probes Aditya Chillara @ 2025-07-09 14:40 ` Steven Rostedt 2025-07-09 14:51 ` Steven Rostedt 2025-07-09 14:51 ` Mathieu Desnoyers 0 siblings, 2 replies; 11+ messages in thread From: Steven Rostedt @ 2025-07-09 14:40 UTC (permalink / raw) To: Aditya Chillara; +Cc: Ingo Molnar, linux-kernel, Mathieu Desnoyers [ Added Mathieu who is the author of the tracepoint code ] On Wed, 9 Jul 2025 11:11:10 +0530 Aditya Chillara <quic_achillar@quicinc.com> wrote: > Prevent tracepoint_probe_unregister from being executed multiple times > for the same probe, which can cause issues with perf due to the lack > of error handling. > > Return an error if the probe is not present in the list of probes. This patch even shows that the first patch is fixing a symptom. Yes, I agree with this patch (with some cleanups below), but there should be no reason for perf to be ever calling unreg() if it doesn't have a tracepoint registered. Something else got screwed up in the mean time. > > Signed-off-by: Aditya Chillara <quic_achillar@quicinc.com> > --- > kernel/tracepoint.c | 11 +++++++++-- > 1 file changed, 9 insertions(+), 2 deletions(-) > > diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c > index ef42c1a1192053cc05b45ccb61358a4996453add..e6eee7e44a9d6f4f19114fbcf8fd9e5c85075324 100644 > --- a/kernel/tracepoint.c > +++ b/kernel/tracepoint.c > @@ -232,7 +232,7 @@ func_add(struct tracepoint_func **funcs, struct tracepoint_func *tp_func, > static void *func_remove(struct tracepoint_func **funcs, > struct tracepoint_func *tp_func) > { > - int nr_probes = 0, nr_del = 0, i; > + int nr_probes = 0, nr_del = 0, nr_tp_stub_del = 0, i; > struct tracepoint_func *old, *new; > > old = *funcs; > @@ -246,11 +246,18 @@ static void *func_remove(struct tracepoint_func **funcs, > for (nr_probes = 0; old[nr_probes].func; nr_probes++) { > if ((old[nr_probes].func == tp_func->func && > old[nr_probes].data == tp_func->data) || > - old[nr_probes].func == tp_stub_func) > + old[nr_probes].func == tp_stub_func) { > + if (old[nr_probes].func == tp_stub_func) > + nr_tp_stub_del++; > nr_del++; > + } I would make this a bit cleaner by: if ((old[nr_probes].func == tp_func->func && old[nr_probes].data == tp_func->data)) nr_del++; if (old[nr_probes].func == tp_stub_func) nr_tp_stub_del++; > } > } > > + /* If there is nothing to delete, do not allow */ > + if (nr_del - nr_tp_stub_del == 0) > + return ERR_PTR(-ENOENT); if (!nr_del) return ERR_PTR(-ENOENT); nr_del += nr_tp_stub_del; -- Steve > + > /* > * If probe is NULL, then nr_probes = nr_del = 0, and then the > * entire entry will be removed. > ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 2/2] tracing: Prevent double unregister of tracepoint probes 2025-07-09 14:40 ` Steven Rostedt @ 2025-07-09 14:51 ` Steven Rostedt 2025-07-09 14:51 ` Mathieu Desnoyers 1 sibling, 0 replies; 11+ messages in thread From: Steven Rostedt @ 2025-07-09 14:51 UTC (permalink / raw) To: Aditya Chillara; +Cc: Ingo Molnar, linux-kernel, Mathieu Desnoyers On Wed, 9 Jul 2025 10:40:17 -0400 Steven Rostedt <rostedt@goodmis.org> wrote: > I would make this a bit cleaner by: > > if ((old[nr_probes].func == tp_func->func && > old[nr_probes].data == tp_func->data)) > nr_del++; > > if (old[nr_probes].func == tp_stub_func) > nr_tp_stub_del++; That probably should be: else if (old[nr_probes].func == tp_stub_func) nr_tp_stub_del++; -- Steve ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 2/2] tracing: Prevent double unregister of tracepoint probes 2025-07-09 14:40 ` Steven Rostedt 2025-07-09 14:51 ` Steven Rostedt @ 2025-07-09 14:51 ` Mathieu Desnoyers 1 sibling, 0 replies; 11+ messages in thread From: Mathieu Desnoyers @ 2025-07-09 14:51 UTC (permalink / raw) To: Steven Rostedt, Aditya Chillara; +Cc: Ingo Molnar, linux-kernel On 2025-07-09 10:40, Steven Rostedt wrote: > [ Added Mathieu who is the author of the tracepoint code ] > > On Wed, 9 Jul 2025 11:11:10 +0530 > Aditya Chillara <quic_achillar@quicinc.com> wrote: > >> Prevent tracepoint_probe_unregister from being executed multiple times >> for the same probe, which can cause issues with perf due to the lack >> of error handling. >> >> Return an error if the probe is not present in the list of probes. > > This patch even shows that the first patch is fixing a symptom. > > Yes, I agree with this patch (with some cleanups below), but there > should be no reason for perf to be ever calling unreg() if it doesn't > have a tracepoint registered. Something else got screwed up in the mean > time. > Agreed. >> >> Signed-off-by: Aditya Chillara <quic_achillar@quicinc.com> >> --- >> kernel/tracepoint.c | 11 +++++++++-- >> 1 file changed, 9 insertions(+), 2 deletions(-) >> >> diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c >> index ef42c1a1192053cc05b45ccb61358a4996453add..e6eee7e44a9d6f4f19114fbcf8fd9e5c85075324 100644 >> --- a/kernel/tracepoint.c >> +++ b/kernel/tracepoint.c >> @@ -232,7 +232,7 @@ func_add(struct tracepoint_func **funcs, struct tracepoint_func *tp_func, >> static void *func_remove(struct tracepoint_func **funcs, >> struct tracepoint_func *tp_func) >> { >> - int nr_probes = 0, nr_del = 0, i; >> + int nr_probes = 0, nr_del = 0, nr_tp_stub_del = 0, i; >> struct tracepoint_func *old, *new; >> >> old = *funcs; >> @@ -246,11 +246,18 @@ static void *func_remove(struct tracepoint_func **funcs, >> for (nr_probes = 0; old[nr_probes].func; nr_probes++) { >> if ((old[nr_probes].func == tp_func->func && >> old[nr_probes].data == tp_func->data) || >> - old[nr_probes].func == tp_stub_func) >> + old[nr_probes].func == tp_stub_func) { >> + if (old[nr_probes].func == tp_stub_func) >> + nr_tp_stub_del++; >> nr_del++; >> + } > > I would make this a bit cleaner by: > > if ((old[nr_probes].func == tp_func->func && > old[nr_probes].data == tp_func->data)) > nr_del++; > > if (old[nr_probes].func == tp_stub_func) > nr_tp_stub_del++; >> } >> } >> >> + /* If there is nothing to delete, do not allow */ >> + if (nr_del - nr_tp_stub_del == 0) >> + return ERR_PTR(-ENOENT); > > if (!nr_del) > return ERR_PTR(-ENOENT); > > nr_del += nr_tp_stub_del; > Indeed func_remove() already returns ERR_PTR(-ENOENT) when old is NULL at the beginning of the function, so its intent is indeed to catch this kind of scenario. I agree with Steven's recommended changes. Thanks, Mathieu > -- Steve > >> + >> /* >> * If probe is NULL, then nr_probes = nr_del = 0, and then the >> * entire entry will be removed. >> > -- Mathieu Desnoyers EfficiOS Inc. https://www.efficios.com ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2025-07-18 7:36 UTC | newest] Thread overview: 11+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-07-09 5:41 [PATCH 0/2] tracing/perf: Prevent double unregister of perf and tracepoint probes Aditya Chillara 2025-07-09 5:41 ` [PATCH 1/2] tracing/perf: Prevent double unregister of perf probes Aditya Chillara 2025-07-09 14:23 ` Steven Rostedt 2025-07-09 16:50 ` Aditya Chillara 2025-07-09 17:18 ` Steven Rostedt 2025-07-11 18:40 ` Aditya Chillara 2025-07-18 7:35 ` Aditya Chillara 2025-07-09 5:41 ` [PATCH 2/2] tracing: Prevent double unregister of tracepoint probes Aditya Chillara 2025-07-09 14:40 ` Steven Rostedt 2025-07-09 14:51 ` Steven Rostedt 2025-07-09 14:51 ` Mathieu Desnoyers
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox