History

tracepoint: Fix race between tracing and removing tracepoint

When executing a tracepoint, the tracepoint's func is dereferenced twice - in __DO_TRACE() (where the returned pointer is checked) and later on in __traceiter_##_name where the returned pointer is dereferenced without checking which leads to races against tracepoint_removal_sync() and crashes. This adds a check before referencing the pointer in tracepoint_ptr_deref. Link: https://lkml.kernel.org/r/20210202072326.120557-1-aik@ozlabs.ru

Alexey Kardashevskiy committed 5 years ago

Commit c8b186a1 parent 0188b871 file · +7 −5Browse files

Showing the changes to include/linux (1 of 1 file). Show all

Unified · Split

include/linux/tracepoint.h+7−5
@@ -307,11 +307,13 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p) · 306 unmodified lines
307307 \
308308 it_func_ptr = \
309309 rcu_dereference_raw((&__tracepoint_##_name)->funcs); \
310− do { \
311− it_func = (it_func_ptr)->func; \
312− __data = (it_func_ptr)->data; \
313− ((void(*)(void *, proto))(it_func))(__data, args); \
314− } while ((++it_func_ptr)->func); \
310+ if (it_func_ptr) { \
311+ do { \
312+ it_func = (it_func_ptr)->func; \
313+ __data = (it_func_ptr)->data; \
314+ ((void(*)(void *, proto))(it_func))(__data, args); \
315+ } while ((++it_func_ptr)->func); \
316+ } \
315317 return 0; \
316318 } \
317319 DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name);