Workaround potential access to unmapped stack

Issue:
Process is crashed near the end (startup_handshake_lock.unlock()) in
pthread_create().

The newly created child thread passes this handshake_lock unexpectedly
=> its stack is unmapped & its associated pthread_internal_t data
structure can’t be accessed.

Analysis:
The created child thread should be blocked by startup_handshake_lock.lock()
and enter __futex_wait_ex()

But if the parent thread is in the middle of startup_handshake_lock.unlock():

  void unlock() {
    if (atomic_exchange_explicit(&state, Unlocked, memory_order_seq_cst) == LockedWithWaiter) {  // => the state is modified to Unlocked

    // (a) if the child thread is back to running and pass the while() check in Lock::lock()
    // (b) the child thread executes its start_routine and then pthread_exit
    // (c) the stack of the child thread (where its pthread_internal_t (so the startup_handshake_lock) is located) will be unmapped

     __futex_wake_ex(&state, process_shared, 1);   // => when the parent thread is back to running
                                                   // the “state” & “process_shared” of startup_handshake_lock can’t be accessed (unmapped)
                                                   // so the process will be crashed
    }
  }

Bug: 129744706
Test: Monkey

(cherry picked from commit 8c1a14d4f358a8135e0c0632da6d40c37192c0c2)

Change-Id: I88f3e1f205f802ece751aacd63fe7d3cc56f2a5f
diff --git a/libc/private/bionic_lock.h b/libc/private/bionic_lock.h
index 410e637..ec179d1 100644
--- a/libc/private/bionic_lock.h
+++ b/libc/private/bionic_lock.h
@@ -70,8 +70,9 @@
   }
 
   void unlock() {
+    bool shared = process_shared; /* cache to local variable */
     if (atomic_exchange_explicit(&state, Unlocked, memory_order_release) == LockedWithWaiter) {
-      __futex_wake_ex(&state, process_shared, 1);
+      __futex_wake_ex(&state, shared, 1);
     }
   }
 };