aboutsummaryrefslogtreecommitdiffstats
path: root/driver
diff options
context:
space:
mode:
authorSimon Rozman <simon.rozman@amebis.si>2026-02-24 15:47:17 -0800
committerSimon Rozman <simon.rozman@amebis.si>2026-03-18 18:49:30 +0100
commitec0a6b98456fe1ba52567bb2add4bbf5f64315a1 (patch)
tree476257f3f18cca7ee32bcc26528b6d45de867cef /driver
parentdriver: fix race condition at Ring->Head (diff)
downloadwintun-master.tar.xz
wintun-master.zip
driver: fix missed-wakeup race in ring buffer Alertable signalingHEADmaster
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 'driver')
-rw-r--r--driver/wintun.c1
1 files changed, 1 insertions, 0 deletions
diff --git a/driver/wintun.c b/driver/wintun.c
index 82e346b..72ba5d3 100644
--- a/driver/wintun.c
+++ b/driver/wintun.c
@@ -481,6 +481,7 @@ TunProcessReceiveData(_Inout_ TUN_CTX *Ctx)
if (RingHead == RingTail)
{
WriteRelease(&Ring->Alertable, TRUE);
+ MemoryBarrier();
RingTail = ReadULongAcquire(&Ring->Tail);
if (RingHead == RingTail)
{