@@ -133,18 +133,41 @@ class GhostStackImpl {
133133 /* *
134134 * Reset the shadow stack, restoring all original return addresses.
135135 *
136- * This is the normal reset path - it restores the original return addresses
137- * to the stack before clearing the shadow stack entries.
136+ * On ARM64, stale trampolines may still fire after reset() because the LR
137+ * register may have already been loaded with the trampoline address before
138+ * we restored the stack location. We keep entries_ around to handle these
139+ * stale trampolines gracefully.
140+ *
141+ * We restore ALL entries (not just 0 to tail-1) but only if the location
142+ * still contains the trampoline address. This handles the case where a
143+ * location was reused by a new frame after its original trampoline fired.
138144 */
139145 void reset () {
140146 if (trampolines_installed_) {
141- size_t tail = tail_.load (std::memory_order_acquire);
142- // With reversed order, iterate from 0 to tail (all entries below tail)
143- for (size_t i = 0 ; i < tail; ++i) {
144- *entries_[i].location = entries_[i].return_address ;
147+ uintptr_t tramp_addr = reinterpret_cast <uintptr_t >(ghost_ret_trampoline);
148+
149+ // Restore ALL entries whose locations still contain the trampoline.
150+ // This handles both pending entries AND already-fired entries whose
151+ // locations haven't been reused by new frames.
152+ for (size_t i = 0 ; i < entries_.size (); ++i) {
153+ uintptr_t current_value = *entries_[i].location ;
154+ // Strip PAC bits before comparison - on ARM64 with PAC enabled,
155+ // the value read from stack may be PAC-signed while tramp_addr is not
156+ uintptr_t stripped_value = ptrauth_strip (current_value);
157+ if (stripped_value == tramp_addr) {
158+ *entries_[i].location = entries_[i].return_address ;
159+ }
145160 }
161+
162+ // Mark trampolines as not installed, but DON'T clear entries_!
163+ // On ARM64, stale trampolines may still fire because LR was loaded
164+ // before we restored the stack. Keep entries_ so we can still
165+ // return the correct address.
166+ trampolines_installed_ = false ;
167+
168+ // Increment epoch to signal state change
169+ epoch_.fetch_add (1 , std::memory_order_release);
146170 }
147- clear_entries ();
148171 }
149172
150173public:
0 commit comments