Fix: racy init_done initialization master
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Sat, 28 Sep 2024 10:57:42 +0000 (06:57 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Sat, 28 Sep 2024 10:57:42 +0000 (06:57 -0400)
If init_done is set while another thread is loading its value, the other
thread can erroneously expect initialization to be complete while the
initialization is still in progress.

Set init_done after initialization with a store-release, and load it
with load-acquire outside of the mutex critical section.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Change-Id: Idb1345c6dcf3da7d711937bd5072527c0bf1d33a

src/rseq.c

index 7ee3616e0463b11d1d0d55693779434ae6277e87..9b5470e1922f8fee32fcfd09ef326bc5b433df78 100644 (file)
@@ -209,8 +209,12 @@ int rseq_unregister_current_thread(void)
 static
 void rseq_init(void)
 {
-       /* Ensure initialization is only done once. */
-       if (RSEQ_READ_ONCE(init_done))
+       /*
+        * Ensure initialization is only done once. Use load-acquire to
+        * observe the initialization performed by a concurrently
+        * running thread.
+        */
+       if (rseq_smp_load_acquire(&init_done))
                return;
 
        /*
@@ -220,7 +224,6 @@ void rseq_init(void)
        pthread_mutex_lock(&init_lock);
        if (init_done)
                goto unlock;
-       RSEQ_WRITE_ONCE(init_done, 1);
 
        /*
         * Check for glibc rseq support, if the 3 public symbols are found and
@@ -286,6 +289,11 @@ void rseq_init(void)
         * libc behavior.
         */
        rseq_size = 0;
+       /*
+        * Set init_done with store-release, to make sure concurrently
+        * running threads observe the initialized state.
+        */
+       rseq_smp_store_release(&init_done, 1);
 unlock:
        pthread_mutex_unlock(&init_lock);
 }
This page took 0.0245 seconds and 4 git commands to generate.