From Jean-Alexandre.CHRONE at stormshield.eu Mon Feb 2 14:36:00 2026 From: Jean-Alexandre.CHRONE at stormshield.eu (Jean-Alexandre CHRONE) Date: Mon, 2 Feb 2026 14:36:00 +0000 Subject: [PATCH] api: use mutex when removing instance on close adapter Message-ID: <7ef930c54a4b4aa5bd3ecd9cf01fe12a@stormshield.eu> >From 298267d3ead7110880a5dc0f5d0e8822600d30c0 Mon Sep 17 00:00:00 2001 From: "jean-alexandre.chrone" Date: Mon, 2 Feb 2026 15:24:12 +0100 Subject: [PATCH] api: use mutex when removing instance on close adapter on successive create and close there might be some error logged --- api/adapter.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/api/adapter.c b/api/adapter.c index 0dd8c42..042645c 100644 --- a/api/adapter.c +++ b/api/adapter.c @@ -158,7 +158,8 @@ VOID AdapterCleanupOrphanedDevices(VOID) continue; } ULONG Status, Code; - if (CM_Get_DevNode_Status(&Status, &Code, DevInfoData.DevInst, 0) == CR_SUCCESS && !(Status & DN_HAS_PROBLEM)) + CONFIGRET Ret = CM_Get_DevNode_Status(&Status, &Code, DevInfoData.DevInst, 0); + if ((Ret == CR_SUCCESS && !(Status & DN_HAS_PROBLEM)) || Ret == CR_NO_SUCH_DEVNODE) continue; DEVPROPTYPE PropType; @@ -195,8 +196,16 @@ WintunCloseAdapter(WINTUN_ADAPTER *Adapter) SwDeviceClose(Adapter->SwDevice); if (Adapter->DevInfo) { + HANDLE DeviceInstallationMutex = NamespaceTakeDeviceInstallationMutex(); + if (DeviceInstallationMutex == NULL) + LOG_LAST_ERROR(L"Failed to take device installation mutex"); + if (!AdapterRemoveInstance(Adapter->DevInfo, &Adapter->DevInfoData)) LOG_LAST_ERROR(L"Failed to remove adapter when closing"); + + if (DeviceInstallationMutex != NULL) + NamespaceReleaseMutex(DeviceInstallationMutex); + SetupDiDestroyDeviceInfoList(Adapter->DevInfo); } Free(Adapter); -- 2.52.0.windows.1 From katz.oded at gmail.com Wed Feb 4 18:19:17 2026 From: katz.oded at gmail.com (Oded Katz) Date: Wed, 4 Feb 2026 10:19:17 -0800 Subject: Fwd: I want to report an issue I found with your example (send ring buffer get corrupted) In-Reply-To: References: Message-ID: Hi, I'm reposting this one as I didn't get any response. We were trying to integrate `wintun` into our product and while testing we found an issue with upload of high UDP throughput on multiple sockets. initially we thought it may be related to our integration. but we managed to find the same issue in your example code.we tried to do some debugging on the example, but it seems like the corruption is on the driver side. the way to reproduce this issue- run the example - run the `send_udp.py` (the attached python script) on 2 different command terminals - `send_udp.py 10.6.7.8 5201 1450` - `send_udp.py 10.6.7.8 5201 1400`after some time the `WintunReceivePacket` returns NULL and `GetLastError()` return 13 (`ERROR_INVALID_DATA`) many thanks, and I hope you can help us. btw: in the meantime, I'll try to see if I can contribute myself with a fix Oded -------------- next part -------------- A non-text attachment was scrubbed... Name: send_udp.py Type: text/x-python Size: 5078 bytes Desc: not available URL: From valentin at spreckels.dev Sun Feb 8 17:05:45 2026 From: valentin at spreckels.dev (Valentin Spreckels) Date: Sun, 8 Feb 2026 18:05:45 +0100 Subject: [PATCH wireguard] wireguard: prevent ipv6 addrconf via IFF_NO_ADDRCONF flag Message-ID: <20260208170545.31942-1-valentin@spreckels.dev> Use the flag introduced in commit 8a321cf7becc6 ("net: add IFF_NO_ADDRCONF and use it in bonding to prevent ipv6 addrconf") instead of mangling the addr_gen_mode to prevent ipv6 addrconf. Signed-off-by: Valentin Spreckels --- drivers/net/wireguard/device.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c index 46a71ec36af87..4b29f2fa51d1d 100644 --- a/drivers/net/wireguard/device.c +++ b/drivers/net/wireguard/device.c @@ -31,7 +31,6 @@ static LIST_HEAD(device_list); static int wg_open(struct net_device *dev) { struct in_device *dev_v4 = __in_dev_get_rtnl(dev); - struct inet6_dev *dev_v6 = __in6_dev_get(dev); struct wg_device *wg = netdev_priv(dev); struct wg_peer *peer; int ret; @@ -44,8 +43,6 @@ static int wg_open(struct net_device *dev) IN_DEV_CONF_SET(dev_v4, SEND_REDIRECTS, false); IPV4_DEVCONF_ALL(dev_net(dev), SEND_REDIRECTS) = false; } - if (dev_v6) - dev_v6->cnf.addr_gen_mode = IN6_ADDR_GEN_MODE_NONE; mutex_lock(&wg->device_update_lock); ret = wg_socket_init(wg, wg->incoming_port); @@ -288,7 +285,7 @@ static void wg_setup(struct net_device *dev) dev->needed_tailroom = noise_encrypted_len(MESSAGE_PADDING_MULTIPLE); dev->type = ARPHRD_NONE; dev->flags = IFF_POINTOPOINT | IFF_NOARP; - dev->priv_flags |= IFF_NO_QUEUE; + dev->priv_flags |= IFF_NO_QUEUE | IFF_NO_ADDRCONF; dev->lltx = true; dev->features |= WG_NETDEV_FEATURES; dev->hw_features |= WG_NETDEV_FEATURES; -- 2.52.0 From samsun1006219 at gmail.com Mon Feb 2 15:06:28 2026 From: samsun1006219 at gmail.com (Sam Sun) Date: Mon, 2 Feb 2026 23:06:28 +0800 Subject: [Linux kernel bug] general protection fault in wg_packet_send_queued_handshake_initiation Message-ID: Dear developers and maintainers, We have encountered a kernel crash in __queue_work occurring within the wg_packet_handshake_send_worker context. The call trace indicates the crash happens when wg_expired_send_persistent_keepalive (timer callback) attempts to queue a specific work item while the interface is being destroyed. The original crash log is listed below. Oops: general protection fault, probably for non-canonical address 0xe1d2d8131fe22003: 0000 [#1] SMP KASAN NOPTI KASAN: maybe wild-memory-access in range [0x0e96e098ff110018-0x0e96e098ff11001f] CPU: 1 UID: 0 PID: 7634 Comm: kworker/u10:17 Tainted: G L 6.19.0-rc6-00003-g13bede03f3b8-dirty #18 PREEMPT(full) Tainted: [L]=SOFTLOCKUP Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014 Workqueue: wg-kex-wg0 wg_packet_handshake_send_worker RIP: 0010:kasan_byte_accessible+0x15/0x30 mm/kasan/generic.c:210 Code: 00 00 0f 1f 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 0f 1f 40 d6 48 b8 00 00 00 00 00 fc ff df 48 c1 ef 03 48 01 c7 <0f> b6 07 3c 07 0f 96 c0 c3 cc cc cc cc 66 66 2e 0f 1f 84 00 00 00 RSP: 0018:ffa00000001d89c0 EFLAGS: 00010086 RAX: dffffc0000000000 RBX: 0000000000000001 RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffffffff8b56293e RDI: e1d2d8131fe22003 RBP: 0e96e098ff110018 R08: 0000000000000001 R09: 0000000000000000 R10: ff11000100070003 R11: 0000000000000007 R12: 0000000000000000 R13: ffffffff8b56293e R14: 0000000000000000 R15: 0000000000000000 FS: 0000000000000000(0000) GS:ff110001a1773000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fd5733fc158 CR3: 000000000df84000 CR4: 0000000000753ef0 PKRU: 55555554 Call Trace: __kasan_check_byte+0x14/0x50 mm/kasan/common.c:573 kasan_check_byte include/linux/kasan.h:402 [inline] lock_acquire kernel/locking/lockdep.c:5842 [inline] lock_acquire+0xfd/0x330 kernel/locking/lockdep.c:5825 __raw_spin_lock include/linux/spinlock_api_smp.h:133 [inline] _raw_spin_lock+0x2e/0x40 kernel/locking/spinlock.c:154 __queue_work+0xac2/0x12b0 kernel/workqueue.c:2315 queue_work_on+0x11c/0x140 kernel/workqueue.c:2418 queue_work include/linux/workqueue.h:765 [inline] wg_packet_send_queued_handshake_initiation+0x220/0x410 drivers/net/wireguard/send.c:75 wg_packet_send_staged_packets+0x10f0/0x1890 drivers/net/wireguard/send.c:413 wg_packet_send_keepalive+0x4b/0x2f0 drivers/net/wireguard/send.c:239 wg_expired_send_persistent_keepalive+0x5e/0x70 drivers/net/wireguard/timers.c:144 call_timer_fn+0x19f/0x570 kernel/time/timer.c:1748 expire_timers kernel/time/timer.c:1799 [inline] __run_timers+0x6d2/0xac0 kernel/time/timer.c:2373 __run_timer_base kernel/time/timer.c:2385 [inline] __run_timer_base kernel/time/timer.c:2377 [inline] run_timer_base+0xc5/0x120 kernel/time/timer.c:2394 run_timer_softirq+0x1a/0x40 kernel/time/timer.c:2404 handle_softirqs+0x1d4/0x8e0 kernel/softirq.c:622 do_softirq kernel/softirq.c:523 [inline] do_softirq+0xac/0xe0 kernel/softirq.c:510 __local_bh_enable_ip+0x100/0x120 kernel/softirq.c:450 local_bh_enable include/linux/bottom_half.h:33 [inline] fpregs_unlock arch/x86/include/asm/fpu/api.h:77 [inline] kernel_fpu_end arch/x86/kernel/fpu/core.c:506 [inline] kernel_fpu_end+0x5e/0x70 arch/x86/kernel/fpu/core.c:499 blake2s_compress+0x77/0xe0 lib/crypto/x86/blake2s.h:42 blake2s_update+0xb6/0x1f0 lib/crypto/blake2s.c:119 mix_hash+0xf1/0x140 drivers/net/wireguard/noise.c:438 message_encrypt drivers/net/wireguard/noise.c:470 [inline] wg_noise_handshake_create_initiation+0x363/0x5c0 drivers/net/wireguard/noise.c:555 wg_packet_send_handshake_initiation+0x182/0x340 drivers/net/wireguard/send.c:34 wg_packet_handshake_send_worker+0x1c/0x30 drivers/net/wireguard/send.c:51 process_one_work+0x9cd/0x1ba0 kernel/workqueue.c:3304 process_scheduled_works kernel/workqueue.c:3401 [inline] worker_thread+0x67e/0xe90 kernel/workqueue.c:3482 kthread+0x3d0/0x780 kernel/kthread.c:463 ret_from_fork+0x966/0xaf0 arch/x86/kernel/process.c:158 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:246 Modules linked in: ---[ end trace 0000000000000000 ]--- RIP: 0010:kasan_byte_accessible+0x15/0x30 mm/kasan/generic.c:210 Code: 00 00 0f 1f 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 0f 1f 40 d6 48 b8 00 00 00 00 00 fc ff df 48 c1 ef 03 48 01 c7 <0f> b6 07 3c 07 0f 96 c0 c3 cc cc cc cc 66 66 2e 0f 1f 84 00 00 00 RSP: 0018:ffa00000001d89c0 EFLAGS: 00010086 RAX: dffffc0000000000 RBX: 0000000000000001 RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffffffff8b56293e RDI: e1d2d8131fe22003 RBP: 0e96e098ff110018 R08: 0000000000000001 R09: 0000000000000000 R10: ff11000100070003 R11: 0000000000000007 R12: 0000000000000000 R13: ffffffff8b56293e R14: 0000000000000000 R15: 0000000000000000 FS: 0000000000000000(0000) GS:ff110001a1773000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fd5733fc158 CR3: 000000000df84000 CR4: 0000000000753ef0 PKRU: 55555554 ---------------- Code disassembly (best guess): 0: 00 00 add %al,(%rax) 2: 0f 1f 00 nopl (%rax) 5: 90 nop 6: 90 nop 7: 90 nop 8: 90 nop 9: 90 nop a: 90 nop b: 90 nop c: 90 nop d: 90 nop e: 90 nop f: 90 nop 10: 90 nop 11: 90 nop 12: 90 nop 13: 90 nop 14: 90 nop 15: 0f 1f 40 d6 nopl -0x2a(%rax) 19: 48 b8 00 00 00 00 00 movabs $0xdffffc0000000000,%rax 20: fc ff df 23: 48 c1 ef 03 shr $0x3,%rdi 27: 48 01 c7 add %rax,%rdi * 2a: 0f b6 07 movzbl (%rdi),%eax <-- trapping instruction 2d: 3c 07 cmp $0x7,%al 2f: 0f 96 c0 setbe %al 32: c3 ret 33: cc int3 34: cc int3 35: cc int3 36: cc int3 37: 66 data16 38: 66 data16 39: 2e cs 3a: 0f .byte 0xf 3b: 1f (bad) 3c: 84 00 test %al,(%rax) <<<<<<<<<<<<<<< tail report >>>>>>>>>>>>>>> Analysis: The crash happens at raw_spin_lock(&pool->lock) inside __queue_work. The faulting address (0xe1d2d8...) suggests that the code is accessing a garbage pointer, characteristic of a Use-After-Free error. Suspected Root Cause: The issue could be resulted by race condition between another thread invoking destroy_workqueue and the current thread. Unfortunately, we don't have any reproducible PoC yet. Best Regards, Yue From rudi at heitbaum.com Sat Feb 7 05:12:27 2026 From: rudi at heitbaum.com (Rudi Heitbaum) Date: Sat, 7 Feb 2026 05:12:27 +0000 Subject: [PATCH] wireguard-tools: retain const qualifier from pointer Message-ID: Since glibc-2.43: For ISO C23, the functions bsearch, memchr, strchr, strpbrk, strrchr, strstr, wcschr, wcspbrk, wcsrchr, wcsstr and wmemchr that return pointers into their input arrays now have definitions as macros that return a pointer to a const-qualified type when the in put argument is a pointer to a const-qualified type. https://lists.gnu.org/archive/html/info-gnu/2026-01/msg00005.html Resolves the following warning: config.c: In function 'config_read_line': config.c:513:17: warning: assignment discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers] 513 | comment = strchr(input, COMMENT_CHAR); | ^ Signed-off-by: Rudi Heitbaum --- src/config.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/config.c b/src/config.c index 6b8aa58..cd65d7e 100644 --- a/src/config.c +++ b/src/config.c @@ -506,7 +506,8 @@ error: bool config_read_line(struct config_ctx *ctx, const char *input) { size_t len, cleaned_len = 0; - char *line, *comment; + const char *comment; + char *line; bool ret = true; /* This is what strchrnul is for, but that isn't portable. */ -- 2.51.0 From list at eworm.de Tue Feb 10 13:30:16 2026 From: list at eworm.de (Christian Hesse) Date: Tue, 10 Feb 2026 14:30:16 +0100 Subject: Arch Linux - out of date?! Message-ID: <20260210143016.0144acf1@leda.eworm.net> Hello everybody, for some time already I am annoyed by mails clogging my input regarding wireguard-tools for Arch Linux being out of date. Obviously this is not true, I built the package the day of release. [0] Now found the install page mentioning the package being out-of date... [1] What goes wrong and how to fix that? [0] https://archlinux.org/packages/extra/x86_64/wireguard-tools/ [1] https://www.wireguard.com/install/#arch-module-tools -- main(a){char*c=/* Schoene Gruesse */"B?IJj;MEH" "CX:;",b;for(a/* Best regards my address: */=0;b=c[a++];) putchar(b-1/(/* Chris cc -ox -xc - && ./x */b/42*2-3)*42);} -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 488 bytes Desc: OpenPGP digital signature URL: From simon.rozman at amebis.si Mon Feb 9 10:33:05 2026 From: simon.rozman at amebis.si (Simon Rozman) Date: Mon, 9 Feb 2026 11:33:05 +0100 Subject: BUG: Crash on log save for Windows wireguard-arm64-0.5.3.msi In-Reply-To: References: Message-ID: <36bfb316-20b0-453e-9a20-e1fc7f8d42c4@amebis.si> Hi! This was fixed in https://git.zx2c4.com/wireguard-windows/commit/?id=8e6558eba6665b51de35779bffa46803dbc4c10d and is pending a release. Meanwhile, you can `git clone https://git.zx2c4.com/wireguard-windows` and run build.bat on any Windows 10+ x64 PC and build it yourself. It is super-easy. The installation files will be marked as unofficial and not code-signed, but the rest should work. Lep pozdrav | Best regards, Simon Rozman Amebis, d. o. o., Kamnik On 11. 8. 2025 10.43, George wrote: > When I click the "Save" button or try to "Save to file" the contents > of the Log tab in Windows 11 the File Explorer window very briefly > pops up and then the app crashes entirely. > > I'm not seeing anything in the Event Viewer as far as a log goes for the app. > > Would appreciate any help isolating what may be causing this issue - > or determining if it's actually a bug that needs to be fixed. > > > Appreciate your help! > > -George From simon.rozman at amebis.si Mon Feb 9 12:02:36 2026 From: simon.rozman at amebis.si (Simon Rozman) Date: Mon, 9 Feb 2026 13:02:36 +0100 Subject: Fwd: I want to report an issue I found with your example (send ring buffer get corrupted) In-Reply-To: References: Message-ID: <8f88f226-031c-4aea-a71a-bf4a143b292b@amebis.si> Hi, Oded! Reviewing your issue closely, I may have found the cause. I have queued a proposal to fix it here: https://git.zx2c4.com/wintun/commit/driver/wintun.c?id=8814f660310c30a9297fc640c844c4ab6f27e5d7 However, I need to reinstall my testing environment to test and confirm it working. Lep pozdrav | Best regards, Simon Rozman Amebis, d. o. o., Kamnik On 4. 2. 2026 19.19, Oded Katz wrote: > Hi, > > I'm reposting this one as I didn't get any response. > > We were trying to integrate `wintun` into our product and while > testing we found an issue with upload of high UDP throughput on > multiple sockets. initially we thought it may be related to our > integration. but we managed to find the same issue in your example > code.we tried to do some debugging on the example, but it seems like > the corruption is on the driver side. > the way to reproduce this issue- run the example > - run the `send_udp.py` (the attached python script) on 2 different > command terminals > - `send_udp.py 10.6.7.8 5201 1450` > - `send_udp.py 10.6.7.8 5201 1400`after some time the > `WintunReceivePacket` returns NULL and `GetLastError()` return 13 > (`ERROR_INVALID_DATA`) > many thanks, > and I hope you can help us. > btw: in the meantime, I'll try to see if I can contribute myself with a fix > Oded From achill at achill.org Tue Feb 10 13:45:14 2026 From: achill at achill.org (Achill Gilgenast) Date: Tue, 10 Feb 2026 14:45:14 +0100 Subject: Arch Linux - out of date?! In-Reply-To: <20260210143016.0144acf1@leda.eworm.net> References: <20260210143016.0144acf1@leda.eworm.net> Message-ID: On Tue Feb 10, 2026 at 2:30 PM CET, Christian Hesse wrote: > Hello everybody, > > for some time already I am annoyed by mails clogging my input regarding > wireguard-tools for Arch Linux being out of date. Obviously this is not true, > I built the package the day of release. [0] > > Now found the install page mentioning the package being out-of date... [1] > What goes wrong and how to fix that? > > [0] https://archlinux.org/packages/extra/x86_64/wireguard-tools/ > [1] https://www.wireguard.com/install/#arch-module-tools Hi, Alpine dev here. The same issue is also for Alpine Linux. It has been up-to-date for a long while, yet people are spamming out-of-date email to Natanael. I could find no website development source or something, where this behavior could be improved. From katz.oded at gmail.com Thu Feb 12 16:38:37 2026 From: katz.oded at gmail.com (Oded Katz) Date: Thu, 12 Feb 2026 08:38:37 -0800 Subject: Fwd: I want to report an issue I found with your example (send ring buffer get corrupted) In-Reply-To: <8f88f226-031c-4aea-a71a-bf4a143b292b@amebis.si> References: <8f88f226-031c-4aea-a71a-bf4a143b292b@amebis.si> Message-ID: Thank you so much Simon, I can try those changes myself and let you know if the issue got resolved. again, thank you. Oded On Tue, Feb 10, 2026 at 9:49?AM Simon Rozman wrote: > > Hi, Oded! > > Reviewing your issue closely, I may have found the cause. I have queued > a proposal to fix it here: > https://git.zx2c4.com/wintun/commit/driver/wintun.c?id=8814f660310c30a9297fc640c844c4ab6f27e5d7 > > However, I need to reinstall my testing environment to test and confirm > it working. > > Lep pozdrav | Best regards, > Simon Rozman > Amebis, d. o. o., Kamnik > > On 4. 2. 2026 19.19, Oded Katz wrote: > > Hi, > > > > I'm reposting this one as I didn't get any response. > > > > We were trying to integrate `wintun` into our product and while > > testing we found an issue with upload of high UDP throughput on > > multiple sockets. initially we thought it may be related to our > > integration. but we managed to find the same issue in your example > > code.we tried to do some debugging on the example, but it seems like > > the corruption is on the driver side. > > the way to reproduce this issue- run the example > > - run the `send_udp.py` (the attached python script) on 2 different > > command terminals > > - `send_udp.py 10.6.7.8 5201 1450` > > - `send_udp.py 10.6.7.8 5201 1400`after some time the > > `WintunReceivePacket` returns NULL and `GetLastError()` return 13 > > (`ERROR_INVALID_DATA`) > > many thanks, > > and I hope you can help us. > > btw: in the meantime, I'll try to see if I can contribute myself with a fix > > Oded > From katz.oded at gmail.com Thu Feb 19 19:32:54 2026 From: katz.oded at gmail.com (odedkatz) Date: Thu, 19 Feb 2026 11:32:54 -0800 Subject: [PATCH 0/1] This PR fixes a critical race condition in the Wintun driver that causes ring buffer overruns Message-ID: <20260219193255.14334-1-katz.oded@gmail.com> ** Description ** This PR fixes a critical race condition in the Wintun driver that causes ring buffer overruns when multiple UDP senders operate in parallel. The issue occurred because multiple threads could read the same Ring->Head value without synchronization, leading to concurrent modifications that corrupted the ring buffer and resulted in ERROR_INVALID_DATA errors. ** Changes ** Extended the critical section in TunSendNetBufferLists by moving spinlock acquisition before reading Ring->Head, ensuring atomic read-modify-write operations on the ring buffer state Fixed the lock release timing in TunReturnNetBufferLists to occur after updating Ring->Head, ensuring consistency between the active NBL list and ring buffer head pointer ** History ** the issue was reported to wireguard ``` We were trying to integrate `wintun` into our product and while testing we found an issue with upload of high UDP throughput on multiple sockets. initially we thought it may be related to our integration. but we managed to find the same issue in your example code.we tried to do some debugging on the example, but it seems like the corruption is on the driver side. the way to reproduce this issue- run the example - run the `send_udp.py` (the attached python script) on 2 different command terminals - `send_udp.py 10.6.7.8 5201 1450` - `send_udp.py 10.6.7.8 5201 1400`after some time the `WintunReceivePacket` returns NULL and `GetLastError()` return 13 (`ERROR_INVALID_DATA`) many thanks, ``` a fix was provided by wireguard with [this commit](https://git.zx2c4.com/wintun/commit/driver/wintun.c?id=8814f660310c30a9297fc640c844c4ab6f27e5d7), but it didn't solve the issue. odedkatz (1): in order to prevent buffer overrun (which was observed while sending multiple high throughput UDP streams from different threads) I move the driver spinlock to protect Ring buffer Head. driver/wintun.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) -- 2.43.0 From katz.oded at gmail.com Thu Feb 19 19:32:55 2026 From: katz.oded at gmail.com (odedkatz) Date: Thu, 19 Feb 2026 11:32:55 -0800 Subject: [PATCH 1/1] in order to prevent buffer overrun (which was observed while sending multiple high throughput UDP streams from different threads) I move the driver spinlock to protect Ring buffer Head. In-Reply-To: <20260219193255.14334-1-katz.oded@gmail.com> References: <20260219193255.14334-1-katz.oded@gmail.com> Message-ID: <20260219193255.14334-2-katz.oded@gmail.com> I observed that the Ring->Head was taken and manipulated later on with just a `ReadULongAcquire` which isn't OK when 2 are trying to manipulate it later on based on the same received value. --- driver/wintun.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/driver/wintun.c b/driver/wintun.c index d1f3b9f..65cd97e 100644 --- a/driver/wintun.c +++ b/driver/wintun.c @@ -284,13 +284,14 @@ TunSendNetBufferLists( TUN_RING *Ring = Ctx->Device.Send.Ring; ULONG RingCapacity = Ctx->Device.Send.Capacity; + KLOCK_QUEUE_HANDLE LockHandle; + KeAcquireInStackQueuedSpinLock(&Ctx->Device.Send.Lock, &LockHandle); /* Allocate space for packets in the ring. */ ULONG RingHead = ReadULongAcquire(&Ring->Head); - if (Status = NDIS_STATUS_ADAPTER_NOT_READY, RingHead >= RingCapacity) + if (Status = NDIS_STATUS_ADAPTER_NOT_READY, RingHead >= RingCapacity) { + KeReleaseInStackQueuedSpinLock(&LockHandle); goto skipNbl; - - KLOCK_QUEUE_HANDLE LockHandle; - KeAcquireInStackQueuedSpinLock(&Ctx->Device.Send.Lock, &LockHandle); + } ULONG RingTail = Ctx->Device.Send.RingTail; ASSERT(RingTail < RingCapacity); @@ -419,8 +420,8 @@ TunReturnNetBufferLists(NDIS_HANDLE MiniportAdapterContext, PNET_BUFFER_LIST Net Ctx->Device.Receive.ActiveNbls.Head = NET_BUFFER_LIST_NEXT_NBL_EX(CompletedNbl); if (!Ctx->Device.Receive.ActiveNbls.Head) KeSetEvent(&Ctx->Device.Receive.ActiveNbls.Empty, IO_NO_INCREMENT, FALSE); - KeReleaseInStackQueuedSpinLock(&LockHandle); WriteULongRelease(&Ring->Head, TunNblGetOffset(CompletedNbl)); + KeReleaseInStackQueuedSpinLock(&LockHandle); const MDL *TargetMdl = Ctx->Device.Receive.Mdl; for (MDL *Mdl = NET_BUFFER_FIRST_MDL(NET_BUFFER_LIST_FIRST_NB(CompletedNbl)); Mdl; Mdl = Mdl->Next) { -- 2.43.0 From simon.rozman at amebis.si Fri Feb 20 07:28:22 2026 From: simon.rozman at amebis.si (Simon Rozman) Date: Fri, 20 Feb 2026 08:28:22 +0100 Subject: [PATCH 1/1] in order to prevent buffer overrun (which was observed while sending multiple high throughput UDP streams from different threads) I move the driver spinlock to protect Ring buffer Head. In-Reply-To: <20260219193255.14334-2-katz.oded@gmail.com> References: <20260219193255.14334-1-katz.oded@gmail.com> <20260219193255.14334-2-katz.oded@gmail.com> Message-ID: <8e797830-9851-47f3-8e10-4126e295b4b9@amebis.si> Hi, Oded! First and foremost, thank you very much for taking time to look into this and troubleshoot it. It was believed, that ReadULongAcquire() and WriteULongRelease() alone provide atomic manipulation with Ring->Head on all modern platforms. Hence, these calls were made outside the spinlock, to squeeze an extra micrometer of performance. I could not directly apply your patch to the wintun repo, since it does not follow our code style, commit message conventions and is not Signed-off-by you. However, it would have been a terrible waste of your research if your contribution wouldn't get into wintun, so I reworked your PR and applied it here: https://git.zx2c4.com/wintun/commit/?id=607c181ea9fa0036d23598038e6019ad54db5ce4 Please, stay tuned for an official WHQL-signed release. Lep pozdrav | Best regards, Simon Rozman Amebis, d. o. o., Kamnik On 19. 2. 2026 20.32, odedkatz wrote: > I observed that the Ring->Head was taken and manipulated later on with just a `ReadULongAcquire` which isn't OK when 2 are trying to manipulate it later on based on the same received value. > --- > driver/wintun.c | 11 ++++++----- > 1 file changed, 6 insertions(+), 5 deletions(-) > > diff --git a/driver/wintun.c b/driver/wintun.c > index d1f3b9f..65cd97e 100644 > --- a/driver/wintun.c > +++ b/driver/wintun.c > @@ -284,13 +284,14 @@ TunSendNetBufferLists( > TUN_RING *Ring = Ctx->Device.Send.Ring; > ULONG RingCapacity = Ctx->Device.Send.Capacity; > > + KLOCK_QUEUE_HANDLE LockHandle; > + KeAcquireInStackQueuedSpinLock(&Ctx->Device.Send.Lock, &LockHandle); > /* Allocate space for packets in the ring. */ > ULONG RingHead = ReadULongAcquire(&Ring->Head); > - if (Status = NDIS_STATUS_ADAPTER_NOT_READY, RingHead >= RingCapacity) > + if (Status = NDIS_STATUS_ADAPTER_NOT_READY, RingHead >= RingCapacity) { > + KeReleaseInStackQueuedSpinLock(&LockHandle); > goto skipNbl; > - > - KLOCK_QUEUE_HANDLE LockHandle; > - KeAcquireInStackQueuedSpinLock(&Ctx->Device.Send.Lock, &LockHandle); > + } > > ULONG RingTail = Ctx->Device.Send.RingTail; > ASSERT(RingTail < RingCapacity); > @@ -419,8 +420,8 @@ TunReturnNetBufferLists(NDIS_HANDLE MiniportAdapterContext, PNET_BUFFER_LIST Net > Ctx->Device.Receive.ActiveNbls.Head = NET_BUFFER_LIST_NEXT_NBL_EX(CompletedNbl); > if (!Ctx->Device.Receive.ActiveNbls.Head) > KeSetEvent(&Ctx->Device.Receive.ActiveNbls.Empty, IO_NO_INCREMENT, FALSE); > - KeReleaseInStackQueuedSpinLock(&LockHandle); > WriteULongRelease(&Ring->Head, TunNblGetOffset(CompletedNbl)); > + KeReleaseInStackQueuedSpinLock(&LockHandle); > const MDL *TargetMdl = Ctx->Device.Receive.Mdl; > for (MDL *Mdl = NET_BUFFER_FIRST_MDL(NET_BUFFER_LIST_FIRST_NB(CompletedNbl)); Mdl; Mdl = Mdl->Next) > { From katz.oded at gmail.com Fri Feb 20 16:55:15 2026 From: katz.oded at gmail.com (Oded Katz) Date: Fri, 20 Feb 2026 08:55:15 -0800 Subject: [PATCH 1/1] in order to prevent buffer overrun (which was observed while sending multiple high throughput UDP streams from different threads) I move the driver spinlock to protect Ring buffer Head. In-Reply-To: <8e797830-9851-47f3-8e10-4126e295b4b9@amebis.si> References: <20260219193255.14334-1-katz.oded@gmail.com> <20260219193255.14334-2-katz.oded@gmail.com> <8e797830-9851-47f3-8e10-4126e295b4b9@amebis.si> Message-ID: Hi Simon, Thanks for the update. FYI: the ReadULongAcquire() and WriteULongRelease() themself are good enough for getting and updating an atomic operation. however, after on thread updates the head, the second thread can't stay with the same atomic read value of the Head. - so assuming 2 thread read the Head on the same time so the 2 threads has same head. - now 1st thread takes the spin lock and updates the head - 2nd thread is pending the job until the spinlock is released and then it doing the job, but with the non-updated Head value - so it will overrun the previous thread data and mess the ringbuffer again thanks for providing the next release Regards, Oded On Thu, Feb 19, 2026 at 11:28?PM Simon Rozman wrote: > > Hi, Oded! > > First and foremost, thank you very much for taking time to look into > this and troubleshoot it. > > It was believed, that ReadULongAcquire() and WriteULongRelease() alone > provide atomic manipulation with Ring->Head on all modern platforms. > Hence, these calls were made outside the spinlock, to squeeze an extra > micrometer of performance. > > I could not directly apply your patch to the wintun repo, since it does > not follow our code style, commit message conventions and is not > Signed-off-by you. > > However, it would have been a terrible waste of your research if your > contribution wouldn't get into wintun, so I reworked your PR and applied > it here: > https://git.zx2c4.com/wintun/commit/?id=607c181ea9fa0036d23598038e6019ad54db5ce4 > > Please, stay tuned for an official WHQL-signed release. > > Lep pozdrav | Best regards, > Simon Rozman > Amebis, d. o. o., Kamnik > > On 19. 2. 2026 20.32, odedkatz wrote: > > I observed that the Ring->Head was taken and manipulated later on with just a `ReadULongAcquire` which isn't OK when 2 are trying to manipulate it later on based on the same received value. > > --- > > driver/wintun.c | 11 ++++++----- > > 1 file changed, 6 insertions(+), 5 deletions(-) > > > > diff --git a/driver/wintun.c b/driver/wintun.c > > index d1f3b9f..65cd97e 100644 > > --- a/driver/wintun.c > > +++ b/driver/wintun.c > > @@ -284,13 +284,14 @@ TunSendNetBufferLists( > > TUN_RING *Ring = Ctx->Device.Send.Ring; > > ULONG RingCapacity = Ctx->Device.Send.Capacity; > > > > + KLOCK_QUEUE_HANDLE LockHandle; > > + KeAcquireInStackQueuedSpinLock(&Ctx->Device.Send.Lock, &LockHandle); > > /* Allocate space for packets in the ring. */ > > ULONG RingHead = ReadULongAcquire(&Ring->Head); > > - if (Status = NDIS_STATUS_ADAPTER_NOT_READY, RingHead >= RingCapacity) > > + if (Status = NDIS_STATUS_ADAPTER_NOT_READY, RingHead >= RingCapacity) { > > + KeReleaseInStackQueuedSpinLock(&LockHandle); > > goto skipNbl; > > - > > - KLOCK_QUEUE_HANDLE LockHandle; > > - KeAcquireInStackQueuedSpinLock(&Ctx->Device.Send.Lock, &LockHandle); > > + } > > > > ULONG RingTail = Ctx->Device.Send.RingTail; > > ASSERT(RingTail < RingCapacity); > > @@ -419,8 +420,8 @@ TunReturnNetBufferLists(NDIS_HANDLE MiniportAdapterContext, PNET_BUFFER_LIST Net > > Ctx->Device.Receive.ActiveNbls.Head = NET_BUFFER_LIST_NEXT_NBL_EX(CompletedNbl); > > if (!Ctx->Device.Receive.ActiveNbls.Head) > > KeSetEvent(&Ctx->Device.Receive.ActiveNbls.Empty, IO_NO_INCREMENT, FALSE); > > - KeReleaseInStackQueuedSpinLock(&LockHandle); > > WriteULongRelease(&Ring->Head, TunNblGetOffset(CompletedNbl)); > > + KeReleaseInStackQueuedSpinLock(&LockHandle); > > const MDL *TargetMdl = Ctx->Device.Receive.Mdl; > > for (MDL *Mdl = NET_BUFFER_FIRST_MDL(NET_BUFFER_LIST_FIRST_NB(CompletedNbl)); Mdl; Mdl = Mdl->Next) > > { > From Jason at zx2c4.com Mon Feb 23 22:29:23 2026 From: Jason at zx2c4.com (Jason A. Donenfeld) Date: Mon, 23 Feb 2026 23:29:23 +0100 Subject: [ANNOUNCE] wireguard-tools v1.0.20260223 released Message-ID: <9356acf55652c651959056db4def95f0@thinkpad.zx2c4.com> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 Hello, A new version, v1.0.20260223, of wireguard-tools has been tagged in the git repository, containing various required userspace utilities, such as the wg(8) and wg-quick(8) commands and documentation. == Changes == * wg-quick: linux: use smallest mtu, not largest The minimum endpoint MTU selection should now actually work. * wg-quick: pass on # comments to {Pre,Post}{Up,Down} This handles the case of a literal # being used in a command. * wg-quick: linux: deal with resolvconf migration more gracefully This fixes an issue when upgrading Ubuntu boxes. * wg-quick: use addconf instead of setconf This will prevent wiping out changes made in PreUp. * wg-quick: linux: do not unnecessarily set sysctl Improves docker compatibility. * wg-quick at .service: add deps on wg-quick.target * config: preserve const correctness Squelches a warning on recent gcc. * syncconf: account for psks removed from config file * syncconf: account for persistent keepalive removed from config file PersistentKeepalive and PresharedKey will be removed if they're not found in the config file during a syncconf operation. This release contains commits from: Jason A. Donenfeld, Robyn Kosching, and Doug Freed. As always, the source is available at https://git.zx2c4.com/wireguard-tools/ and information about the project is available at https://www.wireguard.com/ . This release is available in compressed tarball form here: https://git.zx2c4.com/wireguard-tools/snapshot/wireguard-tools-1.0.20260223.tar.xz SHA2-256: af459827b80bfd31b83b08077f4b5843acb7d18ad9a33a2ef532d3090f291fbf A PGP signature of that file decompressed is available here: https://git.zx2c4.com/wireguard-tools/snapshot/wireguard-tools-1.0.20260223.tar.asc Signing key: AB9942E6D4A4CFC3412620A749FC7012A5DE03AE Remember to unxz the tarball before verifying the signature. If you're a package maintainer, please bump your package version. If you're a user, the WireGuard team welcomes any and all feedback on this latest version. Finally, WireGuard development thrives on donations. By popular demand, we have a webpage for this: https://www.wireguard.com/donations/ Thank you, Jason Donenfeld -----BEGIN PGP SIGNATURE----- iQJgBAEBCABKFiEEq5lC5tSkz8NBJiCnSfxwEqXeA64FAmmc1LYbFIAAAAAABAAO bWFudTIsMi41KzEuMTIsMiwyEBxqYXNvbkB6eDJjNC5jb20ACgkQSfxwEqXeA670 0RAAnGXdDN58CNN7enbl03NLSAE+rtbjy+YbEyXKjQCEocLseB+9+PHrqpkRXERJ fA/ysLmlE8ZhZybSjMB25aF32mvYoVwqQbQ6nCfdDR1vPF7wXN184TS4+ZjX4pxT lu1QQjsJR3DCfV64srqa3a8Z88g/ZYrNE9O/CJn4iL7DHiIcMF2V5s0yRWlRq/Sh YPSeyxoA4x68jH52b0ppprMW8EB9WfXWy9x+OOS0/2DHmVMdiL5n83IKbG2+MCgQ dDvPMNYV6N/JR+GPOHVFlnL34/Jqxw6iyh1IjbJ5MfNz0gqjopruXN0kRI6Sf3bE y4YyJPeZD20l0K4D6Q3Mw2Ar1ryQbwOCrN69WXwBbndxjmoMZ9JLEdSsOlNBwCIJ aqOp9/rP6QALB7gRV7TicKu55t8554FcXzFAkfaTwnorQRnaWWDpsXJubCRLWTaF vcVJ9WIbVuzPYjPituRUeYuZQ10DwzLzDzZoBF5aSlCMHwsUZ8ZzAJYySBFindTd ftSA6mcx47Yln2EYRHARjHV91ZARVDdL4Nd+yVsFNRkVvTKldZSljblLbGwF8lJU ygxEjwsMMB6DvxMd4I4/Wu/MHQ/h3ETOtc2qPob3bt/vPbpkf5k/DkBbaW3Z9bjk 3m9gtspIuLQEMX3sQq3BxpeJBiTNmYVc913PxGvsyUWzLnM= =v2Q+ -----END PGP SIGNATURE----- From list at eworm.de Tue Feb 24 10:52:54 2026 From: list at eworm.de (Christian Hesse) Date: Tue, 24 Feb 2026 11:52:54 +0100 Subject: Arch Linux - out of date?! In-Reply-To: <20260210143016.0144acf1@leda.eworm.net> References: <20260210143016.0144acf1@leda.eworm.net> Message-ID: <20260224115254.761df5a9@leda.eworm.net> Christian Hesse on Tue, 2026/02/10 14:30: > Hello everybody, > > for some time already I am annoyed by mails clogging my input regarding > wireguard-tools for Arch Linux being out of date. Obviously this is not > true, I built the package the day of release. [0] > > Now found the install page mentioning the package being out-of date... [1] > What goes wrong and how to fix that? > > [0] https://archlinux.org/packages/extra/x86_64/wireguard-tools/ > [1] https://www.wireguard.com/install/#arch-module-tools Ping... I would like to see this resolved. Alternatively I will set up my mail server to forward these mails to you personally, Jason. Thanks! -- main(a){char*c=/* Schoene Gruesse */"B?IJj;MEH" "CX:;",b;for(a/* Best regards my address: */=0;b=c[a++];) putchar(b-1/(/* Chris cc -ox -xc - && ./x */b/42*2-3)*42);} -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 488 bytes Desc: OpenPGP digital signature URL: From Jason at zx2c4.com Tue Feb 24 10:57:39 2026 From: Jason at zx2c4.com (Jason A. Donenfeld) Date: Tue, 24 Feb 2026 11:57:39 +0100 Subject: Arch Linux - out of date?! In-Reply-To: <20260224115254.761df5a9@leda.eworm.net> References: <20260210143016.0144acf1@leda.eworm.net> <20260224115254.761df5a9@leda.eworm.net> Message-ID: On Tue, Feb 24, 2026 at 11:53?AM Christian Hesse wrote: > > Christian Hesse on Tue, 2026/02/10 14:30: > > Hello everybody, > > > > for some time already I am annoyed by mails clogging my input regarding > > wireguard-tools for Arch Linux being out of date. Obviously this is not > > true, I built the package the day of release. [0] > > > > Now found the install page mentioning the package being out-of date... [1] > > What goes wrong and how to fix that? > > > > [0] https://archlinux.org/packages/extra/x86_64/wireguard-tools/ > > [1] https://www.wireguard.com/install/#arch-module-tools > > Ping... I would like to see this resolved. > > Alternatively I will set up my mail server to forward these mails to you > personally, Jason. Hehe. In the midst of a big infrastructure refresh (as perhaps you've noticed), so this is certainly in the queue there. Sorry about this. Jason From list at eworm.de Tue Feb 24 12:07:51 2026 From: list at eworm.de (Christian Hesse) Date: Tue, 24 Feb 2026 13:07:51 +0100 Subject: Arch Linux - out of date?! In-Reply-To: References: <20260210143016.0144acf1@leda.eworm.net> <20260224115254.761df5a9@leda.eworm.net> Message-ID: <20260224130751.1faee59a@leda.eworm.net> "Jason A. Donenfeld" on Tue, 2026/02/24 11:57: > On Tue, Feb 24, 2026 at 11:53?AM Christian Hesse wrote: > > > > Christian Hesse on Tue, 2026/02/10 14:30: > > > Hello everybody, > > > > > > for some time already I am annoyed by mails clogging my input regarding > > > wireguard-tools for Arch Linux being out of date. Obviously this is not > > > true, I built the package the day of release. [0] > > > > > > Now found the install page mentioning the package being out-of date... > > > [1] What goes wrong and how to fix that? > > > > > > [0] https://archlinux.org/packages/extra/x86_64/wireguard-tools/ > > > [1] https://www.wireguard.com/install/#arch-module-tools > > > > Ping... I would like to see this resolved. > > > > Alternatively I will set up my mail server to forward these mails to you > > personally, Jason. > > Hehe. > > In the midst of a big infrastructure refresh (as perhaps you've > noticed), so this is certainly in the queue there. Sorry about this. Ok, will wait patiently then. Just wanted to make sure this is not lost. :) Is the code available in git anywhere? I could have a look myself then. -- main(a){char*c=/* Schoene Gruesse */"B?IJj;MEH" "CX:;",b;for(a/* Best regards my address: */=0;b=c[a++];) putchar(b-1/(/* Chris cc -ox -xc - && ./x */b/42*2-3)*42);} -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 488 bytes Desc: OpenPGP digital signature URL: From Jason at zx2c4.com Tue Feb 24 12:27:14 2026 From: Jason at zx2c4.com (Jason A. Donenfeld) Date: Tue, 24 Feb 2026 13:27:14 +0100 Subject: Arch Linux - out of date?! In-Reply-To: <20260224130751.1faee59a@leda.eworm.net> References: <20260210143016.0144acf1@leda.eworm.net> <20260224115254.761df5a9@leda.eworm.net> <20260224130751.1faee59a@leda.eworm.net> Message-ID: On Tue, Feb 24, 2026 at 1:07?PM Christian Hesse wrote: > > "Jason A. Donenfeld" on Tue, 2026/02/24 11:57: > > On Tue, Feb 24, 2026 at 11:53?AM Christian Hesse wrote: > > > > > > Christian Hesse on Tue, 2026/02/10 14:30: > > > > Hello everybody, > > > > > > > > for some time already I am annoyed by mails clogging my input regarding > > > > wireguard-tools for Arch Linux being out of date. Obviously this is not > > > > true, I built the package the day of release. [0] > > > > > > > > Now found the install page mentioning the package being out-of date... > > > > [1] What goes wrong and how to fix that? > > > > > > > > [0] https://archlinux.org/packages/extra/x86_64/wireguard-tools/ > > > > [1] https://www.wireguard.com/install/#arch-module-tools > > > > > > Ping... I would like to see this resolved. > > > > > > Alternatively I will set up my mail server to forward these mails to you > > > personally, Jason. > > > > Hehe. > > > > In the midst of a big infrastructure refresh (as perhaps you've > > noticed), so this is certainly in the queue there. Sorry about this. > > Ok, will wait patiently then. Just wanted to make sure this is not lost. :) > > Is the code available in git anywhere? I could have a look myself then. I sorted out the arch and alpine ones, but there are still a bunch of others that are out of date or broken. For alpine I had to work around anubis (by using a curl useragent). The code isn't online, but maybe it should be. It's just a bash script that fetches webpages and executes a regex. The arch ones are: check \ tools \ "Arch" \ "mail at eworm.de" \ "https://gitlab.archlinux.org/archlinux/packaging/packages/wireguard-tools/-/raw/main/PKGBUILD?ref_type=heads" \ 'pkgver=([0-9.]+)' & check \ linuxcompat \ "Arch" \ "mail at eworm.de" \ "https://aur.archlinux.org/cgit/aur.git/plain/PKGBUILD?h=wireguard-dkms" \ 'pkgver=([0-9.]+)' & check() { local type="$1" local expected="version_$1" expected="${!expected}" local name="$2" local email="$3" local text="$(curl -L -A "curl/8.18.0 ($RANDOM$RANDOM$RANDOM$RANDOM)" -s "$4")" [[ $text =~ $5 ]] && local version="${BASH_REMATCH[1]}" || local version="unknown" [[ $version == "$expected" ]] && local uptodate="true" || local uptodate="false" From rubonmtz at gmail.com Mon Feb 16 18:20:27 2026 From: rubonmtz at gmail.com (M Rubon) Date: Mon, 16 Feb 2026 13:20:27 -0500 Subject: Weirdness on timing of HS request packets when keepalive==5 Message-ID: I am looking at the timing interval between HS request packets during the 90s attempt period. I see different interval timing depending on the (basically unrelated) persistent-keepalive value. I suspect the timer for persistent-keepalive==5 is interfering with the timer for "try HS request again". It is not a massive difference, but it does not match the expected 5+jitter seconds suggested in the documentation, and has interesting consequences. In one case, two of my peers were each sending HS attempts to the other at the same time (almost no randomness), and those HS requests were crossing in the night and being repeatedly ignored because the peer had also sent a HS request (tcpdump available on request). It took a while before they finally completed a full HS. I have a useful workaround to avoid issues for my use case, but wanted to highlight the possibility of keepalive timers at 5s lightly interfering with the "try HS again" timers. M. Environment: OpenWRT v25.12 kernel 6.12 (same issue on kernel 5.4) Trying to connect to a (non-existent) peer over loopback port 5656 Monitoring: tcpdump -nnttt -i lo udp port 5656 When keepalive is 13, the interval between HS packets is 5.x seconds and jitter is decently random 00:00:05.119975 IP6 ::1.50737 > ::1.5656: UDP, length 148 00:00:05.759944 IP6 ::1.50737 > ::1.5656: UDP, length 148 00:00:05.760015 IP6 ::1.50737 > ::1.5656: UDP, length 148 00:00:05.760014 IP6 ::1.50737 > ::1.5656: UDP, length 148 00:00:05.120015 IP6 ::1.50737 > ::1.5656: UDP, length 148 00:00:05.759989 IP6 ::1.50737 > ::1.5656: UDP, length 148 00:00:05.760028 IP6 ::1.50737 > ::1.5656: UDP, length 148 00:00:05.760008 IP6 ::1.50737 > ::1.5656: UDP, length 148 00:00:05.119940 IP6 ::1.50737 > ::1.5656: UDP, length 148 00:00:05.120033 IP6 ::1.50737 > ::1.5656: UDP, length 148 00:00:05.039978 IP6 ::1.50737 > ::1.5656: UDP, length 148 00:00:05.200242 IP6 ::1.50737 > ::1.5656: UDP, length 148 00:00:05.759820 IP6 ::1.50737 > ::1.5656: UDP, length 148 When keepalive is 5, the interval between HS packets is 5.0x seconds and jitter is clamped to under 10ms 00:00:05.039878 IP6 ::1.50737 > ::1.5656: UDP, length 148 00:00:05.040018 IP6 ::1.50737 > ::1.5656: UDP, length 148 00:00:05.039979 IP6 ::1.50737 > ::1.5656: UDP, length 148 00:00:05.040000 IP6 ::1.50737 > ::1.5656: UDP, length 148 00:00:05.040104 IP6 ::1.50737 > ::1.5656: UDP, length 148 00:00:05.039900 IP6 ::1.50737 > ::1.5656: UDP, length 148 00:00:05.040112 IP6 ::1.50737 > ::1.5656: UDP, length 148 00:00:05.039838 IP6 ::1.50737 > ::1.5656: UDP, length 148 From katz.oded at gmail.com Tue Feb 24 23:42:45 2026 From: katz.oded at gmail.com (odedkatz) Date: Tue, 24 Feb 2026 15:42:45 -0800 Subject: [PATCH 0/1] wintun driver get stalled for few sec until another packet is being sent -- approach 1 Message-ID: <20260224234246.16021-1-katz.oded@gmail.com> ## changes: - I observed a code [which can lead to a stall condition in the wintun driver](https://github.com/Twingate/wintun/blob/6bfc34a60aa944149fdc7e9cddb191e9a8b6ec1a/driver/twintun.c#L487-L488) - I didn't want to change the driver code as, I was not sure if it will create a busy loop on kernel - so instead I tackle this on the client-part of wintun # issue description: ## Reproducing issue - run iperf client on Client machine with the command `iperf3 -c 127.0.0.1.us.east.direct.vpn -t 300 -b0 -P1` - once in a while we see intervals when no throughput goes to 0 and it takes about 4-5 sec to get out of this situation. odedkatz (1): remove the condition on possibly stale variable (Session->Descriptor.Receive.Ring->Alertable) for Setting TailMoved event api/session.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) -- 2.43.0 From katz.oded at gmail.com Tue Feb 24 23:42:46 2026 From: katz.oded at gmail.com (odedkatz) Date: Tue, 24 Feb 2026 15:42:46 -0800 Subject: [PATCH 1/1] remove the condition on possibly stale variable (Session->Descriptor.Receive.Ring->Alertable) for Setting TailMoved event In-Reply-To: <20260224234246.16021-1-katz.oded@gmail.com> References: <20260224234246.16021-1-katz.oded@gmail.com> Message-ID: <20260224234246.16021-2-katz.oded@gmail.com> otherwise wintun driver just holds on the event until something wakes it up (see here)[https://github.com/Twingate/wintun/blob/6bfc34a60aa944149fdc7e9cddb191e9a8b6ec1a/driver/twintun.c#L487-L488] --- api/session.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/api/session.c b/api/session.c index ab96c64..dcaeb25 100644 --- a/api/session.c +++ b/api/session.c @@ -302,8 +302,7 @@ WintunSendPacket(TUN_SESSION *Session, const BYTE *Packet) if (Session->Descriptor.Receive.Ring->Tail != Session->Receive.TailRelease) { WriteULongRelease(&Session->Descriptor.Receive.Ring->Tail, Session->Receive.TailRelease); - if (ReadAcquire(&Session->Descriptor.Receive.Ring->Alertable)) - SetEvent(Session->Descriptor.Receive.TailMoved); + SetEvent(Session->Descriptor.Receive.TailMoved); } LeaveCriticalSection(&Session->Receive.Lock); } -- 2.43.0 From katz.oded at gmail.com Tue Feb 24 23:47:16 2026 From: katz.oded at gmail.com (odedkatz) Date: Tue, 24 Feb 2026 15:47:16 -0800 Subject: [PATCH 0/1] wintun driver get stalled for few sec until another packet is being sent -- approach 2 Message-ID: <20260224234717.16883-1-katz.oded@gmail.com> ## Problem High-speed TCP uploads stall for 4-5 seconds when the sender and receiver are close (~1ms RTT). The root cause is a missed-wakeup race in the Receive ring's Alertable/Tail signaling protocol between the userspace API (WintunSendPacket) and the kernel0 consumer thread (TunProcessReceiveData). On x86-64, WriteRelease/ReadAcquire provide acquire-release semantics but do not emit MFENCE ? the only instruction that prevents store-load reordering (the one reordering x86 permits). Both cores can simultaneously observe stale values of the other's store, causing the userspace to skip SetEvent while the driver enters KeWaitForMultipleObjects indefinitely. The driver sleeps until a TCP retransmission (RTO ~1s + exponential backoff) coincidentally wins the race, producing the observed 4-5 second stalls. ## Fix Insert MemoryBarrier() between each store-load pair on both sides. This guarantees that at least one side always sees the other's store, eliminating the missed wakeup. The Alertable optimization (avoiding SetEvent syscalls when the driver is actively spinning) is fully preserved. Alexey Lapuka (1): Fix missed-wakeup race in ring buffer Alertable signaling api/session.c | 1 + driver/wintun.c | 1 + 2 files changed, 2 insertions(+) -- 2.43.0 From katz.oded at gmail.com Tue Feb 24 23:47:17 2026 From: katz.oded at gmail.com (odedkatz) Date: Tue, 24 Feb 2026 15:47:17 -0800 Subject: [PATCH 1/1] Fix missed-wakeup race in ring buffer Alertable signaling In-Reply-To: <20260224234717.16883-1-katz.oded@gmail.com> References: <20260224234717.16883-1-katz.oded@gmail.com> Message-ID: <20260224234717.16883-2-katz.oded@gmail.com> From: Alexey Lapuka 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. --- api/session.c | 1 + driver/wintun.c | 1 + 2 files changed, 2 insertions(+) diff --git a/api/session.c b/api/session.c index ab96c64..13d5bca 100644 --- a/api/session.c +++ b/api/session.c @@ -302,6 +302,7 @@ WintunSendPacket(TUN_SESSION *Session, const BYTE *Packet) if (Session->Descriptor.Receive.Ring->Tail != Session->Receive.TailRelease) { WriteULongRelease(&Session->Descriptor.Receive.Ring->Tail, Session->Receive.TailRelease); + MemoryBarrier(); if (ReadAcquire(&Session->Descriptor.Receive.Ring->Alertable)) SetEvent(Session->Descriptor.Receive.TailMoved); } 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) { -- 2.43.0 From list at eworm.de Wed Feb 25 11:28:02 2026 From: list at eworm.de (Christian Hesse) Date: Wed, 25 Feb 2026 12:28:02 +0100 Subject: Arch Linux - out of date?! In-Reply-To: References: <20260210143016.0144acf1@leda.eworm.net> <20260224115254.761df5a9@leda.eworm.net> <20260224130751.1faee59a@leda.eworm.net> Message-ID: <20260225122802.5e00abb4@leda.eworm.net> "Jason A. Donenfeld" on Tue, 2026/02/24 13:27: > I sorted out the arch and alpine ones, but there are still a bunch of > others that are out of date or broken. For alpine I had to work around > anubis (by using a curl useragent). Thanks a lot! -- main(a){char*c=/* Schoene Gruesse */"B?IJj;MEH" "CX:;",b;for(a/* Best regards my address: */=0;b=c[a++];) putchar(b-1/(/* Chris cc -ox -xc - && ./x */b/42*2-3)*42);} -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 488 bytes Desc: OpenPGP digital signature URL: From katz.oded at gmail.com Fri Feb 27 21:28:05 2026 From: katz.oded at gmail.com (Oded Katz) Date: Fri, 27 Feb 2026 13:28:05 -0800 Subject: [PATCH 1/1] in order to prevent buffer overrun (which was observed while sending multiple high throughput UDP streams from different threads) I move the driver spinlock to protect Ring buffer Head. In-Reply-To: References: <20260219193255.14334-1-katz.oded@gmail.com> <20260219193255.14334-2-katz.oded@gmail.com> <8e797830-9851-47f3-8e10-4126e295b4b9@amebis.si> Message-ID: Hi Simon, We have found another issue with the driver code. some race condition between "alertable" flag between driver and user-side. causing driver to stall until new packet wakes it up. We have seen some cases where it can be for periods of 5 sec. we already made the fix, and I sent 2 approaches for that fix. please let us know if you are planning to solve it in your repo? regards and thanks, Oded On Fri, Feb 20, 2026 at 8:55?AM Oded Katz wrote: > > Hi Simon, > > Thanks for the update. > FYI: the ReadULongAcquire() and WriteULongRelease() themself are good > enough for getting and updating an atomic operation. > however, after on thread updates the head, the second thread can't > stay with the same atomic read value of the Head. > - so assuming 2 thread read the Head on the same time so the 2 threads > has same head. > - now 1st thread takes the spin lock and updates the head > - 2nd thread is pending the job until the spinlock is released and > then it doing the job, but with the non-updated Head value > - so it will overrun the previous thread data and mess the ringbuffer > > > again thanks for providing the next release > Regards, > Oded > > On Thu, Feb 19, 2026 at 11:28?PM Simon Rozman wrote: > > > > Hi, Oded! > > > > First and foremost, thank you very much for taking time to look into > > this and troubleshoot it. > > > > It was believed, that ReadULongAcquire() and WriteULongRelease() alone > > provide atomic manipulation with Ring->Head on all modern platforms. > > Hence, these calls were made outside the spinlock, to squeeze an extra > > micrometer of performance. > > > > I could not directly apply your patch to the wintun repo, since it does > > not follow our code style, commit message conventions and is not > > Signed-off-by you. > > > > However, it would have been a terrible waste of your research if your > > contribution wouldn't get into wintun, so I reworked your PR and applied > > it here: > > https://git.zx2c4.com/wintun/commit/?id=607c181ea9fa0036d23598038e6019ad54db5ce4 > > > > Please, stay tuned for an official WHQL-signed release. > > > > Lep pozdrav | Best regards, > > Simon Rozman > > Amebis, d. o. o., Kamnik > > > > On 19. 2. 2026 20.32, odedkatz wrote: > > > I observed that the Ring->Head was taken and manipulated later on with just a `ReadULongAcquire` which isn't OK when 2 are trying to manipulate it later on based on the same received value. > > > --- > > > driver/wintun.c | 11 ++++++----- > > > 1 file changed, 6 insertions(+), 5 deletions(-) > > > > > > diff --git a/driver/wintun.c b/driver/wintun.c > > > index d1f3b9f..65cd97e 100644 > > > --- a/driver/wintun.c > > > +++ b/driver/wintun.c > > > @@ -284,13 +284,14 @@ TunSendNetBufferLists( > > > TUN_RING *Ring = Ctx->Device.Send.Ring; > > > ULONG RingCapacity = Ctx->Device.Send.Capacity; > > > > > > + KLOCK_QUEUE_HANDLE LockHandle; > > > + KeAcquireInStackQueuedSpinLock(&Ctx->Device.Send.Lock, &LockHandle); > > > /* Allocate space for packets in the ring. */ > > > ULONG RingHead = ReadULongAcquire(&Ring->Head); > > > - if (Status = NDIS_STATUS_ADAPTER_NOT_READY, RingHead >= RingCapacity) > > > + if (Status = NDIS_STATUS_ADAPTER_NOT_READY, RingHead >= RingCapacity) { > > > + KeReleaseInStackQueuedSpinLock(&LockHandle); > > > goto skipNbl; > > > - > > > - KLOCK_QUEUE_HANDLE LockHandle; > > > - KeAcquireInStackQueuedSpinLock(&Ctx->Device.Send.Lock, &LockHandle); > > > + } > > > > > > ULONG RingTail = Ctx->Device.Send.RingTail; > > > ASSERT(RingTail < RingCapacity); > > > @@ -419,8 +420,8 @@ TunReturnNetBufferLists(NDIS_HANDLE MiniportAdapterContext, PNET_BUFFER_LIST Net > > > Ctx->Device.Receive.ActiveNbls.Head = NET_BUFFER_LIST_NEXT_NBL_EX(CompletedNbl); > > > if (!Ctx->Device.Receive.ActiveNbls.Head) > > > KeSetEvent(&Ctx->Device.Receive.ActiveNbls.Empty, IO_NO_INCREMENT, FALSE); > > > - KeReleaseInStackQueuedSpinLock(&LockHandle); > > > WriteULongRelease(&Ring->Head, TunNblGetOffset(CompletedNbl)); > > > + KeReleaseInStackQueuedSpinLock(&LockHandle); > > > const MDL *TargetMdl = Ctx->Device.Receive.Mdl; > > > for (MDL *Mdl = NET_BUFFER_FIRST_MDL(NET_BUFFER_LIST_FIRST_NB(CompletedNbl)); Mdl; Mdl = Mdl->Next) > > > { > > From simon.rozman at amebis.si Fri Feb 27 22:03:24 2026 From: simon.rozman at amebis.si (Simon Rozman) Date: Fri, 27 Feb 2026 23:03:24 +0100 Subject: [PATCH 1/1] in order to prevent buffer overrun (which was observed while sending multiple high throughput UDP streams from different threads) I move the driver spinlock to protect Ring buffer Head. In-Reply-To: References: <20260219193255.14334-1-katz.oded@gmail.com> <20260219193255.14334-2-katz.oded@gmail.com> <8e797830-9851-47f3-8e10-4126e295b4b9@amebis.si> Message-ID: Yes, Oded. Your research is much appreciated. I have stare-reviewed it immediately, and it makes sense: by slightly extending the critical section a race condition should be fixed. Unfortunately, haven't had time to apply it to the master branch yet. Hopefully next week. Definitely before a release. Lep pozdrav | Best regards, Simon Rozman Amebis, d. o. o., Kamnik On 27.2.2026 22:28, Oded Katz wrote: > Hi Simon, > > We have found another issue with the driver code. > some race condition between "alertable" flag between driver and > user-side. causing driver to stall until new packet wakes it up. > We have seen some cases where it can be for periods of 5 sec. > > we already made the fix, and I sent 2 approaches for that fix. > please let us know if you are planning to solve it in your repo? > > regards and thanks, > Oded > > On Fri, Feb 20, 2026 at 8:55?AM Oded Katz wrote: >> >> Hi Simon, >> >> Thanks for the update. >> FYI: the ReadULongAcquire() and WriteULongRelease() themself are good >> enough for getting and updating an atomic operation. >> however, after on thread updates the head, the second thread can't >> stay with the same atomic read value of the Head. >> - so assuming 2 thread read the Head on the same time so the 2 threads >> has same head. >> - now 1st thread takes the spin lock and updates the head >> - 2nd thread is pending the job until the spinlock is released and >> then it doing the job, but with the non-updated Head value >> - so it will overrun the previous thread data and mess the ringbuffer >> >> >> again thanks for providing the next release >> Regards, >> Oded >> >> On Thu, Feb 19, 2026 at 11:28?PM Simon Rozman wrote: >>> >>> Hi, Oded! >>> >>> First and foremost, thank you very much for taking time to look into >>> this and troubleshoot it. >>> >>> It was believed, that ReadULongAcquire() and WriteULongRelease() alone >>> provide atomic manipulation with Ring->Head on all modern platforms. >>> Hence, these calls were made outside the spinlock, to squeeze an extra >>> micrometer of performance. >>> >>> I could not directly apply your patch to the wintun repo, since it does >>> not follow our code style, commit message conventions and is not >>> Signed-off-by you. >>> >>> However, it would have been a terrible waste of your research if your >>> contribution wouldn't get into wintun, so I reworked your PR and applied >>> it here: >>> https://git.zx2c4.com/wintun/commit/?id=607c181ea9fa0036d23598038e6019ad54db5ce4 >>> >>> Please, stay tuned for an official WHQL-signed release. >>> >>> Lep pozdrav | Best regards, >>> Simon Rozman >>> Amebis, d. o. o., Kamnik >>> >>> On 19. 2. 2026 20.32, odedkatz wrote: >>>> I observed that the Ring->Head was taken and manipulated later on with just a `ReadULongAcquire` which isn't OK when 2 are trying to manipulate it later on based on the same received value. >>>> --- >>>> driver/wintun.c | 11 ++++++----- >>>> 1 file changed, 6 insertions(+), 5 deletions(-) >>>> >>>> diff --git a/driver/wintun.c b/driver/wintun.c >>>> index d1f3b9f..65cd97e 100644 >>>> --- a/driver/wintun.c >>>> +++ b/driver/wintun.c >>>> @@ -284,13 +284,14 @@ TunSendNetBufferLists( >>>> TUN_RING *Ring = Ctx->Device.Send.Ring; >>>> ULONG RingCapacity = Ctx->Device.Send.Capacity; >>>> >>>> + KLOCK_QUEUE_HANDLE LockHandle; >>>> + KeAcquireInStackQueuedSpinLock(&Ctx->Device.Send.Lock, &LockHandle); >>>> /* Allocate space for packets in the ring. */ >>>> ULONG RingHead = ReadULongAcquire(&Ring->Head); >>>> - if (Status = NDIS_STATUS_ADAPTER_NOT_READY, RingHead >= RingCapacity) >>>> + if (Status = NDIS_STATUS_ADAPTER_NOT_READY, RingHead >= RingCapacity) { >>>> + KeReleaseInStackQueuedSpinLock(&LockHandle); >>>> goto skipNbl; >>>> - >>>> - KLOCK_QUEUE_HANDLE LockHandle; >>>> - KeAcquireInStackQueuedSpinLock(&Ctx->Device.Send.Lock, &LockHandle); >>>> + } >>>> >>>> ULONG RingTail = Ctx->Device.Send.RingTail; >>>> ASSERT(RingTail < RingCapacity); >>>> @@ -419,8 +420,8 @@ TunReturnNetBufferLists(NDIS_HANDLE MiniportAdapterContext, PNET_BUFFER_LIST Net >>>> Ctx->Device.Receive.ActiveNbls.Head = NET_BUFFER_LIST_NEXT_NBL_EX(CompletedNbl); >>>> if (!Ctx->Device.Receive.ActiveNbls.Head) >>>> KeSetEvent(&Ctx->Device.Receive.ActiveNbls.Empty, IO_NO_INCREMENT, FALSE); >>>> - KeReleaseInStackQueuedSpinLock(&LockHandle); >>>> WriteULongRelease(&Ring->Head, TunNblGetOffset(CompletedNbl)); >>>> + KeReleaseInStackQueuedSpinLock(&LockHandle); >>>> const MDL *TargetMdl = Ctx->Device.Receive.Mdl; >>>> for (MDL *Mdl = NET_BUFFER_FIRST_MDL(NET_BUFFER_LIST_FIRST_NB(CompletedNbl)); Mdl; Mdl = Mdl->Next) >>>> { >>> From katz.oded at gmail.com Sat Feb 28 01:12:32 2026 From: katz.oded at gmail.com (Oded Katz) Date: Fri, 27 Feb 2026 17:12:32 -0800 Subject: [PATCH 1/1] in order to prevent buffer overrun (which was observed while sending multiple high throughput UDP streams from different threads) I move the driver spinlock to protect Ring buffer Head. In-Reply-To: References: <20260219193255.14334-1-katz.oded@gmail.com> <20260219193255.14334-2-katz.oded@gmail.com> <8e797830-9851-47f3-8e10-4126e295b4b9@amebis.si> Message-ID: Thanks for the update. Have a wonderful weekend Oded On Fri, Feb 27, 2026 at 2:03?PM Simon Rozman wrote: > > Yes, Oded. Your research is much appreciated. I have stare-reviewed it > immediately, and it makes sense: by slightly extending the critical > section a race condition should be fixed. Unfortunately, haven't had > time to apply it to the master branch yet. Hopefully next week. > Definitely before a release. > > Lep pozdrav | Best regards, > Simon Rozman > Amebis, d. o. o., Kamnik > > On 27.2.2026 22:28, Oded Katz wrote: > > Hi Simon, > > > > We have found another issue with the driver code. > > some race condition between "alertable" flag between driver and > > user-side. causing driver to stall until new packet wakes it up. > > We have seen some cases where it can be for periods of 5 sec. > > > > we already made the fix, and I sent 2 approaches for that fix. > > please let us know if you are planning to solve it in your repo? > > > > regards and thanks, > > Oded > > > > On Fri, Feb 20, 2026 at 8:55?AM Oded Katz wrote: > >> > >> Hi Simon, > >> > >> Thanks for the update. > >> FYI: the ReadULongAcquire() and WriteULongRelease() themself are good > >> enough for getting and updating an atomic operation. > >> however, after on thread updates the head, the second thread can't > >> stay with the same atomic read value of the Head. > >> - so assuming 2 thread read the Head on the same time so the 2 threads > >> has same head. > >> - now 1st thread takes the spin lock and updates the head > >> - 2nd thread is pending the job until the spinlock is released and > >> then it doing the job, but with the non-updated Head value > >> - so it will overrun the previous thread data and mess the ringbuffer > >> > >> > >> again thanks for providing the next release > >> Regards, > >> Oded > >> > >> On Thu, Feb 19, 2026 at 11:28?PM Simon Rozman wrote: > >>> > >>> Hi, Oded! > >>> > >>> First and foremost, thank you very much for taking time to look into > >>> this and troubleshoot it. > >>> > >>> It was believed, that ReadULongAcquire() and WriteULongRelease() alone > >>> provide atomic manipulation with Ring->Head on all modern platforms. > >>> Hence, these calls were made outside the spinlock, to squeeze an extra > >>> micrometer of performance. > >>> > >>> I could not directly apply your patch to the wintun repo, since it does > >>> not follow our code style, commit message conventions and is not > >>> Signed-off-by you. > >>> > >>> However, it would have been a terrible waste of your research if your > >>> contribution wouldn't get into wintun, so I reworked your PR and applied > >>> it here: > >>> https://git.zx2c4.com/wintun/commit/?id=607c181ea9fa0036d23598038e6019ad54db5ce4 > >>> > >>> Please, stay tuned for an official WHQL-signed release. > >>> > >>> Lep pozdrav | Best regards, > >>> Simon Rozman > >>> Amebis, d. o. o., Kamnik > >>> > >>> On 19. 2. 2026 20.32, odedkatz wrote: > >>>> I observed that the Ring->Head was taken and manipulated later on with just a `ReadULongAcquire` which isn't OK when 2 are trying to manipulate it later on based on the same received value. > >>>> --- > >>>> driver/wintun.c | 11 ++++++----- > >>>> 1 file changed, 6 insertions(+), 5 deletions(-) > >>>> > >>>> diff --git a/driver/wintun.c b/driver/wintun.c > >>>> index d1f3b9f..65cd97e 100644 > >>>> --- a/driver/wintun.c > >>>> +++ b/driver/wintun.c > >>>> @@ -284,13 +284,14 @@ TunSendNetBufferLists( > >>>> TUN_RING *Ring = Ctx->Device.Send.Ring; > >>>> ULONG RingCapacity = Ctx->Device.Send.Capacity; > >>>> > >>>> + KLOCK_QUEUE_HANDLE LockHandle; > >>>> + KeAcquireInStackQueuedSpinLock(&Ctx->Device.Send.Lock, &LockHandle); > >>>> /* Allocate space for packets in the ring. */ > >>>> ULONG RingHead = ReadULongAcquire(&Ring->Head); > >>>> - if (Status = NDIS_STATUS_ADAPTER_NOT_READY, RingHead >= RingCapacity) > >>>> + if (Status = NDIS_STATUS_ADAPTER_NOT_READY, RingHead >= RingCapacity) { > >>>> + KeReleaseInStackQueuedSpinLock(&LockHandle); > >>>> goto skipNbl; > >>>> - > >>>> - KLOCK_QUEUE_HANDLE LockHandle; > >>>> - KeAcquireInStackQueuedSpinLock(&Ctx->Device.Send.Lock, &LockHandle); > >>>> + } > >>>> > >>>> ULONG RingTail = Ctx->Device.Send.RingTail; > >>>> ASSERT(RingTail < RingCapacity); > >>>> @@ -419,8 +420,8 @@ TunReturnNetBufferLists(NDIS_HANDLE MiniportAdapterContext, PNET_BUFFER_LIST Net > >>>> Ctx->Device.Receive.ActiveNbls.Head = NET_BUFFER_LIST_NEXT_NBL_EX(CompletedNbl); > >>>> if (!Ctx->Device.Receive.ActiveNbls.Head) > >>>> KeSetEvent(&Ctx->Device.Receive.ActiveNbls.Empty, IO_NO_INCREMENT, FALSE); > >>>> - KeReleaseInStackQueuedSpinLock(&LockHandle); > >>>> WriteULongRelease(&Ring->Head, TunNblGetOffset(CompletedNbl)); > >>>> + KeReleaseInStackQueuedSpinLock(&LockHandle); > >>>> const MDL *TargetMdl = Ctx->Device.Receive.Mdl; > >>>> for (MDL *Mdl = NET_BUFFER_FIRST_MDL(NET_BUFFER_LIST_FIRST_NB(CompletedNbl)); Mdl; Mdl = Mdl->Next) > >>>> { > >>> >