From: Lev Stipakov Date: Wed, 2 Apr 2025 11:30:11 +0000 (+0200) Subject: dco-win: Ensure correct OVERLAPPED scope X-Git-Tag: v2.6.15~25 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9c888671832041febf9284ca66fb163ab9d54a93;p=thirdparty%2Fopenvpn.git dco-win: Ensure correct OVERLAPPED scope 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 Acked-by: Gert Doering 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 --- diff --git a/src/openvpn/dco_win.c b/src/openvpn/dco_win.c index 3ec946ffb..0b8f8319d 100644 --- a/src/openvpn/dco_win.c +++ b/src/openvpn/dco_win.c @@ -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); } } } diff --git a/src/openvpn/dco_win.h b/src/openvpn/dco_win.h index 48836299a..dcf480ee8 100644 --- a/src/openvpn/dco_win.h +++ b/src/openvpn/dco_win.h @@ -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); diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c index e07068813..2eb2e7472 100644 --- a/src/openvpn/socket.c +++ b/src/openvpn/socket.c @@ -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), diff --git a/src/openvpn/tun.h b/src/openvpn/tun.h index 33b9552b4..91dbeefe0 100644 --- a/src/openvpn/tun.h +++ b/src/openvpn/tun.h @@ -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;