Null Dereference in tcpip.sys Leading to Single Packet Denial of Service [CVE-2021-24086]
tl;dr Cleverly crafting a packet with a large header+options length could cause a null dereference. The net buffer would be created with DataSize=uint16_t(length), but it would attempt to read with size=length (no truncation), which would result in an error case and a null return.
NdisGetDataBuffer is used to get a contiguous block of data from a NET_BUFFER structure. When there is an error, it’ll return a null. Ipv6pReassembleDatagram doesn’t account for that so in the error condition it will try to write to the null pointer, crashing the system
Before this call, it’ll calculate the size of the Unfragmentable headers and the ipv6 headers. This value it used when setting up the net buffer, where it is passed into NetioRetreatNetBuffer as a uint16_t, which sets the DataLength.
Then it tries to get the data buffer, with GetDataBuffer, passing in that size as the amount of bytes needed, but it does not truncate the length. So you end up with the NetBuffer->DataLength being less than the needed number of bytes, and a NULL return.
The trick is how do you craft a packet with more than 0xFFFF bytes for the headers. MTU will prevent such packets from being sent on most setups. QuarksLabs post covers this. Basically because of the MTU even fragmented packets are limited in their headers, but if each fragment itself has a fragment header you can cause a recursive reassembly of the packets and get around that, resulting in a packet with more headers than the MTU.