Re: [PATCH] tracing: fix CFI violation in probestub helper

From: Steven Rostedt

Date: Thu May 28 2026 - 16:56:11 EST


On Sun, 24 May 2026 18:43:01 +0300
Eva Kurchatova <eva.kurchatova@xxxxxxxxxxxxx> wrote:

> When multiple callbacks are registered on the same tracepoint, probestub
> will be indirectly called via traceiter helper.
>
> Pointer to probestub callback resides in __tracepoints section, which is
> excluded from ENDBR checks in objtool. Pointers to regfunc/unregfunc
> callbacks reside in extended structure however, which is not affected.
>
> Registering multiple callbacks will result in a #CP exception due to
> missed ENDBR in __probestub helper on a CFI-enabled machine.
>
> Fix this by adding CFI_NOSEAL annotation to probestub declaration.
>
> Fixes: d5173f753750 ("objtool: Exclude __tracepoints data from ENDBR checks")
> Signed-off-by: Eva Kurchatova <eva.kurchatova@xxxxxxxxxxxxx>

Wait! The probestub is not in the __tracepoints section. At least it
shouldn't be. Are you sure there's not another issue here?

#define __DEFINE_TRACE_EXT(_name, _ext, proto, args) \
static const char __tpstrtab_##_name[] \
__section("__tracepoints_strings") = #_name; \
extern struct static_call_key STATIC_CALL_KEY(tp_func_##_name); \
int __traceiter_##_name(void *__data, proto); \
void __probestub_##_name(void *__data, proto); \
struct tracepoint __tracepoint_##_name __used \
__section("__tracepoints") = { \

Here the structure __tracepoint_##name is in the __tracepoints section.

.name = __tpstrtab_##_name, \
.key = STATIC_KEY_FALSE_INIT, \
.static_call_key = &STATIC_CALL_KEY(tp_func_##_name), \
.static_call_tramp = STATIC_CALL_TRAMP_ADDR(tp_func_##_name), \
.iterator = &__traceiter_##_name, \
.probestub = &__probestub_##_name, \
.funcs = NULL, \
.ext = _ext, \
}; \
__TRACEPOINT_ENTRY(_name); \
int __traceiter_##_name(void *__data, proto) \
{ \
struct tracepoint_func *it_func_ptr; \
void *it_func; \
\
it_func_ptr = \
rcu_dereference_raw((&__tracepoint_##_name)->funcs); \
if (it_func_ptr) { \
do { \
it_func = READ_ONCE((it_func_ptr)->func); \
__data = (it_func_ptr)->data; \
((void(*)(void *, proto))(it_func))(__data, args); \
} while ((++it_func_ptr)->func); \
} \
return 0; \
} \
void __probestub_##_name(void *__data, proto) \
{ \
}

But above, probestub is just a function defined wherever the tracepoint is
created.

In fact, it's just there for fprobes to work. It doesn't get called if you
add more than one callback to the tracepoint. So your explanation is totally
bogus.

Do you actually see a crash? Or is this just some AI slop that told you
this is a bug?

-- Steve



> ---
> include/linux/tracepoint.h | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
> index 583d962abcc3..5a32a709759c 100644
> --- a/include/linux/tracepoint.h
> +++ b/include/linux/tracepoint.h
> @@ -19,6 +19,7 @@
> #include <linux/rcupdate.h>
> #include <linux/tracepoint-defs.h>
> #include <linux/static_call.h>
> +#include <asm/cfi.h>
>
> struct module;
> struct tracepoint;
> @@ -356,6 +357,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
> void __probestub_##_name(void *__data, proto) \
> { \
> } \
> + CFI_NOSEAL(__probestub_##_name); \
> DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name);
>
> #define DEFINE_TRACE_FN(_name, _reg, _unreg, _proto, _args) \