From: W.C.A. Wijngaards Date: Tue, 11 Aug 2026 07:42:30 +0000 (+0200) Subject: - Fix #1492 from zacek: Data race in log_init() on X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c58e6add2b90e36bd71f7abe2ea8c780ebbb0775;p=thirdparty%2Funbound.git - Fix #1492 from zacek: Data race in log_init() on key_created/log_lock when calling ub_ctx_create() concurrently from multiple threads. --- diff --git a/doc/Changelog b/doc/Changelog index 25a43cfd6..84f7aaea7 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,8 @@ +11 August 2026: Wouter + - Fix #1492 from zacek: Data race in log_init() on + key_created/log_lock when calling ub_ctx_create() + concurrently from multiple threads. + 7 August 2026: Wouter - Fix #1489 from jplesnik: Replace removed Python 2 C API macros for SWIG 4.5.0 compatibility. diff --git a/util/log.c b/util/log.c index f2beafc87..e618ee051 100644 --- a/util/log.c +++ b/util/log.c @@ -72,6 +72,14 @@ static ub_thread_key_type logkey; #ifndef THREADS_DISABLED /** pthread mutex to protect FILE* */ static lock_basic_type log_lock; +#ifdef HAVE_PTHREAD +/* Guards the one-time initialization below. Without this, two threads + * calling log_init() for the first time concurrently (e.g. via + * ub_ctx_create() from a multi-threaded application) can both observe + * key_created==0 and both call lock_basic_init(&log_lock), a data race + * that reinitializes/corrupts an in-use mutex. */ +static pthread_once_t log_lock_once = PTHREAD_ONCE_INIT; +#endif #endif /** the identity of this executable/process */ static const char* ident="unbound"; @@ -85,15 +93,28 @@ static int log_time_asc = 0; /** print time in iso format */ static int log_time_iso = 0; +#if !defined(THREADS_DISABLED) && defined(HAVE_PTHREAD) +static void log_lock_init_once(void) +{ + ub_thread_key_create(&logkey, NULL); + lock_basic_init(&log_lock); + key_created = 1; +} +#endif + void log_init(const char* filename, int use_syslog, const char* chrootdir) { FILE *f; +#if !defined(THREADS_DISABLED) && defined(HAVE_PTHREAD) + (void)pthread_once(&log_lock_once, log_lock_init_once); +#else if(!key_created) { key_created = 1; ub_thread_key_create(&logkey, NULL); lock_basic_init(&log_lock); } +#endif lock_basic_lock(&log_lock); if(logfile #if defined(HAVE_SYSLOG_H) || defined(UB_ON_WINDOWS)