diff options
| author | 2026-02-24 15:47:17 -0800 | |
|---|---|---|
| committer | 2026-03-18 18:49:30 +0100 | |
| commit | ec0a6b98456fe1ba52567bb2add4bbf5f64315a1 (patch) | |
| tree | 476257f3f18cca7ee32bcc26528b6d45de867cef /api/api.vcxproj | |
| parent | driver: fix race condition at Ring->Head (diff) | |
| download | wintun-master.tar.xz wintun-master.zip | |
Add MemoryBarrier() between store-load pairs in the Dekker-style
synchronization used by the Receive ring's Alertable/Tail protocol.
On x86-64, WriteRelease/ReadAcquire only prevent compiler reordering and
provide acquire/release semantics, but do not emit MFENCE — the only
instruction that prevents store-load reordering across cores. Without a
full barrier, both the userspace producer and the kernel consumer can
simultaneously read stale values:
Userspace: STORE(Tail) ... LOAD(Alertable) -> sees FALSE (stale)
Driver: STORE(Alertable=TRUE) ... LOAD(Tail) -> sees old tail
The driver then enters KeWaitForMultipleObjects with no pending
SetEvent, sleeping until a TCP retransmission (typically 4-5s later)
re-triggers the send path and wins the race.
The fix adds MemoryBarrier() (MFENCE on x86) on both sides:
- api/session.c WintunSendPacket: between WriteULongRelease(Tail) and
ReadAcquire(Alertable)
- driver/twintun.c TunProcessReceiveData: between
WriteRelease(Alertable, TRUE) and ReadULongAcquire(Tail)
This guarantees that at least one side always observes the other's
store, preventing the missed wakeup while preserving the Alertable
optimization that avoids unnecessary SetEvent syscalls.
Reported-by: Alexey Lapuka <alexey@twingate.com>
Reference: https://lists.zx2c4.com/pipermail/wireguard/2026-February/009523.html
Signed-off-by: Simon Rozman <simon.rozman@amebis.si>
Diffstat (limited to 'api/api.vcxproj')
0 files changed, 0 insertions, 0 deletions
