]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: thread: Fix a deadlock if an isolated thread is marked as harmless
authorChristopher Faulet <cfaulet@haproxy.com>
Thu, 25 Mar 2021 13:11:36 +0000 (14:11 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Thu, 25 Mar 2021 13:31:50 +0000 (14:31 +0100)
If an isolated thread is marked as harmless, it will loop forever in
thread_harmless_till_end() waiting no threads are isolated anymore. It never
happens because the current thread is isolated. To fix the bug, we exclude
the current thread for the test. We now wait for all other threads to leave
the rendez-vous point.

This bug only seems to occurr if HAProxy is compiled with DEBUG_UAF, when
pool_gc() is called. pool_gc() isolates the current thread, while
pool_free_area() set the thread as harmless when munmap is called.

This patch must be backported as far as 2.0.

src/thread.c

index 06612e2532bf084c37f71528eff93a5997948c29..93a529420414695ca5762d5f0ffef1684a0cb4e7 100644 (file)
@@ -48,13 +48,15 @@ struct lock_stat lock_stats[LOCK_LABELS];
 #endif
 
 /* Marks the thread as harmless until the last thread using the rendez-vous
- * point quits. Given that we can wait for a long time, sched_yield() is used
- * when available to offer the CPU resources to competing threads if needed.
+ * point quits, excluding the current one. Thus an isolated thread may be safely
+ * marked as harmless. Given that we can wait for a long time, sched_yield() is
+ * used when available to offer the CPU resources to competing threads if
+ * needed.
  */
 void thread_harmless_till_end()
 {
                _HA_ATOMIC_OR(&threads_harmless_mask, tid_bit);
-               while (threads_want_rdv_mask & all_threads_mask) {
+               while (threads_want_rdv_mask & ~tid_bit) {
                        ha_thread_relax();
                }
 }