----- On Nov 17, 2020, at 5:19 PM, rostedt rostedt@xxxxxxxxxxx wrote: > 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. That being said, the called functions have a prototype which match the caller prototype exactly. So within the tracepoint internal data structures, this function pointer is indeed a void pointer, but it is cast to a prototype matching the callees to perform the calls. I suspect that as long as CFI checks that caller/callees prototypes are compatible at runtime when the actual calls happen, this all works fine. Thanks, Mathieu > > -- Steve > > > } while ((++it_func_ptr)->func); \ > return 0; \ > } \ -- Mathieu Desnoyers EfficiOS Inc. http://www.efficios.com