BOOL WinDivertHelperFormatIPv4Address(
From 0b164b6ba36de75d5a689573861d54ee73a0bf19 Mon Sep 17 00:00:00 2001
From: basil00
Date: Sat, 9 Apr 2022 09:49:45 +0800
Subject: [PATCH 07/11] Fix handling of FwpmTransaction*() errors.
Fixes #294
---
sys/windivert.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/sys/windivert.c b/sys/windivert.c
index 536be73..901367a 100644
--- a/sys/windivert.c
+++ b/sys/windivert.c
@@ -122,8 +122,7 @@ typedef enum
WINDIVERT_CONTEXT_STATE_OPENING = 0xA0, // Context is opening.
WINDIVERT_CONTEXT_STATE_OPEN = 0xB1, // Context is open.
WINDIVERT_CONTEXT_STATE_CLOSING = 0xC2, // Context is closing.
- WINDIVERT_CONTEXT_STATE_CLOSED = 0xD3, // Context is closed.
- WINDIVERT_CONTEXT_STATE_INVALID = 0xE4 // Context is invalid.
+ WINDIVERT_CONTEXT_STATE_CLOSED = 0xD3 // Context is closed.
} context_state_t;
struct context_s
{
From c983d554c9c9d102176e4440ef811d2bf845e32e Mon Sep 17 00:00:00 2001
From: basil00
Date: Sun, 10 Apr 2022 06:51:38 +0800
Subject: [PATCH 08/11] Fix previous commit 8bda0af
Fix #294
Previous commit was incomplete.
---
sys/windivert.c | 58 ++++++++++++++++++++++++++-----------------------
1 file changed, 31 insertions(+), 27 deletions(-)
diff --git a/sys/windivert.c b/sys/windivert.c
index 901367a..d5d55d2 100644
--- a/sys/windivert.c
+++ b/sys/windivert.c
@@ -1,6 +1,6 @@
/*
* windivert.c
- * (C) 2019, all rights reserved,
+ * (C) 2022, all rights reserved,
*
* This file is part of WinDivert.
*
@@ -122,7 +122,7 @@ typedef enum
WINDIVERT_CONTEXT_STATE_OPENING = 0xA0, // Context is opening.
WINDIVERT_CONTEXT_STATE_OPEN = 0xB1, // Context is open.
WINDIVERT_CONTEXT_STATE_CLOSING = 0xC2, // Context is closing.
- WINDIVERT_CONTEXT_STATE_CLOSED = 0xD3 // Context is closed.
+ WINDIVERT_CONTEXT_STATE_CLOSED = 0xD3, // Context is closed.
} context_state_t;
struct context_s
{
@@ -332,7 +332,7 @@ extern VOID windivert_worker(IN WDFWORKITEM item);
static void windivert_read_service(context_t context);
extern VOID windivert_create(IN WDFDEVICE device, IN WDFREQUEST request,
IN WDFFILEOBJECT object);
-static NTSTATUS windivert_install_provider();
+static NTSTATUS windivert_install_provider(void);
static NTSTATUS windivert_install_sublayer(layer_t layer);
static NTSTATUS windivert_install_callouts(context_t context, UINT8 layer,
UINT64 flags);
@@ -1165,12 +1165,14 @@ extern NTSTATUS DriverEntry(IN PDRIVER_OBJECT driver_obj,
if (!NT_SUCCESS(status))
{
DEBUG_ERROR("failed to begin WFP transaction", status);
+ FwpmTransactionAbort0(engine_handle);
goto driver_entry_exit;
}
status = windivert_install_provider();
if (!NT_SUCCESS(status))
{
DEBUG_ERROR("failed to install provider", status);
+ FwpmTransactionAbort0(engine_handle);
goto driver_entry_exit;
}
status = windivert_install_sublayer(WINDIVERT_LAYER_INBOUND_NETWORK_IPV4);
@@ -1282,6 +1284,7 @@ driver_entry_sublayer_error:
if (!NT_SUCCESS(status))
{
DEBUG_ERROR("failed to commit WFP transaction", status);
+ FwpmTransactionAbort0(engine_handle);
goto driver_entry_exit;
}
@@ -1358,6 +1361,7 @@ static void windivert_driver_unload(void)
if (!NT_SUCCESS(status))
{
DEBUG_ERROR("failed to begin WFP transaction", status);
+ FwpmTransactionAbort0(engine_handle);
FwpmEngineClose0(engine_handle);
return;
}
@@ -1408,6 +1412,7 @@ static void windivert_driver_unload(void)
status = FwpmTransactionCommit0(engine_handle);
if (!NT_SUCCESS(status))
{
+ FwpmTransactionAbort0(engine_handle);
DEBUG_ERROR("failed to commit WFP transaction", status);
}
FwpmEngineClose0(engine_handle);
@@ -1567,7 +1572,7 @@ windivert_create_exit:
// Clean-up on error:
if (!NT_SUCCESS(status))
{
- context->state = WINDIVERT_CONTEXT_STATE_INVALID;
+ context->state = WINDIVERT_CONTEXT_STATE_CLOSED;
if (context->read_queue != NULL)
{
WdfObjectDelete(context->read_queue);
@@ -1576,14 +1581,7 @@ windivert_create_exit:
{
WdfObjectDelete(context->worker);
}
- if (context->process != NULL)
- {
- ObDereferenceObject(context->process);
- }
- if (context->engine_handle != NULL)
- {
- FwpmEngineClose0(context->engine_handle);
- }
+ // process/engine_handle handled by windivert_destroy()
}
WdfRequestComplete(request, status);
@@ -1602,15 +1600,15 @@ static NTSTATUS windivert_install_callouts(context_t context, UINT8 layer,
accept, close;
NTSTATUS status = STATUS_SUCCESS;
- inbound = ((flags & WINDIVERT_FILTER_FLAG_INBOUND) != 0);
- outbound = ((flags & WINDIVERT_FILTER_FLAG_OUTBOUND) != 0);
- ipv4 = ((flags & WINDIVERT_FILTER_FLAG_IP) != 0);
- ipv6 = ((flags & WINDIVERT_FILTER_FLAG_IPV6) != 0);
- bind = ((flags & WINDIVERT_FILTER_FLAG_EVENT_SOCKET_BIND) != 0);
- connect = ((flags & WINDIVERT_FILTER_FLAG_EVENT_SOCKET_CONNECT) != 0);
- listen = ((flags & WINDIVERT_FILTER_FLAG_EVENT_SOCKET_LISTEN) != 0);
- accept = ((flags & WINDIVERT_FILTER_FLAG_EVENT_SOCKET_ACCEPT) != 0);
- close = ((flags & WINDIVERT_FILTER_FLAG_EVENT_SOCKET_CLOSE) != 0);
+ inbound = ((flags & WINDIVERT_FILTER_FLAG_INBOUND) != 0);
+ outbound = ((flags & WINDIVERT_FILTER_FLAG_OUTBOUND) != 0);
+ ipv4 = ((flags & WINDIVERT_FILTER_FLAG_IP) != 0);
+ ipv6 = ((flags & WINDIVERT_FILTER_FLAG_IPV6) != 0);
+ bind = ((flags & WINDIVERT_FILTER_FLAG_EVENT_SOCKET_BIND) != 0);
+ connect = ((flags & WINDIVERT_FILTER_FLAG_EVENT_SOCKET_CONNECT) != 0);
+ listen = ((flags & WINDIVERT_FILTER_FLAG_EVENT_SOCKET_LISTEN) != 0);
+ accept = ((flags & WINDIVERT_FILTER_FLAG_EVENT_SOCKET_ACCEPT) != 0);
+ close = ((flags & WINDIVERT_FILTER_FLAG_EVENT_SOCKET_CLOSE) != 0);
i = 0;
switch (layer)
@@ -1802,8 +1800,7 @@ static NTSTATUS windivert_install_callout(context_t context, UINT idx,
if (!NT_SUCCESS(status))
{
DEBUG_ERROR("failed to begin WFP transaction", status);
- FwpsCalloutUnregisterByKey0(&callout_guid);
- return status;
+ goto windivert_install_callout_error;
}
status = FwpmCalloutAdd0(engine, &mcallout, NULL, NULL);
if (!NT_SUCCESS(status))
@@ -1821,8 +1818,7 @@ static NTSTATUS windivert_install_callout(context_t context, UINT idx,
if (!NT_SUCCESS(status))
{
DEBUG_ERROR("failed to commit WFP transaction", status);
- FwpsCalloutUnregisterByKey0(&callout_guid);
- return status;
+ goto windivert_install_callout_error;
}
KeAcquireInStackQueuedSpinLock(&context->lock, &lock_handle);
@@ -1877,6 +1873,7 @@ windivert_uninstall_callouts_error:
// RPC handle was closed first. So, this path is "normal" if
// the user's app crashed or never closed the WinDivert handle.
DEBUG_ERROR("failed to begin WFP transaction", status);
+ FwpmTransactionAbort0(engine);
goto windivert_uninstall_callouts_unregister;
}
for (i = 0; i < WINDIVERT_CONTEXT_MAXLAYERS; i++)
@@ -1921,6 +1918,7 @@ windivert_uninstall_callouts_error:
if (!NT_SUCCESS(status))
{
DEBUG_ERROR("failed to commit WFP transaction", status);
+ FwpmTransactionAbort0(engine);
// continue
}
@@ -2103,9 +2101,15 @@ extern VOID windivert_destroy(IN WDFOBJECT object)
filter = context->filter;
KeReleaseInStackQueuedSpinLock(&lock_handle);
windivert_uninstall_callouts(context, WINDIVERT_CONTEXT_STATE_CLOSED);
- FwpmEngineClose0(context->engine_handle);
+ if (context->engine_handle != NULL)
+ {
+ FwpmEngineClose0(context->engine_handle);
+ }
windivert_free((PVOID)filter);
- ObDereferenceObject(context->process);
+ if (context->process != NULL)
+ {
+ ObDereferenceObject(context->process);
+ }
}
/*
From 65bb889c792147938881d1ed7786238b0c2b632f Mon Sep 17 00:00:00 2001
From: basil00
Date: Sat, 30 Jul 2022 11:34:25 +0800
Subject: [PATCH 09/11] Bump version and copyright years
---
VERSION | 2 +-
inf/windivert32.inf | 2 +-
inf/windivert64.inf | 2 +-
sys/windivert.rc | 4 ++--
4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/VERSION b/VERSION
index ccbccc3..c043eea 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.2.0
+2.2.1
diff --git a/inf/windivert32.inf b/inf/windivert32.inf
index 30da774..08b1aba 100644
--- a/inf/windivert32.inf
+++ b/inf/windivert32.inf
@@ -4,7 +4,7 @@ Class = WFPCALLOUTS
ClassGuid = {57465043-616C-6C6F-7574-5F636C617373}
Provider = %Basil%
CatalogFile = WinDivert32.Cat
-DriverVer = 08/08/2019,2.2.0
+DriverVer = 01/08/2022,2.2.1
[SourceDisksNames]
1 = %DiskName%
diff --git a/inf/windivert64.inf b/inf/windivert64.inf
index c5e2cdb..33888f0 100644
--- a/inf/windivert64.inf
+++ b/inf/windivert64.inf
@@ -4,7 +4,7 @@ Class = WFPCALLOUTS
ClassGuid = {57465043-616C-6C6F-7574-5F636C617373}
Provider = %Basil%
CatalogFile = WinDivert64.Cat
-DriverVer = 08/08/2019,2.2.0
+DriverVer = 01/08/2022,2.2.1
[SourceDisksNames]
1 = %DiskName%
diff --git a/sys/windivert.rc b/sys/windivert.rc
index 11a4e97..775f97b 100644
--- a/sys/windivert.rc
+++ b/sys/windivert.rc
@@ -1,6 +1,6 @@
/*
* windivert.rc
- * (C) 2019, all rights reserved,
+ * (C) 2022, all rights reserved,
*
* This file is part of WinDivert.
*
@@ -48,7 +48,7 @@
#define VER_PRODUCTVERSION 2.2
#define VER_PRODUCTVERSION_STR "2.2"
#define VER_COMPANYNAME_STR "Basil"
-#define VER_LEGALCOPYRIGHT_YEARS "2011-2019"
+#define VER_LEGALCOPYRIGHT_YEARS "2011-2022"
#define VER_LEGALCOPYRIGHT_STR \
"Copyright \251 " VER_COMPANYNAME_STR " " VER_LEGALCOPYRIGHT_YEARS
#define VER_FILEVERSION VER_PRODUCTVERSION
From 3402f8b2f1a787e67b11e3212f1cffee3aa07b5e Mon Sep 17 00:00:00 2001
From: basil00
Date: Mon, 12 Sep 2022 08:08:42 +0800
Subject: [PATCH 10/11] Fix #315
---
sys/windivert.c | 61 ++++++++++++++++++++++---------------------------
1 file changed, 27 insertions(+), 34 deletions(-)
diff --git a/sys/windivert.c b/sys/windivert.c
index d5d55d2..cca6cc9 100644
--- a/sys/windivert.c
+++ b/sys/windivert.c
@@ -273,8 +273,6 @@ struct flow_s
UINT64 flow_id; // WFP flow ID.
UINT32 callout_id; // WFP callout ID.
UINT16 layer_id; // WFP layout ID.
- BOOL inserted:1; // Flow inserted into context?
- BOOL deleted:1; // Flow deleted from context?
BOOL outbound:1; // Flow is outound?
BOOL loopback:1; // Flow is loopback?
BOOL ipv6:1; // Flow is ipv6?
@@ -1981,17 +1979,20 @@ windivert_cleanup_error:
context->state = WINDIVERT_CONTEXT_STATE_CLOSING;
sniff_mode = ((context->flags & WINDIVERT_FLAG_SNIFF) != 0);
forward = (context->layer == WINDIVERT_LAYER_NETWORK_FORWARD);
- while (!IsListEmpty(&context->flow_set))
+ entry = context->flow_set.Flink;
+ if (entry != &context->flow_set)
{
- entry = RemoveHeadList(&context->flow_set);
- flow = CONTAINING_RECORD(entry, struct flow_s, entry);
- flow->deleted = TRUE;
KeReleaseInStackQueuedSpinLock(&lock_handle);
- status = FwpsFlowRemoveContext0(flow->flow_id, flow->layer_id,
- flow->callout_id);
- if (!NT_SUCCESS(status))
+ for (; entry != &context->flow_set; entry = entry->Flink)
{
- windivert_free(flow);
+ flow = CONTAINING_RECORD(entry, struct flow_s, entry);
+ status = FwpsFlowRemoveContext0(flow->flow_id, flow->layer_id,
+ flow->callout_id);
+ if (!NT_SUCCESS(status) && status != STATUS_UNSUCCESSFUL)
+ {
+ // For STATUS_UNSUCCESSFUL, flow_delete() is still called.
+ WdfObjectDereference((WDFOBJECT)object);
+ }
}
KeAcquireInStackQueuedSpinLock(&context->lock, &lock_handle);
}
@@ -2086,6 +2087,8 @@ extern VOID windivert_destroy(IN WDFOBJECT object)
KLOCK_QUEUE_HANDLE lock_handle;
context_t context = windivert_context_get((WDFFILEOBJECT)object);
const WINDIVERT_FILTER *filter;
+ PLIST_ENTRY entry;
+ flow_t flow;
NTSTATUS status;
DEBUG("DESTROY: destroying WinDivert context (context=%p)", context);
@@ -2106,6 +2109,12 @@ extern VOID windivert_destroy(IN WDFOBJECT object)
FwpmEngineClose0(context->engine_handle);
}
windivert_free((PVOID)filter);
+ while (!IsListEmpty(&context->flow_set))
+ {
+ entry = RemoveHeadList(&context->flow_set);
+ flow = CONTAINING_RECORD(entry, struct flow_s, entry);
+ windivert_free(flow);
+ }
if (context->process != NULL)
{
ObDereferenceObject(context->process);
@@ -4179,22 +4188,11 @@ static void windivert_flow_established_classify(context_t context,
flow->flow_id = flow_id;
flow->callout_id = callout_id;
flow->layer_id = layer_id;
- flow->inserted = FALSE;
- flow->deleted = FALSE;
flow->outbound = outbound;
flow->loopback = loopback;
flow->ipv6 = !ipv4;
RtlCopyMemory(&flow->data, flow_data, sizeof(flow->data));
- status = FwpsFlowAssociateContext0(flow_id, layer_id, callout_id,
- (UINT64)flow);
- if (!NT_SUCCESS(status))
- {
- windivert_free(flow);
- WdfObjectDereference(object);
- return;
- }
-
KeAcquireInStackQueuedSpinLock(&context->lock, &lock_handle);
if (context->state != WINDIVERT_CONTEXT_STATE_OPEN ||
context->shutdown_recv)
@@ -4204,19 +4202,16 @@ static void windivert_flow_established_classify(context_t context,
WdfObjectDereference(object);
return;
}
- if (!flow->deleted)
+ status = FwpsFlowAssociateContext0(flow_id, layer_id, callout_id,
+ (UINT64)flow);
+ if (!NT_SUCCESS(status))
{
- InsertTailList(&context->flow_set, &flow->entry);
- flow->inserted = TRUE;
- }
- else
- {
- // Flow was deleted before insertion; we are responsible for cleanup.
KeReleaseInStackQueuedSpinLock(&lock_handle);
windivert_free(flow);
WdfObjectDereference(object);
return;
}
+ InsertTailList(&context->flow_set, &flow->entry);
KeReleaseInStackQueuedSpinLock(&lock_handle);
}
@@ -4243,18 +4238,16 @@ static void windivert_flow_delete_notify(UINT16 layer_id, UINT32 callout_id,
{
return;
}
-
timestamp = KeQueryPerformanceCounter(NULL).QuadPart;
context = flow->context;
KeAcquireInStackQueuedSpinLock(&context->lock, &lock_handle);
object = (WDFOBJECT)context->object; // referenced in flow_established.
- if (flow->inserted && !flow->deleted)
+ cleanup = (context->state == WINDIVERT_CONTEXT_STATE_OPEN);
+ if (cleanup)
{
RemoveEntryList(&flow->entry);
}
- flow->deleted = TRUE;
- cleanup = flow->inserted;
if (context->state != WINDIVERT_CONTEXT_STATE_OPEN ||
context->shutdown_recv)
{
@@ -4279,12 +4272,12 @@ static void windivert_flow_delete_notify(UINT16 layer_id, UINT32 callout_id,
}
windivert_flow_delete_notify_exit:
-
if (cleanup)
{
+ // If context->state != OPEN, then destroy() will free the flow.
windivert_free(flow);
- WdfObjectDereference(object);
}
+ WdfObjectDereference(object);
}
/*
From 1789526ecfb9ff5397c94f9f54c1a3dc2fb60440 Mon Sep 17 00:00:00 2001
From: basil00
Date: Sat, 17 Sep 2022 10:32:57 +0800
Subject: [PATCH 11/11] Bump version to 2.2.2 & other fixups
---
CHANGELOG | 6 ++++++
README | 2 +-
VERSION | 2 +-
doc/windivert.html | 2 +-
inf/windivert32.inf | 2 +-
inf/windivert64.inf | 2 +-
6 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index bab7d43..bb7a27a 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -312,3 +312,9 @@ WinDivert 2.2.0
- Implement new packet parser that correctly handles IP fragments.
- Add a new "fragment" filter field that matches IP fragments.
- (Un)Loading the WinDivert driver will cause a system event to be logged.
+WinDivert 2.2.1
+ - Fix potential driver deadlock on user-mode program crash.
+ - Fix filter language simplification bug.
+ - Fix Flow.EndpointId containing junk data.
+WinDivert 2.2.2
+ - Fix potential WinDivertClose() BSOD for WINDIVERT_LAYER_FLOW handles.
diff --git a/README b/README
index 5dcbc58..14e9055 100644
--- a/README
+++ b/README
@@ -5,7 +5,7 @@ WinDivert 2.2: Windows Packet Divert
---------------
Windows Packet Divert (WinDivert) is a user-mode packet interception library
-for Windows 7, Windows 8 and Windows 10.
+for Windows 10, Windows 11, and Windows Server.
WinDivert enables user-mode capturing/modifying/dropping of network packets
sent to/from the Windows network stack. In summary, WinDivert can:
diff --git a/VERSION b/VERSION
index c043eea..b1b25a5 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.2.1
+2.2.2
diff --git a/doc/windivert.html b/doc/windivert.html
index eab15d9..85a870a 100644
--- a/doc/windivert.html
+++ b/doc/windivert.html
@@ -72,7 +72,7 @@
WinDivert is a powerful user-mode
capture/sniffing/modification/blocking/re-injection package for
-Windows 7, Windows 8 and Windows 10.
+Windows 10, Windows 11, and Windows Server.
WinDivert can be used to implement user-mode packet filters, packet sniffers,
firewalls, NAT, VPNs, tunneling applications, etc., without the need to
write kernel-mode code.
diff --git a/inf/windivert32.inf b/inf/windivert32.inf
index 08b1aba..031e7df 100644
--- a/inf/windivert32.inf
+++ b/inf/windivert32.inf
@@ -4,7 +4,7 @@ Class = WFPCALLOUTS
ClassGuid = {57465043-616C-6C6F-7574-5F636C617373}
Provider = %Basil%
CatalogFile = WinDivert32.Cat
-DriverVer = 01/08/2022,2.2.1
+DriverVer = 01/09/2022,2.2.2
[SourceDisksNames]
1 = %DiskName%
diff --git a/inf/windivert64.inf b/inf/windivert64.inf
index 33888f0..014ef36 100644
--- a/inf/windivert64.inf
+++ b/inf/windivert64.inf
@@ -4,7 +4,7 @@ Class = WFPCALLOUTS
ClassGuid = {57465043-616C-6C6F-7574-5F636C617373}
Provider = %Basil%
CatalogFile = WinDivert64.Cat
-DriverVer = 01/08/2022,2.2.1
+DriverVer = 01/09/2022,2.2.2
[SourceDisksNames]
1 = %DiskName%
|