On Tue, 17 Nov 2020 13:33:42 -0800 Kees Cook <keescook@xxxxxxxxxxxx> wrote: > As I think got discussed in the thread, what you had here wouldn't work > in a CFI build if the function prototype of the call site and the > function don't match. (Though I can't tell if .func() is ever called?) > > i.e. .func's prototype must match tp_stub_func()'s. > Hmm, I wonder how you handle tracepoints? This is called here: include/linux/tracepoint.h: #define DEFINE_TRACE_FN(_name, _reg, _unreg, 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); \ struct tracepoint __tracepoint_##_name __used \ __section("__tracepoints") = { \ .name = __tpstrtab_##_name, \ .key = STATIC_KEY_INIT_FALSE, \ .static_call_key = &STATIC_CALL_KEY(tp_func_##_name), \ .static_call_tramp = STATIC_CALL_TRAMP_ADDR(tp_func_##_name), \ .iterator = &__traceiter_##_name, \ .regfunc = _reg, \ .unregfunc = _unreg, \ .funcs = NULL }; \ __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); \ do { \ it_func = (it_func_ptr)->func; \ __data = (it_func_ptr)->data; \ ((void(*)(void *, proto))(it_func))(__data, args); \ ^^^^ called above ^^^^ Where args is unique for every tracepoint, but func is simply a void pointer. -- Steve } while ((++it_func_ptr)->func); \ return 0; \ } \