pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-bsc/+/42010?usp=email )
Change subject: assignment_fsm: Fix use-after-free of lchan->conn ......................................................................
assignment_fsm: Fix use-after-free of lchan->conn
Scenario: * A DYNAMIC/OSMOCOM TS in PDCH mode is selected to be used for TCH/F, hence the TS is being switched to TCH/F: RF Channel Release is being transmitted and waiting to receive RF Channel release ACK. Hence, lchan is in state LCHAN_ST_WAIT_TS_READY, and there's a conn with an assignment FSM pointing to it in conn->assignment.new_lchan. lchan->conn also points to the related conn. * The BSSMAP SCCP link goes down (link lost), which will terminate the conn->fi of all conns related to the MSC peer going down. During that teardown, first gscon_pre_term()->gscon_release_lchans()-> assignment_reset() is called, which sets conn->assignment.new_lchan=NULL and calls lchan_release(). This path leaves conn->assignment.new_lchan->conn untouched! * Later in the call path, when finally the bsc_subscr is put() to 0 references and associated lchan gets its lchan_forget_conn() called, it will access lchan->conn which was not freed in the previous step mentioned above during assignment_reset().
This patch fixes the issue by adding a lchan_forget_conn() after the lchan_release() in assignment_reset(), to make sure the conn is no longer user by the lchan afterwards.
Related: OS#6936 Change-Id: Ifbb9a61cd8a40d953ef5c2b52f9be9ef0dffefa4 --- M src/osmo-bsc/assignment_fsm.c 1 file changed, 1 insertion(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-bsc refs/changes/10/42010/1
diff --git a/src/osmo-bsc/assignment_fsm.c b/src/osmo-bsc/assignment_fsm.c index f0a2781..e5392f6 100644 --- a/src/osmo-bsc/assignment_fsm.c +++ b/src/osmo-bsc/assignment_fsm.c @@ -127,6 +127,7 @@ struct gsm_lchan *lchan = conn->assignment.new_lchan; conn->assignment.new_lchan = NULL; lchan_release(lchan, false, true, RSL_ERR_EQUIPMENT_FAIL, NULL); + lchan_forget_conn(lchan); }
if (conn->assignment.created_ci_for_msc) {