Commit 8dfb6182 authored by Jaroslava Fiedlerova's avatar Jaroslava Fiedlerova

Merge remote-tracking branch 'origin/bugfix-rlc-fuzzing' into integration_2026_w15 (!4029)

nr rlc: tolerate bogus data

Some unfriendly entity may play with the RLC module and send bogus data to
trigger funky behaviors here and there.

A report sent by Dhanish indentifies one such issue.

From analyzing this report, a possible scenario is the following. Unfriendly
entity sends an RLC PDU with: is_first=0 is_last=0 so=15 lenght of data,
whatever, let's say 1.

This PDU is put in the RX list.

Then later it sends another PDU (for the same SN, obviously), with: is_first=1
is_last=1 so=0 (well, since is_first=1, necessarily so=0; it is not transmitted,
see 38.322 6.2.2.3 for UM and 38.322 6.2.2.4 for AM) length=10, let's say.

This PDU is also put in the RX list, before the previous one.

Then the function sdu_full() returns 1, so reassemble_and_deliver() is called
and the 'while (pdu)' loop is executed for both PDUs. When the second (bogus
one) is processed, so==10 (after processing the first PDU) and the line: int
len = pdu->size - (so - pdu->so) is: int len = 1 - (10 - 15) which is not good.

So we detect the case 'pdu->so > so' and reject the SDU. We could label the
other entity as bogus, since no standard RLC implementation will produce such a
case, but let's remain friendly, even with unfriendly entities. (To be changed
later if needed.)

The problem was reported for RLC AM but is also present in RLC UM. (Not in RLC
TM, where there is no segmentation.) Note: according to the report, this bug was
found using a fuzzer described as 'AI-assisted custom 5G NR protocol fuzzer'. It
had to be said.
parents da44a520 6556c886
......@@ -185,6 +185,12 @@ static void reassemble_and_deliver(nr_rlc_entity_am_t *entity, int sn)
/* reassemble - free 'data' of each segment after processing */
while (pdu != NULL) {
if (pdu->so > so && !bad_sdu) {
/* pdu->so > so is possible when the other end sends bogus data */
LOG_E(RLC, "%s:%d:%s: inconsistent SDU, discarding\n",
__FILE__, __LINE__, __FUNCTION__);
bad_sdu = 1;
}
int len = pdu->size - (so - pdu->so);
if (so + len > NR_SDU_MAX && !bad_sdu) {
LOG_E(RLC, "%s:%d:%s: bad SDU, too big, discarding\n",
......
......@@ -139,6 +139,12 @@ static void reassemble_and_deliver(nr_rlc_entity_um_t *entity, int sn)
/* reassemble - free 'data' of each segment after processing */
while (pdu != NULL && pdu->sn == sn) {
if (pdu->so > so && !bad_sdu) {
/* pdu->so > so is possible when the other end sends bogus data */
LOG_E(RLC, "%s:%d:%s: inconsistent SDU, discarding\n",
__FILE__, __LINE__, __FUNCTION__);
bad_sdu = 1;
}
int len = pdu->size - (so - pdu->so);
if (so + len > NR_SDU_MAX && !bad_sdu) {
LOG_E(RLC, "%s:%d:%s: bad SDU, too big, discarding\n",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment