]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
dco-win: Fix crash when cancelling pending operation
authorLev Stipakov <lev@openvpn.net>
Tue, 1 Apr 2025 18:15:30 +0000 (20:15 +0200)
committerGert Doering <gert@greenie.muc.de>
Tue, 1 Apr 2025 18:37:50 +0000 (20:37 +0200)
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.

Github: closes OpenVPN/openvpn#715

Change-Id: Ib1db457c42a80f6b8fc0e3ceb4a895d4cf7f0155
Signed-off-by: Lev Stipakov <lev@openvpn.net>
Acked-by: Gert Doering <gert@greenie.muc.de>
Message-Id: <20250401181535.7854-1-gert@greenie.muc.de>
URL: https://sourceforge.net/p/openvpn/mailman/message/59168247/
URL: https://gerrit.openvpn.net/c/openvpn/+/928
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 8b47124631bfd6714f1b9ad69aed64cb5cf4dbd9..a386e532285df3542b9b54eb7ae07a7452ff01a4 100644 (file)
@@ -321,7 +321,7 @@ dco_mp_start_vpn(HANDLE handle, struct link_socket *sock)
 }
 
 void
-dco_p2p_new_peer(HANDLE handle, struct link_socket *sock, struct signal_info *sig_info)
+dco_p2p_new_peer(HANDLE handle, OVERLAPPED *ov, struct link_socket *sock, struct signal_info *sig_info)
 {
     msg(D_DCO_DEBUG, "%s", __func__);
 
@@ -395,8 +395,8 @@ dco_p2p_new_peer(HANDLE handle, struct link_socket *sock, struct signal_info *si
         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)
@@ -405,7 +405,7 @@ dco_p2p_new_peer(HANDLE handle, struct link_socket *sock, struct signal_info *si
         }
         else
         {
-            dco_connect_wait(handle, &ov, get_server_poll_remaining_time(sock->server_poll_timeout), sig_info);
+            dco_connect_wait(handle, ov, get_server_poll_remaining_time(sock->server_poll_timeout), sig_info);
         }
     }
 }
index 95c95c8f5e0db828b40d2d5a5b4f852adcf28810..e8e4e223d578c99cf37e8d478b14a62f6b24d544 100644 (file)
@@ -63,7 +63,7 @@ void
 dco_mp_start_vpn(HANDLE handle, struct link_socket *sock);
 
 void
-dco_p2p_new_peer(HANDLE handle, struct link_socket *sock, struct signal_info *sig_info);
+dco_p2p_new_peer(HANDLE handle, OVERLAPPED *ov, struct link_socket *sock, struct signal_info *sig_info);
 
 void
 dco_start_tun(struct tuntap *tt);
index 4fb6fe6c365aea607b4994f73d3babc3ebf2bca7..bd7a4498c8def53288583e6b76ffacff1747b7ba 100644 (file)
@@ -2247,7 +2247,7 @@ create_socket_dco_win(struct context *c, struct link_socket *sock,
     }
     else
     {
-        dco_p2p_new_peer(c->c1.tuntap->hand, sock, sig_info);
+        dco_p2p_new_peer(c->c1.tuntap->hand, &c->c1.tuntap->dco_new_peer_ov, sock, sig_info);
     }
     sock->sockflags |= SF_DCO_WIN;
 
index b616f5d8f03b58550a4d7b4a9727fd7235639a04..bcc23b4aa1712556f752be7c7298a8976b33dbe8 100644 (file)
@@ -215,6 +215,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;