Skip to content

Commit 3402f8b

Browse files
committed
Fix #315
1 parent 65bb889 commit 3402f8b

File tree

1 file changed

+27
-34
lines changed

1 file changed

+27
-34
lines changed

sys/windivert.c

+27-34
Original file line numberDiff line numberDiff line change
@@ -273,8 +273,6 @@ struct flow_s
273273
UINT64 flow_id; // WFP flow ID.
274274
UINT32 callout_id; // WFP callout ID.
275275
UINT16 layer_id; // WFP layout ID.
276-
BOOL inserted:1; // Flow inserted into context?
277-
BOOL deleted:1; // Flow deleted from context?
278276
BOOL outbound:1; // Flow is outound?
279277
BOOL loopback:1; // Flow is loopback?
280278
BOOL ipv6:1; // Flow is ipv6?
@@ -1981,17 +1979,20 @@ extern VOID windivert_cleanup(IN WDFFILEOBJECT object)
19811979
context->state = WINDIVERT_CONTEXT_STATE_CLOSING;
19821980
sniff_mode = ((context->flags & WINDIVERT_FLAG_SNIFF) != 0);
19831981
forward = (context->layer == WINDIVERT_LAYER_NETWORK_FORWARD);
1984-
while (!IsListEmpty(&context->flow_set))
1982+
entry = context->flow_set.Flink;
1983+
if (entry != &context->flow_set)
19851984
{
1986-
entry = RemoveHeadList(&context->flow_set);
1987-
flow = CONTAINING_RECORD(entry, struct flow_s, entry);
1988-
flow->deleted = TRUE;
19891985
KeReleaseInStackQueuedSpinLock(&lock_handle);
1990-
status = FwpsFlowRemoveContext0(flow->flow_id, flow->layer_id,
1991-
flow->callout_id);
1992-
if (!NT_SUCCESS(status))
1986+
for (; entry != &context->flow_set; entry = entry->Flink)
19931987
{
1994-
windivert_free(flow);
1988+
flow = CONTAINING_RECORD(entry, struct flow_s, entry);
1989+
status = FwpsFlowRemoveContext0(flow->flow_id, flow->layer_id,
1990+
flow->callout_id);
1991+
if (!NT_SUCCESS(status) && status != STATUS_UNSUCCESSFUL)
1992+
{
1993+
// For STATUS_UNSUCCESSFUL, flow_delete() is still called.
1994+
WdfObjectDereference((WDFOBJECT)object);
1995+
}
19951996
}
19961997
KeAcquireInStackQueuedSpinLock(&context->lock, &lock_handle);
19971998
}
@@ -2086,6 +2087,8 @@ extern VOID windivert_destroy(IN WDFOBJECT object)
20862087
KLOCK_QUEUE_HANDLE lock_handle;
20872088
context_t context = windivert_context_get((WDFFILEOBJECT)object);
20882089
const WINDIVERT_FILTER *filter;
2090+
PLIST_ENTRY entry;
2091+
flow_t flow;
20892092
NTSTATUS status;
20902093

20912094
DEBUG("DESTROY: destroying WinDivert context (context=%p)", context);
@@ -2106,6 +2109,12 @@ extern VOID windivert_destroy(IN WDFOBJECT object)
21062109
FwpmEngineClose0(context->engine_handle);
21072110
}
21082111
windivert_free((PVOID)filter);
2112+
while (!IsListEmpty(&context->flow_set))
2113+
{
2114+
entry = RemoveHeadList(&context->flow_set);
2115+
flow = CONTAINING_RECORD(entry, struct flow_s, entry);
2116+
windivert_free(flow);
2117+
}
21092118
if (context->process != NULL)
21102119
{
21112120
ObDereferenceObject(context->process);
@@ -4179,22 +4188,11 @@ static void windivert_flow_established_classify(context_t context,
41794188
flow->flow_id = flow_id;
41804189
flow->callout_id = callout_id;
41814190
flow->layer_id = layer_id;
4182-
flow->inserted = FALSE;
4183-
flow->deleted = FALSE;
41844191
flow->outbound = outbound;
41854192
flow->loopback = loopback;
41864193
flow->ipv6 = !ipv4;
41874194
RtlCopyMemory(&flow->data, flow_data, sizeof(flow->data));
41884195

4189-
status = FwpsFlowAssociateContext0(flow_id, layer_id, callout_id,
4190-
(UINT64)flow);
4191-
if (!NT_SUCCESS(status))
4192-
{
4193-
windivert_free(flow);
4194-
WdfObjectDereference(object);
4195-
return;
4196-
}
4197-
41984196
KeAcquireInStackQueuedSpinLock(&context->lock, &lock_handle);
41994197
if (context->state != WINDIVERT_CONTEXT_STATE_OPEN ||
42004198
context->shutdown_recv)
@@ -4204,19 +4202,16 @@ static void windivert_flow_established_classify(context_t context,
42044202
WdfObjectDereference(object);
42054203
return;
42064204
}
4207-
if (!flow->deleted)
4208-
{
4209-
InsertTailList(&context->flow_set, &flow->entry);
4210-
flow->inserted = TRUE;
4211-
}
4212-
else
4205+
status = FwpsFlowAssociateContext0(flow_id, layer_id, callout_id,
4206+
(UINT64)flow);
4207+
if (!NT_SUCCESS(status))
42134208
{
4214-
// Flow was deleted before insertion; we are responsible for cleanup.
42154209
KeReleaseInStackQueuedSpinLock(&lock_handle);
42164210
windivert_free(flow);
42174211
WdfObjectDereference(object);
42184212
return;
42194213
}
4214+
InsertTailList(&context->flow_set, &flow->entry);
42204215
KeReleaseInStackQueuedSpinLock(&lock_handle);
42214216
}
42224217

@@ -4243,18 +4238,16 @@ static void windivert_flow_delete_notify(UINT16 layer_id, UINT32 callout_id,
42434238
{
42444239
return;
42454240
}
4246-
42474241
timestamp = KeQueryPerformanceCounter(NULL).QuadPart;
42484242
context = flow->context;
42494243

42504244
KeAcquireInStackQueuedSpinLock(&context->lock, &lock_handle);
42514245
object = (WDFOBJECT)context->object; // referenced in flow_established.
4252-
if (flow->inserted && !flow->deleted)
4246+
cleanup = (context->state == WINDIVERT_CONTEXT_STATE_OPEN);
4247+
if (cleanup)
42534248
{
42544249
RemoveEntryList(&flow->entry);
42554250
}
4256-
flow->deleted = TRUE;
4257-
cleanup = flow->inserted;
42584251
if (context->state != WINDIVERT_CONTEXT_STATE_OPEN ||
42594252
context->shutdown_recv)
42604253
{
@@ -4279,12 +4272,12 @@ static void windivert_flow_delete_notify(UINT16 layer_id, UINT32 callout_id,
42794272
}
42804273

42814274
windivert_flow_delete_notify_exit:
4282-
42834275
if (cleanup)
42844276
{
4277+
// If context->state != OPEN, then destroy() will free the flow.
42854278
windivert_free(flow);
4286-
WdfObjectDereference(object);
42874279
}
4280+
WdfObjectDereference(object);
42884281
}
42894282

42904283
/*

0 commit comments

Comments
 (0)