From f60a49362515a87ccf8db406ef422499adf34eb7 Mon Sep 17 00:00:00 2001 From: Lev Stipakov Date: Tue, 1 Apr 2025 20:15:30 +0200 Subject: [PATCH] dco-win: Fix crash when cancelling pending operation 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 Acked-by: Gert Doering 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 --- src/openvpn/dco_win.c | 8 ++++---- src/openvpn/dco_win.h | 2 +- src/openvpn/socket.c | 2 +- src/openvpn/tun.h | 1 + 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/openvpn/dco_win.c b/src/openvpn/dco_win.c index 8b4712463..a386e5322 100644 --- a/src/openvpn/dco_win.c +++ b/src/openvpn/dco_win.c @@ -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); } } } diff --git a/src/openvpn/dco_win.h b/src/openvpn/dco_win.h index 95c95c8f5..e8e4e223d 100644 --- a/src/openvpn/dco_win.h +++ b/src/openvpn/dco_win.h @@ -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); diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c index 4fb6fe6c3..bd7a4498c 100644 --- a/src/openvpn/socket.c +++ b/src/openvpn/socket.c @@ -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; diff --git a/src/openvpn/tun.h b/src/openvpn/tun.h index b616f5d8f..bcc23b4aa 100644 --- a/src/openvpn/tun.h +++ b/src/openvpn/tun.h @@ -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; -- 2.47.3