From e523392c2c091f53c18edf2086d6966eec38561f Mon Sep 17 00:00:00 2001 From: Daniel Willmann Date: Tue, 25 Dec 2012 23:15:50 +0100 Subject: lapd: Check in rslms_rx_rll() if lapdm context was initialized earlier This was found while implementing handover on a sysmobts. When we receive a channel release request for a channel that was never really activated (set_lapdm_context() was not called) we segfault in lapd_recv_dlsap(). We now return early with -EINVAL in rslms_rx_rll() if we receive a message that assumes set_lapdm_context() was already called. These are: * RSL_MT_UNIT_DATA_REQ * RSL_MT_DATA_REQ * RSL_MT_SUSP_REQ * RSL_MT_REL_REQ A test case was added to trigger the issue. --- src/gsm/lapdm.c | 20 ++++++++++++++++++-- tests/lapd/lapd_test.c | 43 +++++++++++++++++++++++++++++++++++++++++++ tests/lapd/lapd_test.ok | 1 + 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/src/gsm/lapdm.c b/src/gsm/lapdm.c index 1c08113e..2bda48ae 100644 --- a/src/gsm/lapdm.c +++ b/src/gsm/lapdm.c @@ -1069,8 +1069,24 @@ static int rslms_rx_rll(struct msgb *msg, struct lapdm_channel *lc) return -EINVAL; } - LOGP(DLLAPD, LOGL_INFO, "(%p) RLL Message '%s' received. (sapi %d)\n", - lc->name, rsl_msg_name(msg_type), sapi); + switch (msg_type) { + case RSL_MT_UNIT_DATA_REQ: + case RSL_MT_DATA_REQ: + case RSL_MT_SUSP_REQ: + case RSL_MT_REL_REQ: + /* This is triggered in abnormal error conditions where + * set_lapdm_context() was not called for the channel earlier. */ + if (!dl->dl.lctx.dl) { + LOGP(DLLAPD, LOGL_NOTICE, "(%p) RLL Message '%s' received without LAPDm context. (sapi %d)\n", + lc->name, rsl_msg_name(msg_type), sapi); + msgb_free(msg); + return -EINVAL; + } + break; + default: + LOGP(DLLAPD, LOGL_INFO, "(%p) RLL Message '%s' received. (sapi %d)\n", + lc->name, rsl_msg_name(msg_type), sapi); + } switch (msg_type) { case RSL_MT_UNIT_DATA_REQ: diff --git a/tests/lapd/lapd_test.c b/tests/lapd/lapd_test.c index d58bec65..2dabbc6d 100644 --- a/tests/lapd/lapd_test.c +++ b/tests/lapd/lapd_test.c @@ -81,6 +81,10 @@ static const uint8_t dummy1[] = { 0xab, 0x03, 0x30, 0x60, 0x06, }; +static const uint8_t rel_req[] = { + 0x02, 0x07, 0x01, 0x0a, 0x02, 0x40, 0x14, 0x01 +}; + static struct msgb *create_cm_serv_req(void) { struct msgb *msg; @@ -122,6 +126,16 @@ static struct msgb *create_dummy_data_req(void) return msg; } +static struct msgb *create_rel_req(void) +{ + struct msgb *msg; + + msg = msgb_from_array(rel_req, sizeof(rel_req)); + msg->l2h = msg->data; + msg->l3h = msg->l2h + sizeof(struct abis_rsl_rll_hdr); + return msg; +} + static int send(struct msgb *in_msg, struct lapdm_channel *chan) { struct osmo_phsap_prim pp; @@ -308,11 +322,40 @@ static void test_lapdm_polling() lapdm_channel_exit(&ms_to_bts_channel); } +static void test_lapdm_early_release() +{ + printf("I test RF channel release of an unestablished channel.\n"); + + int rc; + struct lapdm_polling_state test_state; + + /* Configure LAPDm on both sides */ + struct lapdm_channel bts_to_ms_channel; + memset(&bts_to_ms_channel, 0, sizeof(bts_to_ms_channel)); + + memset(&test_state, 0, sizeof(test_state)); + test_state.bts = &bts_to_ms_channel; + + /* BTS to MS in polling mode */ + lapdm_channel_init(&bts_to_ms_channel, LAPDM_MODE_BTS); + lapdm_channel_set_flags(&bts_to_ms_channel, LAPDM_ENT_F_POLLING_ONLY); + lapdm_channel_set_l1(&bts_to_ms_channel, NULL, &test_state); + lapdm_channel_set_l3(&bts_to_ms_channel, bts_to_ms_tx_cb, &test_state); + + /* Send the release request */ + rc = lapdm_rslms_recvmsg(create_rel_req(), &bts_to_ms_channel); + ASSERT(rc == -EINVAL); + + /* clean up */ + lapdm_channel_exit(&bts_to_ms_channel); +} + int main(int argc, char **argv) { osmo_init_logging(&info); test_lapdm_polling(); + test_lapdm_early_release(); printf("Success.\n"); return 0; diff --git a/tests/lapd/lapd_test.ok b/tests/lapd/lapd_test.ok index d67a0a80..f1b990ea 100644 --- a/tests/lapd/lapd_test.ok +++ b/tests/lapd/lapd_test.ok @@ -17,4 +17,5 @@ Sending back to BTS ms_to_bts_l1_cb: MS(us) -> BTS prim message bts_to_ms_tx_cb: MS->BTS(us) message 14 BTS: Verifying dummy message. +I test RF channel release of an unestablished channel. Success. -- cgit v1.2.3