One subtle issue found by Specula:
FutexManager::wait inserts a waiter into the futex bucket before it validates that the futex word still equals the expected value. FutexManager::wake(count=1) scans and counts matching queue entries without knowing whether a selected waiter has passed that validation. As a result, an unvalidated waiter can consume the single wake quota, return ImmediatelyWokenBecauseValueMismatch, and leave a validated waiter blocked.
See the full report for more details.
According to copilot, Linux uses a two-stage approach:
- Under the bucket lock, perform a no-fault read.
- If it faults, release the lock.
- Perform a normal fault-capable read to bring the page in.
- Reacquire the lock and repeat the comparison.
- Enqueue only while still holding that lock.
LiteBox currently inserts and then checks without holding the list lock across both operations, which avoids missed wakes but introduces the wake-consumption race we identified. LoanList already has a per-bucket mutex; its API just does not expose atomic check-and-insert. A robust LiteBox fix likely needs a distinct read_no_fault() operation. Using the existing read_at_offset() under the LoanList lock requires guaranteeing that it cannot block or re-enter lock-dependent code.
One subtle issue found by Specula:
FutexManager::wait inserts a waiter into the futex bucket before it validates that the futex word still equals the expected value. FutexManager::wake(count=1) scans and counts matching queue entries without knowing whether a selected waiter has passed that validation. As a result, an unvalidated waiter can consume the single wake quota, return ImmediatelyWokenBecauseValueMismatch, and leave a validated waiter blocked.
See the full report for more details.
According to copilot, Linux uses a two-stage approach:
LiteBox currently inserts and then checks without holding the list lock across both operations, which avoids missed wakes but introduces the wake-consumption race we identified. LoanList already has a per-bucket mutex; its API just does not expose atomic check-and-insert. A robust LiteBox fix likely needs a distinct read_no_fault() operation. Using the existing read_at_offset() under the LoanList lock requires guaranteeing that it cannot block or re-enter lock-dependent code.