]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
dco-win: Ensure correct OVERLAPPED scope
authorLev Stipakov <lev@openvpn.net>
Wed, 2 Apr 2025 11:30:11 +0000 (13:30 +0200)
committerGert Doering <gert@greenie.muc.de>
Wed, 2 Apr 2025 14:27:27 +0000 (16:27 +0200)
This is a backport of the master commit

   f60a493 ("dco-win: Fix crash when cancelling pending operation")

Although I am unable to reproduce this issue on release branch,
the code is clearly wrong and has to be fixed.

The OVERLAPPED structure must remain valid for the entire duration of an
asynchronous operation. Previously, when a TCP connection was pending
inside the NEW_PEER call, the OVERLAPPED structure was defined as a
local variable within dco_p2p_new_peer().

When CancelIo() was called later from close_tun_handle(), the OVERLAPPED
structure was already out of scope, resulting in undefined behavior and
stack corruption.

This fix moves the OVERLAPPED structure to the tuntap struct, ensuring
it remains valid throughout the operation's lifetime.

Change-Id: I44a73f06c0672c1d288bf46e9424dc0dc2abe054
Signed-off-by: Lev Stipakov <lev@openvpn.net>
Acked-by: Gert Doering <gert@greenie.muc.de>
Message-Id: <20250402113016.14980-1-gert@greenie.muc.de>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg31316.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
src/openvpn/dco_win.c
src/openvpn/dco_win.h
src/openvpn/socket.c
src/openvpn/tun.h

index 3ec946ffb8673c97128d5e573e8ef690f68a8304..0b8f8319de1bd80ad20cdc21d83fc4fabe906e7e 100644 (file)
@@ -156,7 +156,8 @@ dco_connect_wait(HANDLE handle, OVERLAPPED *ov, int timeout, struct signal_info
 }
 
 void
-dco_create_socket(HANDLE handle, struct addrinfo *remoteaddr, bool bind_local,
+dco_create_socket(HANDLE handle, OVERLAPPED *ov,
+                  struct addrinfo *remoteaddr, bool bind_local,
                   struct addrinfo *bind, int timeout,
                   struct signal_info *sig_info)
 {
@@ -229,8 +230,8 @@ dco_create_socket(HANDLE handle, struct addrinfo *remoteaddr, bool bind_local,
         ASSERT(0);
     }
 
-    OVERLAPPED ov = { 0 };
-    if (!DeviceIoControl(handle, OVPN_IOCTL_NEW_PEER, &peer, sizeof(peer), NULL, 0, NULL, &ov))
+    CLEAR(*ov);
+    if (!DeviceIoControl(handle, OVPN_IOCTL_NEW_PEER, &peer, sizeof(peer), NULL, 0, NULL, ov))
     {
         DWORD err = GetLastError();
         if (err != ERROR_IO_PENDING)
@@ -239,7 +240,7 @@ dco_create_socket(HANDLE handle, struct addrinfo *remoteaddr, bool bind_local,
         }
         else
         {
-            dco_connect_wait(handle, &ov, timeout, sig_info);
+            dco_connect_wait(handle, ov, timeout, sig_info);
         }
     }
 }
index 48836299ad47d85270ba8a403916b54c869b84ed..dcf480ee8b08df618875e7d0dc103cc0a1cd58ca 100644 (file)
@@ -41,7 +41,8 @@ struct tuntap
 create_dco_handle(const char *devname, struct gc_arena *gc);
 
 void
-dco_create_socket(HANDLE handle, struct addrinfo *remoteaddr, bool bind_local,
+dco_create_socket(HANDLE handle, OVERLAPPED *ov,
+                  struct addrinfo *remoteaddr, bool bind_local,
                   struct addrinfo *bind, int timeout,
                   struct signal_info *sig_info);
 
index e07068813394eb28f4552cc2d13fd5b6ca6756d5..2eb2e747285087c5b5e281299b586158ba6494fb 100644 (file)
@@ -2148,7 +2148,7 @@ create_socket_dco_win(struct context *c, struct link_socket *sock,
         c->c1.tuntap = tt;
     }
 
-    dco_create_socket(c->c1.tuntap->hand,
+    dco_create_socket(c->c1.tuntap->hand, &c->c1.tuntap->dco_new_peer_ov,
                       sock->info.lsa->current_remote,
                       sock->bind_local, sock->info.lsa->bind_local,
                       get_server_poll_remaining_time(sock->server_poll_timeout),
index 33b9552b4c4bef5123269453f7dd70ef060f3bff..91dbeefe0001e3fb94063ba9d53f9cd1a5680e15 100644 (file)
@@ -196,6 +196,7 @@ struct tuntap
 
 #ifdef _WIN32
     HANDLE hand;
+    OVERLAPPED dco_new_peer_ov; /* used for async NEW_PEER dco call, which might wait for TCP connect */
     struct overlapped_io reads;
     struct overlapped_io writes;
     struct rw_handle rw_handle;