Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Fault Injection in WFP OS APIs #2380

Merged
merged 3 commits into from
Apr 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 38 additions & 11 deletions netebpfext/net_ebpf_ext.c
Original file line number Diff line number Diff line change
Expand Up @@ -349,8 +349,12 @@ void
net_ebpf_extension_delete_wfp_filters(uint32_t filter_count, _Frees_ptr_ _In_count_(filter_count) uint64_t* filter_ids)
{
NET_EBPF_EXT_LOG_ENTRY();
NTSTATUS status;
for (uint32_t index = 0; index < filter_count; index++) {
FwpmFilterDeleteById(_fwp_engine_handle, filter_ids[index]);
status = FwpmFilterDeleteById(_fwp_engine_handle, filter_ids[index]);
if (!NT_SUCCESS(status)) {
NET_EBPF_EXT_LOG_NTSTATUS_API_FAILURE(NET_EBPF_EXT_TRACELOG_KEYWORD_ERROR, "FwpmFilterDeleteById", status);
}
}
ExFreePool(filter_ids);
NET_EBPF_EXT_LOG_EXIT();
Expand Down Expand Up @@ -444,7 +448,11 @@ net_ebpf_extension_add_wfp_filters(
ExFreePool(local_filter_ids);
}
if (is_in_transaction) {
FwpmTransactionAbort(_fwp_engine_handle);
status = FwpmTransactionAbort(_fwp_engine_handle);
if (!NT_SUCCESS(status)) {
NET_EBPF_EXT_LOG_NTSTATUS_API_FAILURE(
NET_EBPF_EXT_TRACELOG_KEYWORD_ERROR, "FwpmTransactionAbort", status);
}
}
}

Expand Down Expand Up @@ -584,7 +592,7 @@ net_ebpf_extension_initialize_wfp_components(_Inout_ void* device_object)

UNREFERENCED_PARAMETER(device_object);

BOOLEAN is_engined_opened = FALSE;
BOOLEAN is_engine_opened = FALSE;
BOOLEAN is_in_transaction = FALSE;

FWPM_SESSION session = {0};
Expand All @@ -602,7 +610,7 @@ net_ebpf_extension_initialize_wfp_components(_Inout_ void* device_object)

status = FwpmEngineOpen(NULL, RPC_C_AUTHN_WINNT, NULL, &session, &_fwp_engine_handle);
NET_EBPF_EXT_BAIL_ON_API_FAILURE_STATUS("FwpmEngineOpen", status);
is_engined_opened = TRUE;
is_engine_opened = TRUE;

status = FwpmTransactionBegin(_fwp_engine_handle, 0);
NET_EBPF_EXT_BAIL_ON_API_FAILURE_STATUS("FwpmTransactionBegin", status);
Expand Down Expand Up @@ -654,12 +662,15 @@ net_ebpf_extension_initialize_wfp_components(_Inout_ void* device_object)

if (!NT_SUCCESS(status)) {
if (is_in_transaction) {
status = FwpmTransactionAbort(_fwp_engine_handle);
if (!NT_SUCCESS(status)) {
NET_EBPF_EXT_LOG_NTSTATUS_API_FAILURE(
NET_EBPF_EXT_TRACELOG_KEYWORD_ERROR, "FwpmTransactionAbort", status);
NTSTATUS ret = FwpmTransactionAbort(_fwp_engine_handle);
if (!NT_SUCCESS(ret)) {
NET_EBPF_EXT_LOG_NTSTATUS_API_FAILURE(NET_EBPF_EXT_TRACELOG_KEYWORD_ERROR, "FwpmTransactionAbort", ret);
}
}

if (is_engine_opened) {
net_ebpf_extension_uninitialize_wfp_components();
}
}

NET_EBPF_EXT_RETURN_NTSTATUS(status);
Expand All @@ -669,16 +680,32 @@ void
net_ebpf_extension_uninitialize_wfp_components(void)
{
size_t index;
NTSTATUS status;

if (_fwp_engine_handle != NULL) {
FwpmEngineClose(_fwp_engine_handle);
status = FwpmEngineClose(_fwp_engine_handle);
if (!NT_SUCCESS(status)) {
NET_EBPF_EXT_LOG_NTSTATUS_API_FAILURE(NET_EBPF_EXT_TRACELOG_KEYWORD_ERROR, "FwpmEngineClose", status);
}
_fwp_engine_handle = NULL;

for (index = 0; index < EBPF_COUNT_OF(_net_ebpf_ext_wfp_callout_states); index++) {
FwpsCalloutUnregisterById(_net_ebpf_ext_wfp_callout_states[index].assigned_callout_id);
status = FwpsCalloutUnregisterById(_net_ebpf_ext_wfp_callout_states[index].assigned_callout_id);
if (!NT_SUCCESS(status)) {
NET_EBPF_EXT_LOG_NTSTATUS_API_FAILURE(
NET_EBPF_EXT_TRACELOG_KEYWORD_ERROR, "FwpsCalloutUnregisterById", status);
}
}
}

FwpsInjectionHandleDestroy(_net_ebpf_ext_l2_injection_handle);
// FwpsInjectionHandleCreate can fail. So, check for NULL.
if (_net_ebpf_ext_l2_injection_handle != NULL) {
status = FwpsInjectionHandleDestroy(_net_ebpf_ext_l2_injection_handle);
if (!NT_SUCCESS(status)) {
NET_EBPF_EXT_LOG_NTSTATUS_API_FAILURE(
NET_EBPF_EXT_TRACELOG_KEYWORD_ERROR, "FwpsInjectionHandleDestroy", status);
}
}
}

NTSTATUS
Expand Down
48 changes: 48 additions & 0 deletions netebpfext/user/fwp_um.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,10 @@ static std::unique_ptr<fwp_injection_handle> _injection_handle;

_IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS FwpmFilterDeleteById0(_In_ HANDLE engine_handle, _In_ uint64_t id)
{
if (ebpf_fault_injection_inject_fault()) {
return STATUS_INVALID_PARAMETER;
}

auto& engine = *reinterpret_cast<_fwp_engine*>(engine_handle);

if (engine.remove_fwpm_filter(id)) {
Expand All @@ -444,6 +448,10 @@ _IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS FwpmFilterDeleteById0(_In_ HANDLE en
_IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS
FwpmTransactionBegin0(_In_ _Acquires_lock_(_Curr_) HANDLE engine_handle, _In_ uint32_t flags)
{
if (ebpf_fault_injection_inject_fault()) {
return STATUS_NO_MEMORY;
}

UNREFERENCED_PARAMETER(engine_handle);
UNREFERENCED_PARAMETER(flags);
return STATUS_SUCCESS;
Expand All @@ -455,6 +463,10 @@ _IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS FwpmFilterAdd0(
_In_opt_ PSECURITY_DESCRIPTOR sd,
_Out_opt_ uint64_t* id)
{
if (ebpf_fault_injection_inject_fault()) {
return STATUS_NO_MEMORY;
}

UNREFERENCED_PARAMETER(sd);

auto& engine = *reinterpret_cast<_fwp_engine*>(engine_handle);
Expand Down Expand Up @@ -483,6 +495,10 @@ _IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS FwpmTransactionAbort0(_In_ _Releases
_IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS
FwpsCalloutRegister3(_Inout_ void* device_object, _In_ const FWPS_CALLOUT3* callout, _Out_opt_ uint32_t* callout_id)
{
if (ebpf_fault_injection_inject_fault()) {
return STATUS_NO_MEMORY;
}

UNREFERENCED_PARAMETER(device_object);

auto& engine = *_fwp_engine::get()->get();
Expand All @@ -502,6 +518,10 @@ _IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS FwpmCalloutAdd0(
_In_opt_ PSECURITY_DESCRIPTOR sd,
_Out_opt_ uint32_t* id)
{
if (ebpf_fault_injection_inject_fault()) {
return STATUS_NO_MEMORY;
}

auto& engine = *reinterpret_cast<_fwp_engine*>(engine_handle);

auto id_returned = engine.add_fwpm_callout(callout);
Expand All @@ -515,6 +535,10 @@ _IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS FwpmCalloutAdd0(

_IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS FwpsCalloutUnregisterById0(_In_ const uint32_t callout_id)
{
if (ebpf_fault_injection_inject_fault()) {
return STATUS_NO_MEMORY;
}

auto& engine = *_fwp_engine::get()->get();

if (engine.remove_fwps_callout(callout_id)) {
Expand All @@ -531,6 +555,10 @@ _IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS FwpmEngineOpen0(
_In_opt_ const FWPM_SESSION0* session,
_Out_ HANDLE* engine_handle)
{
if (ebpf_fault_injection_inject_fault()) {
return STATUS_NO_MEMORY;
}

UNREFERENCED_PARAMETER(server_name);
UNREFERENCED_PARAMETER(authn_service);
UNREFERENCED_PARAMETER(auth_identity);
Expand All @@ -543,6 +571,10 @@ _IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS FwpmEngineOpen0(
_IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS
FwpmProviderAdd0(_In_ HANDLE engine_handle, _In_ const FWPM_PROVIDER0* provider, _In_opt_ PSECURITY_DESCRIPTOR sd)
{
if (ebpf_fault_injection_inject_fault()) {
return STATUS_NO_MEMORY;
}

auto& engine = *reinterpret_cast<_fwp_engine*>(engine_handle);

engine.add_fwpm_provider(provider);
Expand All @@ -554,6 +586,10 @@ _IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS
_IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS
FwpmSubLayerAdd0(_In_ HANDLE engine_handle, _In_ const FWPM_SUBLAYER0* sub_layer, _In_opt_ PSECURITY_DESCRIPTOR sd)
{
if (ebpf_fault_injection_inject_fault()) {
return STATUS_NO_MEMORY;
}

UNREFERENCED_PARAMETER(sd);
auto& engine = *reinterpret_cast<_fwp_engine*>(engine_handle);

Expand All @@ -564,6 +600,10 @@ _IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS

_IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS FwpmEngineClose0(_Inout_ HANDLE engine_handle)
{
if (ebpf_fault_injection_inject_fault()) {
return STATUS_NO_MEMORY;
}

if (engine_handle != _fwp_engine::get()->get()) {
return STATUS_INVALID_PARAMETER;
} else {
Expand All @@ -574,6 +614,10 @@ _IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS FwpmEngineClose0(_Inout_ HANDLE engi
_IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS FwpsInjectionHandleCreate0(
_In_opt_ ADDRESS_FAMILY address_family, _In_ uint32_t flags, _Out_ HANDLE* injection_handle)
{
if (ebpf_fault_injection_inject_fault()) {
return STATUS_NO_MEMORY;
}

_injection_handle = std::make_unique<_fwp_injection_handle>(address_family, flags);
*injection_handle = _injection_handle.get();

Expand All @@ -582,6 +626,10 @@ _IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS FwpsInjectionHandleCreate0(

_IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS FwpsInjectionHandleDestroy0(_In_ HANDLE injection_handle)
{
if (ebpf_fault_injection_inject_fault()) {
return STATUS_NO_MEMORY;
}

if (injection_handle != _injection_handle.get()) {
return STATUS_INVALID_PARAMETER;
} else {
Expand Down