// Copyright (c) Microsoft Corporation // SPDX-License-Identifier: MIT /*++ Abstract: WDF based driver that does the following: 1. Registers a set of WFP callouts. 2. Registers as an eBPF program information provider and hook provider. Environment: Kernel mode --*/ // ntddk.h needs to be included first due to inter header dependencies on Windows. #include #pragma warning(push) #pragma warning(disable : 4201) // unnamed struct/union #include #include #pragma warning(pop) #include #include #include "ebpf_platform.h" #include "ebpf_store_helper.h" #include "net_ebpf_ext.h" #define NET_EBPF_EXT_DEVICE_NAME L"\\Device\\NetEbpfExt" // Driver global variables static WDFDEVICE _net_ebpf_ext_device = NULL; static BOOLEAN _net_ebpf_ext_driver_unloading_flag = FALSE; DEVICE_OBJECT* _net_ebpf_ext_driver_device_object; // // Pre-Declarations // DRIVER_INITIALIZE DriverEntry; static void _net_ebpf_ext_driver_uninitialize_objects() { _net_ebpf_ext_driver_unloading_flag = TRUE; net_ebpf_ext_unregister_providers(); net_ebpf_extension_uninitialize_wfp_components(); net_ebpf_ext_uninitialize_ndis_handles(); net_ebpf_ext_trace_terminate(); if (_net_ebpf_ext_device != NULL) WdfObjectDelete(_net_ebpf_ext_device); } static _Function_class_(EVT_WDF_DRIVER_UNLOAD) _IRQL_requires_same_ _IRQL_requires_max_(PASSIVE_LEVEL) void _net_ebpf_ext_driver_unload(_In_ WDFDRIVER driver_object) { UNREFERENCED_PARAMETER(driver_object); _net_ebpf_ext_driver_uninitialize_objects(); } // // Create and initialize WDF driver, device object, // WFP callouts and NPI providers. // static NTSTATUS _net_ebpf_ext_driver_initialize_objects(_Inout_ DRIVER_OBJECT* driver_object, _In_ const UNICODE_STRING* registry_path) { NTSTATUS status; WDF_DRIVER_CONFIG driver_configuration; PWDFDEVICE_INIT device_initialize = NULL; UNICODE_STRING ebpf_device_name; WDFDRIVER driver; WDF_DRIVER_CONFIG_INIT(&driver_configuration, WDF_NO_EVENT_CALLBACK); driver_configuration.DriverInitFlags |= WdfDriverInitNonPnpDriver; driver_configuration.EvtDriverUnload = _net_ebpf_ext_driver_unload; status = WdfDriverCreate(driver_object, registry_path, WDF_NO_OBJECT_ATTRIBUTES, &driver_configuration, &driver); if (!NT_SUCCESS(status)) { goto Exit; } device_initialize = WdfControlDeviceInitAllocate( driver, &SDDL_DEVOBJ_SYS_ALL_ADM_ALL // only kernel/system and administrators. ); if (!device_initialize) { status = STATUS_INSUFFICIENT_RESOURCES; goto Exit; } WdfDeviceInitSetDeviceType(device_initialize, FILE_DEVICE_NETWORK); WdfDeviceInitSetCharacteristics(device_initialize, FILE_DEVICE_SECURE_OPEN, FALSE); WdfDeviceInitSetCharacteristics(device_initialize, FILE_AUTOGENERATED_DEVICE_NAME, TRUE); RtlInitUnicodeString(&ebpf_device_name, NET_EBPF_EXT_DEVICE_NAME); status = WdfDeviceInitAssignName(device_initialize, &ebpf_device_name); if (!NT_SUCCESS(status)) { goto Exit; } status = WdfDeviceCreate(&device_initialize, WDF_NO_OBJECT_ATTRIBUTES, &_net_ebpf_ext_device); if (!NT_SUCCESS(status)) { // do not free if any other call // after WdfDeviceCreate fails. WdfDeviceInitFree(device_initialize); device_initialize = NULL; goto Exit; } _net_ebpf_ext_driver_device_object = WdfDeviceWdmGetDeviceObject(_net_ebpf_ext_device); status = net_ebpf_ext_trace_initiate(); if (!NT_SUCCESS(status)) goto Exit; status = net_ebpf_ext_initialize_ndis_handles((const DRIVER_OBJECT*)driver_object); if (!NT_SUCCESS(status)) goto Exit; status = net_ebpf_ext_register_providers(); if (!NT_SUCCESS(status)) goto Exit; // TODO: https://github.com/microsoft/ebpf-for-windows/issues/521 (void)net_ebpf_extension_initialize_wfp_components(_net_ebpf_ext_driver_device_object); WdfControlFinishInitializing(_net_ebpf_ext_device); Exit: return status; } NTSTATUS DriverEntry(_In_ DRIVER_OBJECT* driver_object, _In_ UNICODE_STRING* registry_path) { NTSTATUS status; // Request NX Non-Paged Pool when available ExInitializeDriverRuntime(DrvRtPoolNxOptIn); KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "NetEbpfExt: DriverEntry\n")); status = _net_ebpf_ext_driver_initialize_objects(driver_object, registry_path); if (!NT_SUCCESS(status)) { goto Exit; } Exit: if (!NT_SUCCESS(status)) { _net_ebpf_ext_driver_uninitialize_objects(); } return status; }