Skip to content

gh-148820: Fix _PyRawMutex use-after-free on spurious semaphore wakeup#148852

Draft
colesbury wants to merge 1 commit intopython:mainfrom
colesbury:gh-148820-raw-mutex-park-intr
Draft

gh-148820: Fix _PyRawMutex use-after-free on spurious semaphore wakeup#148852
colesbury wants to merge 1 commit intopython:mainfrom
colesbury:gh-148820-raw-mutex-park-intr

Conversation

@colesbury
Copy link
Copy Markdown
Contributor

@colesbury colesbury commented Apr 21, 2026

_PyRawMutex_UnlockSlow CAS-removes the waiter from the list and then calls _PySemaphore_Wakeup, with no handshake. If _PySemaphore_Wait returns Py_PARK_INTR, the waiter can destroy its stack-allocated semaphore before the unlocker's Wakeup runs, causing a fatal error from ReleaseSemaphore / sem_post.

Loop in _PyRawMutex_LockSlow until _PySemaphore_Wait returns Py_PARK_OK, which is only signalled when a matching Wakeup has been observed.

Also include GetLastError() and the handle in the Windows fatal messages in _PySemaphore_Init, _PySemaphore_Wait, and _PySemaphore_Wakeup to make similar races easier to diagnose in the future.

… wakeup

_PyRawMutex_UnlockSlow CAS-removes the waiter from the list and then
calls _PySemaphore_Wakeup, with no handshake. If _PySemaphore_Wait
returns Py_PARK_INTR, the waiter can destroy its stack-allocated
semaphore before the unlocker's Wakeup runs, causing a fatal error from
ReleaseSemaphore / sem_post.

Loop in _PyRawMutex_LockSlow until _PySemaphore_Wait returns Py_PARK_OK,
which is only signalled when a matching Wakeup has been observed.

Also include GetLastError() and the handle in the Windows fatal messages
in _PySemaphore_Init, _PySemaphore_Wait, and _PySemaphore_Wakeup to make
similar races easier to diagnose in the future.
@colesbury
Copy link
Copy Markdown
Contributor Author

I played around with adding a regression test for this, but I think it's trick to get right. You have to raise a SIGINT at just the right point. However, if you raise SIGINT too frequently you can cause a stack overflow in the main thread due to Python signal handlers being called within Python signal handlers...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant