xdp-for-windows icon indicating copy to clipboard operation
xdp-for-windows copied to clipboard

Use after free from offload handles to LWF detach

Open mtfriesen opened this issue 2 years ago • 0 comments

There's nothing preventing the LWF detach from completing while the InterfaceSet is still referenced (only individual Interface references prevent detaching) which allows the LWF filter object to be deleted while an offload context on that InterfaceSet is being created. It looks like XdpLwfOpenInterfaceOffloadHandle attempted to avoid this issue by checking whether Filter->NdisFilterHandle is NULL, but Filter itself can be freed by this point.

This could be fixed by adding reference count protection to the InterfaceSet itself.

1: kd> kn
 # Child-SP          RetAddr               Call Site
00 ffffaf80`75d46598 fffff803`d161c4e4     nt!KeBugCheckEx [d:\rs1\minkernel\ntos\ke\amd64\procstat.asm @ 127] 
01 ffffaf80`75d465a0 fffff803`d1657004     nt!MiSystemFault+0xfb4 [d:\rs1\minkernel\ntos\mm\mmfault.c @ 4460] 
02 ffffaf80`75d46690 fffff803`d1771a61     nt!MmAccessFault+0x254 [d:\rs1\minkernel\ntos\mm\mmfault.c @ 6347] 
03 ffffaf80`75d46890 fffff80d`43d210ae     nt!KiPageFault+0x321 [d:\rs1\minkernel\ntos\ke\amd64\trap.asm @ 1278] 
04 ffffaf80`75d46a20 fffff80d`43d211b8     xdp!RtlpCheckListEntry+0xe [C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\km\wdm.h @ 12831] 
05 ffffaf80`75d46a50 fffff80d`43d5695c     xdp!InsertTailList+0x18 [C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\km\wdm.h @ 12942] 
06 ffffaf80`75d46a90 fffff80d`43d247dd     xdp!XdpLwfOpenInterfaceOffloadHandle+0x42c [D:\a\1\s\src\xdplwf\offload.c @ 1245] 
07 ffffaf80`75d46b20 fffff80d`43d2ec2b     xdp!XdpIfOpenInterfaceOffloadHandle+0x4d [D:\a\1\s\src\xdp\bind.c @ 710] 
08 ffffaf80`75d46b60 fffff80d`43d2a79b     xdp!XdpIrpCreateInterface+0x38b [D:\a\1\s\src\xdp\offload.c @ 397] 
09 ffffaf80`75d46c40 fffff80d`43d6c9fd     xdp!XdpIrpCreate+0x1eb [D:\a\1\s\src\xdp\dispatch.c @ 137] 
0a ffffaf80`75d46cf0 fffff80d`4175bf06     xdp!XdpIrpDispatch+0xcd [D:\a\1\s\src\xdp\dispatch.c @ 205] 
0b ffffaf80`75d46d40 fffff803`d1d05d26     VerifierExt!xdv_IRP_MJ_CREATE_wrapper+0xc6 [d:\rs1\minkernel\verifier\xdv\rules\group_x64.c @ 16966] 
0c ffffaf80`75d46d90 fffff803`d1679be2     nt!IovCallDriver+0x252 [d:\rs1\minkernel\ntos\io\iomgr\ioverifier.c @ 573] 
0d ffffaf80`75d46dd0 fffff803`d1a1240f     nt!IofCallDriver+0x72 [d:\rs1\minkernel\ntos\io\iomgr\iosubs.c @ 3038] 
0e (Inline Function) --------`--------     nt!IoCallDriverWithTracing+0xbd [d:\rs1\minkernel\ntos\io\iomgr\iomgr.h @ 1051] 
0f ffffaf80`75d46e10 fffff803`d1a2e8af     nt!IopParseDevice+0x172f [d:\rs1\minkernel\ntos\io\iomgr\parse.c @ 2986] 
10 ffffaf80`75d47000 fffff803`d1a23ccd     nt!ObpLookupObjectName+0x8af [d:\rs1\minkernel\ntos\ob\obdir.c @ 2556] 
11 ffffaf80`75d471d0 fffff803`d1a4e330     nt!ObOpenObjectByNameEx+0x1dd [d:\rs1\minkernel\ntos\ob\obref.c @ 1011] 
12 ffffaf80`75d47310 fffff803`d1a4dab9     nt!IopCreateFile+0x860 [d:\rs1\minkernel\ntos\io\iomgr\iosubs.c @ 6560] 
13 ffffaf80`75d473c0 fffff803`d1774503     nt!NtCreateFile+0x79 [d:\rs1\minkernel\ntos\io\iomgr\create.c @ 119] 
14 ffffaf80`75d47450 00007ffd`001f6724     nt!KiSystemServiceCopyEnd+0x13 [d:\rs1\minkernel\ntos\ke\amd64\trap.asm @ 2885] 
15 000000db`bf8ff638 00000000`00000000     0x00007ffd`001f6724
1: kd> .frame a
0a ffffaf80`75d46cf0 fffff80d`4175bf06     xdp!XdpIrpDispatch+0xcd [D:\a\1\s\src\xdp\dispatch.c @ 205] 
1: kd> dv
   DeviceObject = 0xffff8e80`e13a7400 Device for "\Driver\xdp"
            Irp = 0xffffed8e`bcab6ea0
          IrpSp = 0xffffed8e`bcab6f70 IRP_MJ_CREATE / 0x0 for Device for "\Driver\xdp"
         Status = 0n0
1: kd> .f-
09 ffffaf80`75d46c40 fffff80d`43d6c9fd     xdp!XdpIrpCreate+0x1eb [D:\a\1\s\src\xdp\dispatch.c @ 137] 
1: kd> dv
            Irp = 0xffffed8e`bcab6ea0
          IrpSp = 0xffffed8e`bcab6f70 IRP_MJ_CREATE / 0x0 for Device for "\Driver\xdp"
    Disposition = 0x02 ''
 ExpectedEaName = struct _STRING "XdpOpenPacket000"
   ActualEaName = struct _STRING "XdpOpenPacket000"
  CreateRoutine = 0xfffff80d`43d2e8a0
         Status = 0n-2035
     OpenPacket = 0xffff8e80`dcf6c939
       EaBuffer = 0xffff8e80`dcf6c920
1: kd> .f-
08 ffffaf80`75d46b60 fffff80d`43d2a79b     xdp!XdpIrpCreateInterface+0x38b [D:\a\1\s\src\xdp\offload.c @ 397] 
1: kd> dv
                   Irp = 0xffffed8e`bcab6ea0
                 IrpSp = 0xffffed8e`bcab6f70 IRP_MJ_CREATE / 0x0 for Device for "\Driver\xdp"
           Disposition = 0x02 ''
           InputBuffer = 0xffff8e80`dcf6c941
     InputBufferLength = 4
                HookId = struct _XDP_HOOK_ID
           IfSetHandle = 0xffffed8e`baa28fc0
InterfaceOffloadHandle = 0x00000000`00000000
                Params = 0xffff8e80`dcf6c941
                Status = 0n8064
       InterfaceObject = 0x00000000`00000000
1: kd> .f-
07 ffffaf80`75d46b20 fffff80d`43d2ec2b     xdp!XdpIfOpenInterfaceOffloadHandle+0x4d [D:\a\1\s\src\xdp\bind.c @ 710] 
1: kd> dv
           IfSetHandle = 0xffffed8e`baa28fc0
                HookId = 0xffffaf80`75d46c18
InterfaceOffloadHandle = 0xffffaf80`75d46c10
                 IfSet = 0xffffed8e`baa28fc0
1: kd> dt IfSetHandle
Local var @ 0xffffaf8075d46b60 Type _XDP_IFSET_HANDLE*
0xffffed8e`baa28fc0 
1: kd> dt XDP_INTERFACE_SET 0xffffed8e`baa28fc0 
   +0x000 Link             : _LIST_ENTRY [ 0xfffff80d`43d67708 - 0xffffed8e`bab1cfc0 ]
   +0x010 IfIndex          : 0x12
   +0x018 ReferenceCount   : 0n1
   +0x020 OffloadDispatch  : 0xfffff80d`43d65610 _XDP_OFFLOAD_DISPATCH
   +0x028 XdpIfInterfaceSetContext : 0xffffed8e`bc6d2dd0 Void
   +0x030 Interfaces       : [2] (null) 
1: kd> .f-
06 ffffaf80`75d46a90 fffff80d`43d247dd     xdp!XdpLwfOpenInterfaceOffloadHandle+0x42c [D:\a\1\s\src\xdplwf\offload.c @ 1245] 
1: kd> dv
                Filter = 0xffffed8e`bc6d2dd0
                HookId = 0xffffaf80`75d46c18
InterfaceOffloadHandle = 0xffffaf80`75d46c10
        OffloadContext = 0xffffed8e`bcbfcfd0
                Status = 0n-516262912
1: kd> dt Filter
Local var @ 0xffffaf8075d46b20 Type _XDP_LWF_FILTER*
0xffffed8e`bc6d2dd0 
   +0x000 NdisFilterHandle : ???? 
   +0x008 MiniportIfIndex  : ??
   +0x00c NdisState        : ??
   +0x010 ReferenceCount   : ??
   +0x018 XdpIfInterfaceSetHandle : ???? 
   +0x020 Offload          : _XDP_LWF_OFFLOAD
   +0x060 OidWorkerRequest : ???? 
   +0x068 OidWorker        : ???? 
   +0x070 Generic          : _XDP_LWF_GENERIC
   +0x1d0 Native           : _XDP_LWF_NATIVE
Memory read error ffffed8ebc6d2e38
1: kd> !pool 0xffffed8e`bc6d2dd0 
Pool page ffffed8ebc6d2dd0 region is Special pool
ffffed8ebc6d2000: Unable to get contents of special pool block
1: kd> !verifier 0x20 0xffffed8e`bc6d2dd0 
Incorrect command options. Please check the correct syntax for the command.
1: kd> !verifier 0x80 0xffffed8e`bc6d2dd0 

Log of recent kernel pool Allocate and Free operations:

There are up to 0x10000 entries in the log.

Parsing 0x0000000000010000 log entries, searching for address 0xffffed8ebc6d2dd0.


======================================================================
Pool block ffffed8ebc6d2dd0, Size 0000000000000230, Thread ffff8e80dbf29800
fffff803d1d159c5 nt!VfFreePoolNotification+0x5d
fffff803d1830e39 nt!ExpFreePoolChecks+0x81
fffff803d1859b5b nt!ExFreePoolWithTag+0x17db
fffff80d41758de0 VerifierExt!ExFreePoolWithTag_wrapper+0x10
fffff803d1d07434 nt!VerifierExFreePoolWithTag+0x44
fffff80d43d4f701 xdp!XdpLwfDereferenceFilter+0x31
fffff80d43d503d0 xdp!XdpLwfFilterDetach+0x260
fffff80d41e0dd0f NDIS!ndisFInvokeDetach+0x2f
fffff80d41e57c26 NDIS!ndisDetachFilterInner+0x146
fffff80d41e0db65 NDIS!ndisDetachFilter+0x61
fffff80d41e1600d NDIS!Ndis::BindEngine::Iterate+0x71d
fffff80d41e1589c NDIS!Ndis::BindEngine::UpdateBindings+0x44
fffff80d41e0d228 NDIS!Ndis::BindEngine::DispatchPendingWork+0x44

Finished parsing all pool tracking information.

mtfriesen avatar Sep 28 '22 21:09 mtfriesen