From a903e580464c604451f9d23ec60d681d8b71baec Mon Sep 17 00:00:00 2001 From: Lev Stipakov Date: Fri, 3 Feb 2023 10:52:29 +0200 Subject: [PATCH] Move WSK initialization into OVPN_IOCTL_NEW_PEER ioctl Having WskCaptureProviderNPI() call with WSK_INFINITE_WAIT argument in EvtDeviceAdd callback causes boot hang on some systems. It is not clear why it happens and why majority of systems are fine. Remove PnP Power callbacks, they're not relevant to us. Bump version to 0.9.0. Fixes https://github.com/OpenVPN/ovpn-dco-win/issues/24 Signed-off-by: Lev Stipakov --- Driver.cpp | 82 +++------------------------------------------ PropertySheet.props | 4 +-- bufferpool.cpp | 6 ++++ peer.cpp | 2 +- socket.cpp | 10 ++++-- socket.h | 2 +- 6 files changed, 23 insertions(+), 83 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index 143c2c6..fe2e9b8 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -89,7 +89,6 @@ DriverEntry(_In_ PDRIVER_OBJECT driverObject, _In_ PUNICODE_STRING registryPath) wskClientNpi.Dispatch = &WskAppDispatch; POVPN_DRIVER driverCtx = OvpnGetDriverContext(WdfGetDriver()); - GOTO_IF_NOT_NT_SUCCESS(done, status, WskRegister(&wskClientNpi, &driverCtx->WskRegistration)); done: @@ -286,7 +285,9 @@ VOID OvpnEvtFileCleanup(WDFFILEOBJECT fileObject) { InterlockedExchange(&device->UserspacePid, 0); - OvpnAdapterSetLinkState(OvpnGetAdapterContext(device->Adapter), MediaConnectStateDisconnected); + if (device->Adapter != NULL) { + OvpnAdapterSetLinkState(OvpnGetAdapterContext(device->Adapter), MediaConnectStateDisconnected); + } LOG_EXIT(); } @@ -312,70 +313,13 @@ VOID OvpnEvtDeviceCleanup(WDFOBJECT obj) { LOG_EXIT(); } -EVT_WDF_DEVICE_PREPARE_HARDWARE OvpnEvtDevicePrepareHardware; -EVT_WDF_DEVICE_RELEASE_HARDWARE OvpnEvtDeviceReleaseHardware; -_No_competing_thread_ EVT_WDF_DEVICE_D0_ENTRY OvpnEvtDeviceD0Entry; -_No_competing_thread_ EVT_WDF_DEVICE_D0_EXIT OvpnEvtDeviceD0Exit; - -_Use_decl_annotations_ -NTSTATUS -OvpnEvtDevicePrepareHardware(_In_ WDFDEVICE wdfDevice, _In_ WDFCMRESLIST resourcesRaw, _In_ WDFCMRESLIST resourcesTranslated) -{ - UNREFERENCED_PARAMETER(wdfDevice); - UNREFERENCED_PARAMETER(resourcesRaw); - UNREFERENCED_PARAMETER(resourcesTranslated); - - LOG_ENTER(); - LOG_EXIT(); - return STATUS_SUCCESS; -} - -_Use_decl_annotations_ -NTSTATUS -OvpnEvtDeviceReleaseHardware(_In_ WDFDEVICE wdfDevice, _In_ WDFCMRESLIST resourcesTranslated) -{ - UNREFERENCED_PARAMETER(wdfDevice); - UNREFERENCED_PARAMETER(resourcesTranslated); - - LOG_ENTER(); - LOG_EXIT(); - return STATUS_SUCCESS; -} - -_Use_decl_annotations_ -NTSTATUS -OvpnEvtDeviceD0Entry(_In_ WDFDEVICE wdfDevice, WDF_POWER_DEVICE_STATE previousState) -{ - UNREFERENCED_PARAMETER(wdfDevice); - - LOG_ENTER(); - - LOG_INFO("PreviousState", TraceLoggingUInt32(previousState, "PreviousState")); - - LOG_EXIT(); - - return STATUS_SUCCESS; -} - -_Use_decl_annotations_ -NTSTATUS -OvpnEvtDeviceD0Exit(_In_ WDFDEVICE Device, _In_ WDF_POWER_DEVICE_STATE TargetState) -{ - UNREFERENCED_PARAMETER(Device); - - LOG_ENTER(); - - LOG_INFO("TargetState", TraceLoggingUInt32(TargetState, "TargetState")); - - LOG_EXIT(); - return STATUS_SUCCESS; -} - EVT_WDF_DRIVER_DEVICE_ADD OvpnEvtDeviceAdd; _Use_decl_annotations_ NTSTATUS OvpnEvtDeviceAdd(WDFDRIVER wdfDriver, PWDFDEVICE_INIT deviceInit) { + UNREFERENCED_PARAMETER(wdfDriver); + LOG_ENTER(); // make sure only one app can access driver at time @@ -391,15 +335,6 @@ OvpnEvtDeviceAdd(WDFDRIVER wdfDriver, PWDFDEVICE_INIT deviceInit) { NTSTATUS status; GOTO_IF_NOT_NT_SUCCESS(done, status, NetDeviceInitConfig(deviceInit)); - WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; - WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); - pnpPowerCallbacks.EvtDevicePrepareHardware = OvpnEvtDevicePrepareHardware; - pnpPowerCallbacks.EvtDeviceReleaseHardware = OvpnEvtDeviceReleaseHardware; - pnpPowerCallbacks.EvtDeviceD0Entry = OvpnEvtDeviceD0Entry; - pnpPowerCallbacks.EvtDeviceD0Exit = OvpnEvtDeviceD0Exit; - - WdfDeviceInitSetPnpPowerEventCallbacks(deviceInit, &pnpPowerCallbacks); - WDF_OBJECT_ATTRIBUTES objAttributes; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&objAttributes, OVPN_DEVICE); // BCryptOpenAlgorithmProvider with BCRYPT_PROV_DISPATCH returns STATUS_NOT_SUPPORTED if sync scope is WdfSynchronizationScopeDevice @@ -440,13 +375,6 @@ OvpnEvtDeviceAdd(WDFDRIVER wdfDriver, PWDFDEVICE_INIT deviceInit) { WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual); GOTO_IF_NOT_NT_SUCCESS(done, status, WdfIoQueueCreate(wdfDevice, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &device->PendingNewPeerQueue)); - POVPN_DRIVER driver = OvpnGetDriverContext(wdfDriver); - - LOG_INFO("Before calling WskCaptureProviderNPI()"); - // Capture the WSK Provider NPI. If WSK subsystem is not ready yet, wait until it becomes ready. - GOTO_IF_NOT_NT_SUCCESS(done, status, WskCaptureProviderNPI(&driver->WskRegistration, WSK_INFINITE_WAIT, &driver->WskProviderNpi)); - LOG_INFO("After calling WskCaptureProviderNPI()"); - GOTO_IF_NOT_NT_SUCCESS(done, status, OvpnTxBufferPoolCreate(&device->TxBufferPool, device)); GOTO_IF_NOT_NT_SUCCESS(done, status, OvpnRxBufferPoolCreate(&device->RxBufferPool)); diff --git a/PropertySheet.props b/PropertySheet.props index 0fb9732..99ebfb5 100644 --- a/PropertySheet.props +++ b/PropertySheet.props @@ -3,8 +3,8 @@ 0 - 8 - 4 + 9 + 0 diff --git a/bufferpool.cpp b/bufferpool.cpp index a4cf115..5b85661 100644 --- a/bufferpool.cpp +++ b/bufferpool.cpp @@ -223,6 +223,9 @@ static VOID OvpnBufferPoolDelete(OVPN_BUFFER_POOL handle) { + if (handle == NULL) + return; + OVPN_BUFFER_POOL_IMPL* pool = (OVPN_BUFFER_POOL_IMPL*)handle; LIST_ENTRY* list_entry = NULL; @@ -277,6 +280,9 @@ OvpnRxBufferPoolCreate(OVPN_RX_BUFFER_POOL* handle) VOID OvpnBufferQueueDelete(OVPN_BUFFER_QUEUE handle) { + if (handle == NULL) + return; + OVPN_BUFFER_QUEUE_IMPL* queue = (OVPN_BUFFER_QUEUE_IMPL*)handle; ExFreePoolWithTag(queue, 'ovpn'); diff --git a/peer.cpp b/peer.cpp index 3164b87..dbe337f 100644 --- a/peer.cpp +++ b/peer.cpp @@ -71,7 +71,7 @@ OvpnPeerNew(POVPN_DEVICE device, WDFREQUEST request) BOOLEAN proto_tcp = peer->Proto == OVPN_PROTO_TCP; SIZE_T remoteAddrSize = peer->Remote.Addr4.sin_family == AF_INET ? sizeof(peer->Remote.Addr4) : sizeof(peer->Remote.Addr6); - GOTO_IF_NOT_NT_SUCCESS(done, status, OvpnSocketInit(&driver->WskProviderNpi, peer->Local.Addr4.sin_family, proto_tcp, (PSOCKADDR)&peer->Local, + GOTO_IF_NOT_NT_SUCCESS(done, status, OvpnSocketInit(&driver->WskProviderNpi, &driver->WskRegistration, peer->Local.Addr4.sin_family, proto_tcp, (PSOCKADDR)&peer->Local, (PSOCKADDR)&peer->Remote, remoteAddrSize, device, &socket)); BCRYPT_ALG_HANDLE aesAlgHandle = NULL, chachaAlgHandle = NULL; diff --git a/socket.cpp b/socket.cpp index 6b53071..3a58533 100644 --- a/socket.cpp +++ b/socket.cpp @@ -460,11 +460,18 @@ const WSK_CLIENT_CONNECTION_DISPATCH OvpnSocketTcpDispatch = { OvpnSocketTcpRece _Use_decl_annotations_ NTSTATUS -OvpnSocketInit(WSK_PROVIDER_NPI* wskProviderNpi, ADDRESS_FAMILY addressFamily, BOOLEAN tcp, PSOCKADDR localAddr, +OvpnSocketInit(WSK_PROVIDER_NPI* wskProviderNpi, WSK_REGISTRATION* wskRegistration, ADDRESS_FAMILY addressFamily, BOOLEAN tcp, PSOCKADDR localAddr, PSOCKADDR remoteAddr, SIZE_T remoteAddrSize, PVOID deviceContext, PWSK_SOCKET* socket) { + NTSTATUS status; WSK_EVENT_CALLBACK_CONTROL eventCallbackControl = {}; + // init WSK + if (wskProviderNpi->Client == NULL) { + LOG_INFO("Init WSK"); + GOTO_IF_NOT_NT_SUCCESS(done, status, WskCaptureProviderNPI(wskRegistration, WSK_INFINITE_WAIT, wskProviderNpi)); + } + // create socket USHORT socketType = tcp ? SOCK_STREAM : SOCK_DGRAM; @@ -472,7 +479,6 @@ OvpnSocketInit(WSK_PROVIDER_NPI* wskProviderNpi, ADDRESS_FAMILY addressFamily, B ULONG flags = tcp ? WSK_FLAG_CONNECTION_SOCKET : WSK_FLAG_DATAGRAM_SOCKET; PVOID dispatch = tcp ? (PVOID)&OvpnSocketTcpDispatch : (PVOID)&OvpnSocketUdpDispatch; - NTSTATUS status; GOTO_IF_NOT_NT_SUCCESS(done, status, OvpnSocketSyncOp("CreateSocket", [&status, wskProviderNpi, addressFamily, socketType, proto, flags, deviceContext, dispatch](PIRP irp) { return wskProviderNpi->Dispatch->WskSocket(wskProviderNpi->Client, addressFamily, socketType, proto, flags, deviceContext, dispatch, NULL, NULL, NULL, irp); diff --git a/socket.h b/socket.h index 5f553d0..38e04a6 100644 --- a/socket.h +++ b/socket.h @@ -59,7 +59,7 @@ struct OvpnSocket _Must_inspect_result_ _IRQL_requires_(PASSIVE_LEVEL) NTSTATUS -OvpnSocketInit(_In_ WSK_PROVIDER_NPI* wskProviderNpi, ADDRESS_FAMILY addrFamily, +OvpnSocketInit(_In_ WSK_PROVIDER_NPI* wskProviderNpi, _In_ WSK_REGISTRATION* wskRegistration, ADDRESS_FAMILY addrFamily, BOOLEAN tcp, _In_ PSOCKADDR localAddr, _In_ PSOCKADDR remoteAddr, SIZE_T remoteAddrSize, _In_ PVOID deviceContext, _Out_ PWSK_SOCKET* socket);