From dda8901294d4c820b125c8b13ae6c219b57840ee Mon Sep 17 00:00:00 2001 From: Cheng Shao <terrorjack@type.dance> Date: Thu, 22 Feb 2024 13:47:54 +0000 Subject: [PATCH] rts: add missing ccs_mutex guard to internal_dlopen See added comment for details. Closes #24423. (cherry picked from commit 20f80b775971a4fc08397c9b569f2b72c34cad5b) --- rts/Linker.c | 19 +++++++++++++++++++ rts/Profiling.c | 2 +- rts/Profiling.h | 4 ++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/rts/Linker.c b/rts/Linker.c index 51a10a79a6a..9a9051d8821 100644 --- a/rts/Linker.c +++ b/rts/Linker.c @@ -598,8 +598,27 @@ internal_dlopen(const char *dll_name) // (see POSIX also) ACQUIRE_LOCK(&dl_mutex); + + // When dlopen() loads a profiled dynamic library, it calls the + // ctors which will call registerCcsList() to append the defined + // CostCentreStacks to CCS_LIST. This execution path starting from + // addDLL() was only protected by dl_mutex previously. However, + // another thread may be doing other things with the RTS linker + // that transitively calls refreshProfilingCCSs() which also + // accesses CCS_LIST, and those execution paths are protected by + // linker_mutex. So there's a risk of data race that may lead to + // segfaults (#24423), and we need to ensure the ctors are also + // protected by ccs_mutex. +#if defined(PROFILING) + ACQUIRE_LOCK(&ccs_mutex); +#endif + hdl = dlopen(dll_name, RTLD_LAZY|RTLD_LOCAL); /* see Note [RTLD_LOCAL] */ +#if defined(PROFILING) + RELEASE_LOCK(&ccs_mutex); +#endif + errmsg = NULL; if (hdl == NULL) { /* dlopen failed; return a ptr to the error msg. */ diff --git a/rts/Profiling.c b/rts/Profiling.c index 9dde1f28604..c3408fb8098 100644 --- a/rts/Profiling.c +++ b/rts/Profiling.c @@ -58,7 +58,7 @@ CostCentre *CC_LIST = NULL; static CostCentreStack *CCS_LIST = NULL; #if defined(THREADED_RTS) -static Mutex ccs_mutex; +Mutex ccs_mutex; #endif /* diff --git a/rts/Profiling.h b/rts/Profiling.h index b3724c3c881..d91e2cc9c1b 100644 --- a/rts/Profiling.h +++ b/rts/Profiling.h @@ -55,6 +55,10 @@ extern Arena *prof_arena; void debugCCS( CostCentreStack *ccs ); #endif +#if defined(THREADED_RTS) +extern Mutex ccs_mutex; +#endif + #endif #include "EndPrivate.h" -- GitLab