quic: fix reassembly issue for smb2 (and other protocols)

If we did not find an msp that matched the current segment we would
try to find the msp for set-1 instead. This will only work IFF
we do not know the the exact size of the PDU and where it ends,
i.e. DESEGMENT_ONE_MORE_SEGMENT and friends.

In the case where "get msp for seq-1" gives us an msp where we know the exact
PDU boundary and the current seq is beyond the end of that boundary, then
we should not use the msp for seq-1 but instead treat this as a brand new PDU.

This fixes issues with SMB2-over-QUIC dissection that can be seen in the
sample capture for the "add smb2-over-quic" bug where only the first
multi-segment PDU would be dissected correctly for each direction.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
This commit is contained in:
Ronnie Sahlberg 2020-09-26 06:57:31 +10:00
parent c597927da8
commit b9a2d861e4
1 changed files with 19 additions and 3 deletions

View File

@ -1153,6 +1153,14 @@ again:
/* Else, find the most previous PDU starting before this sequence number */
if (!msp && seq > 0) {
msp = (struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(stream->multisegment_pdus, seq-1);
/* Unless if we already fully reassembled the msp that covers seq-1
* and seq is beyond the end of that msp. In that case this segment
* will be the start of a new msp.
*/
if (msp && (msp->flags & MSP_FLAGS_GOT_ALL_SEGMENTS) &&
seq >= msp->nxtpdu) {
msp = NULL;
}
}
{
@ -1196,7 +1204,9 @@ again:
pinfo, reassembly_id, NULL,
seq - msp->seq, len,
nxtseq < msp->nxtpdu);
if (fh) {
msp->flags |= MSP_FLAGS_GOT_ALL_SEGMENTS;
}
if (!PINFO_FD_VISITED(pinfo)
&& msp->flags & MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT) {
msp->flags &= (~MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT);
@ -1234,8 +1244,11 @@ again:
* packet.
*/
if (pinfo->desegment_len) {
if (!PINFO_FD_VISITED(pinfo))
if (!PINFO_FD_VISITED(pinfo)) {
must_desegment = TRUE;
if (msp)
msp->flags &= ~MSP_FLAGS_GOT_ALL_SEGMENTS;
}
/*
* Set "deseg_offset" to the offset in "tvb"
@ -1340,8 +1353,11 @@ again:
// TODO move tree item if needed.
if(pinfo->desegment_len) {
if (!PINFO_FD_VISITED(pinfo))
if (!PINFO_FD_VISITED(pinfo)) {
must_desegment = TRUE;
if (msp)
msp->flags &= ~MSP_FLAGS_GOT_ALL_SEGMENTS;
}
/* See packet-tcp.h for details about this. */
deseg_offset = fh->datalen - pinfo->desegment_offset;
deseg_offset = tvb_reported_length(tvb) - deseg_offset;