tbf: Avoid keeping poll nodes in pdch_ulc of temporary control_ts used during PACCH assignment

When MS sends us the Packet Resource Request as RRBP from final UL ACK/NACK, we create a new TBF
with a different set of allocated TS. However, we must send the Pkt UL Assignment with information
of the new TBF using that same TS where we receive the Packet Resource Request, which happens to
be the control TS of the previous/old TBF. The original control TS of the new TBF is kept in
tbf->first_common_ts.

Hence the code does gprs_rlcmac_pdch::rcv_resource_request():
"""
ul_tbf->control_ts = ts_no;
"""

And later, when we receive a CTRL ACK answering the Pkt UL Assigment, we change the control TS of
the new TBF back to the new one, by calling tbf_assign_control_ts(), which basically does:
"""
tbf->control_ts = tbf->first_common_ts;
"""

So, for instance we have a TBF which was allocated with tbf->control_ts=4 and hence is only attached
to PDCH 4 (tbf->pdch[]), but for which is temporarily applied tbf->control_ts=7.  Hence, when a poll
is requested, it is done in control_ts, aka 7, which is not in the array of attached PDCH.

The problem is of course if we never reach the point where the final control_ts is set, due to never
receiving the CTRL ACK. If the TBF is freed (due to timer X2001) before receiving the CTRL ACK and
hence tbf_assign_control_ts() is called, a crash may occur, because potentially a poll for the TBF is
left in TS 7 because it's not a PDCH attached to the TBF and hence poll
entries on that TS are not released, hence keeping a pointer to the
freed TBF.

Related: SYS#5647
Change-Id: I0c49f2695e0d932d956c01976c9458eebee63cd4
This commit is contained in:
Pau Espin 2021-10-12 19:52:02 +02:00
parent ffa2918bc5
commit b9fede74ef
1 changed files with 10 additions and 0 deletions

View File

@ -243,6 +243,16 @@ static void tbf_unlink_pdch(struct gprs_rlcmac_tbf *tbf)
{
int ts;
/* During assignment (state=ASSIGN), tbf may be temporarily using
* tbf->control_ts from a previous TBF/SBA to transmit the UL/DL
* Assignment, which may not be necessarly be a TS where the current TBF
* is attached to. Hence, we may have ULC pollings ongoing and we need
* to make sure we drop all reserved nodes there: */
if (tbf_state(tbf) == TBF_ST_ASSIGN &&
tbf->control_ts != TBF_CONTROL_TS_UNSET && !tbf->pdch[tbf->control_ts])
pdch_ulc_release_tbf(tbf->trx->pdch[tbf->control_ts].ulc, tbf);
/* Now simply detach from all attached PDCHs */
for (ts = 0; ts < 8; ts++) {
if (!tbf->pdch[ts])
continue;