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

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
307 \307 \
308 it_func_ptr = \308 it_func_ptr = \
309 rcu_dereference_raw((&__tracepoint_##_name)->funcs); \309 rcu_dereference_raw((&__tracepoint_##_name)->funcs); \
310 do { \310 if (it_func_ptr) { \
311 it_func = (it_func_ptr)->func; \311 do { \
312 __data = (it_func_ptr)->data; \312 it_func = (it_func_ptr)->func; \
313 ((void(*)(void *, proto))(it_func))(__data, args); \313 __data = (it_func_ptr)->data; \
314 } while ((++it_func_ptr)->func); \314 ((void(*)(void *, proto))(it_func))(__data, args); \
315 } while ((++it_func_ptr)->func); \
316 } \
315 return 0; \317 return 0; \
316 } \318 } \
317 DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name);319 DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name);