Skip to content

Commit

Permalink
defrag: fix check for complete packet
Browse files Browse the repository at this point in the history
The list of fragments may still contain overlaps, so adding up the
fragment lengths is flawed. Instead track the largest size of
contiguous data that can be re-assembled.

Bug: #6675
(cherry picked from commit d226d0a)
  • Loading branch information
jasonish authored and victorjulien committed Apr 22, 2024
1 parent 1e110d0 commit e626775
Showing 1 changed file with 114 additions and 2 deletions.
116 changes: 114 additions & 2 deletions src/defrag.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,8 @@ Defrag4Reassemble(ThreadVars *tv, DefragTracker *tracker, Packet *p)
goto done;
}
else {
len += frag->data_len;
/* Update the packet length to the largest known data offset. */
len = MAX(len, frag->offset + frag->data_len);
}
}

Expand Down Expand Up @@ -414,7 +415,7 @@ Defrag6Reassemble(ThreadVars *tv, DefragTracker *tracker, Packet *p)
goto done;
}
else {
len += frag->data_len;
len = MAX(len, frag->offset + frag->data_len);
}
}
}
Expand Down Expand Up @@ -3011,6 +3012,115 @@ static int DefragBsdSubsequentOverlapsStartOfOriginalIpv6Test(void)
PASS;
}

/**
* Reassembly should fail.
*
* |0 |8 |16 |24 |32 |40 |48 |
* |========|========|========|========|========|========|========|
* | | |AABBCCDD|AABBDDCC| | | |
* | | | | | |AACCBBDD| |
* | |AACCDDBB|AADDBBCC| | | | |
* |ZZZZZZZZ| | | | | | |
* | | | | | | |DDCCBBAA|
*/
static int DefragBsdMissingFragmentIpv4Test(void)
{
DefragInit();
default_policy = DEFRAG_POLICY_BSD;
Packet *packets[5];

packets[0] = BuildIpv4TestPacketWithContent(
IPPROTO_ICMP, 189, 16 >> 3, 1, (uint8_t *)"AABBCCDDAABBDDCC", 16);

packets[1] =
BuildIpv4TestPacketWithContent(IPPROTO_ICMP, 189, 40 >> 3, 1, (uint8_t *)"AACCBBDD", 8);

packets[2] = BuildIpv4TestPacketWithContent(
IPPROTO_ICMP, 189, 8 >> 3, 1, (uint8_t *)"AACCDDBBAADDBBCC", 16);

/* ICMP header. */
packets[3] = BuildIpv4TestPacketWithContent(IPPROTO_ICMP, 189, 0, 1, (uint8_t *)"ZZZZZZZZ", 8);

packets[4] =
BuildIpv4TestPacketWithContent(IPPROTO_ICMP, 189, 48 >> 3, 0, (uint8_t *)"DDCCBBAA", 8);

Packet *r = Defrag(NULL, NULL, packets[0]);
FAIL_IF_NOT_NULL(r);

r = Defrag(NULL, NULL, packets[1]);
FAIL_IF_NOT_NULL(r);

r = Defrag(NULL, NULL, packets[2]);
FAIL_IF_NOT_NULL(r);

r = Defrag(NULL, NULL, packets[3]);
FAIL_IF_NOT_NULL(r);

r = Defrag(NULL, NULL, packets[4]);
FAIL_IF_NOT_NULL(r);

#if 0
PrintRawDataFp(stdout, GET_PKT_DATA(r) + 20, GET_PKT_LEN(r) - 20);
#endif

for (int i = 0; i < 5; i++) {
SCFree(packets[i]);
}

DefragDestroy();

PASS;
}

static int DefragBsdMissingFragmentIpv6Test(void)
{
DefragInit();
default_policy = DEFRAG_POLICY_BSD;
Packet *packets[5];

packets[0] = BuildIpv6TestPacketWithContent(
IPPROTO_ICMP, 189, 16 >> 3, 1, (uint8_t *)"AABBCCDDAABBDDCC", 16);

packets[1] =
BuildIpv6TestPacketWithContent(IPPROTO_ICMP, 189, 40 >> 3, 1, (uint8_t *)"AACCBBDD", 8);

packets[2] = BuildIpv6TestPacketWithContent(
IPPROTO_ICMP, 189, 8 >> 3, 1, (uint8_t *)"AACCDDBBAADDBBCC", 16);

/* ICMP header. */
packets[3] = BuildIpv6TestPacketWithContent(IPPROTO_ICMP, 189, 0, 1, (uint8_t *)"ZZZZZZZZ", 8);

packets[4] =
BuildIpv6TestPacketWithContent(IPPROTO_ICMP, 189, 48 >> 3, 0, (uint8_t *)"DDCCBBAA", 8);

Packet *r = Defrag(NULL, NULL, packets[0]);
FAIL_IF_NOT_NULL(r);

r = Defrag(NULL, NULL, packets[1]);
FAIL_IF_NOT_NULL(r);

r = Defrag(NULL, NULL, packets[2]);
FAIL_IF_NOT_NULL(r);

r = Defrag(NULL, NULL, packets[3]);
FAIL_IF_NOT_NULL(r);

r = Defrag(NULL, NULL, packets[4]);
FAIL_IF_NOT_NULL(r);

#if 0
PrintRawDataFp(stdout, GET_PKT_DATA(r) + 40, GET_PKT_LEN(r) - 40);
#endif

for (int i = 0; i < 5; i++) {
SCFree(packets[i]);
}

DefragDestroy();

PASS;
}

#endif /* UNITTESTS */

void DefragRegisterTests(void)
Expand Down Expand Up @@ -3059,5 +3169,7 @@ void DefragRegisterTests(void)
DefragBsdSubsequentOverlapsStartOfOriginalIpv6Test);
UtRegisterTest("DefragBsdSubsequentOverlapsStartOfOriginalIpv4Test_2", DefragBsdSubsequentOverlapsStartOfOriginalIpv4Test_2);
UtRegisterTest("DefragBsdSubsequentOverlapsStartOfOriginalIpv6Test_2", DefragBsdSubsequentOverlapsStartOfOriginalIpv6Test_2);
UtRegisterTest("DefragBsdMissingFragmentIpv4Test", DefragBsdMissingFragmentIpv4Test);
UtRegisterTest("DefragBsdMissingFragmentIpv6Test", DefragBsdMissingFragmentIpv6Test);
#endif /* UNITTESTS */
}

0 comments on commit e626775

Please sign in to comment.