laforge has submitted this change. ( https://gerrit.osmocom.org/c/osmocom-bb/+/35576?usp=email )
Change subject: mobile: always check return value of tlv_parse() ......................................................................
mobile: always check return value of tlv_parse()
Change-Id: Id02fc0b1af6da939cb72f327c7d2ddca484ca063 --- M src/host/layer23/src/mobile/gsm480_ss.c M src/host/layer23/src/mobile/gsm48_cc.c M src/host/layer23/src/mobile/gsm48_mm.c M src/host/layer23/src/mobile/gsm48_rr.c 4 files changed, 143 insertions(+), 64 deletions(-)
Approvals: pespin: Looks good to me, but someone else must approve Jenkins Builder: Verified laforge: Looks good to me, approved
diff --git a/src/host/layer23/src/mobile/gsm480_ss.c b/src/host/layer23/src/mobile/gsm480_ss.c index 4ed8354..fe601bc 100644 --- a/src/host/layer23/src/mobile/gsm480_ss.c +++ b/src/host/layer23/src/mobile/gsm480_ss.c @@ -1062,7 +1062,12 @@ struct tlv_parsed tp; int rc = 0;
- tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0); + if (tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0) < 0) { + LOGP(DSS, LOGL_ERROR, "%s(): tlv_parse() failed\n", __func__); + gsm480_trans_free(trans); + return -EINVAL; + } + if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { rc = gsm480_rx_fac_ie(trans, TLVP_VAL(&tp, GSM48_IE_FACILITY), *(TLVP_VAL(&tp, GSM48_IE_FACILITY)-1)); @@ -1095,11 +1100,16 @@ struct tlv_parsed tp; int rc = 0;
+ if (tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, + GSM48_IE_FACILITY, 0) < 0) { + LOGP(DSS, LOGL_ERROR, "%s(): tlv_parse() failed\n", __func__); + /* XXX: indicate an error somehow */ + return -EINVAL; + } + /* go register state */ trans->ss.state = GSM480_SS_ST_ACTIVE;
- tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, - GSM48_IE_FACILITY, 0); if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { rc = gsm480_rx_fac_ie(trans, TLVP_VAL(&tp, GSM48_IE_FACILITY), *(TLVP_VAL(&tp, GSM48_IE_FACILITY)-1)); @@ -1127,10 +1137,15 @@ struct tlv_parsed tp; int rc = 0;
+ if (tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0) < 0) { + LOGP(DSS, LOGL_ERROR, "%s(): tlv_parse() failed\n", __func__); + /* XXX: indicate an error somehow */ + return -EINVAL; + } + /* go register state */ trans->ss.state = GSM480_SS_ST_ACTIVE;
- tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0); if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { rc = gsm480_rx_fac_ie(trans, TLVP_VAL(&tp, GSM48_IE_FACILITY), *(TLVP_VAL(&tp, GSM48_IE_FACILITY)-1)); diff --git a/src/host/layer23/src/mobile/gsm48_cc.c b/src/host/layer23/src/mobile/gsm48_cc.c index 4e26713..c3ec94b 100644 --- a/src/host/layer23/src/mobile/gsm48_cc.c +++ b/src/host/layer23/src/mobile/gsm48_cc.c @@ -623,10 +623,14 @@
LOGP(DCC, LOGL_INFO, "received PROGRESS\n");
+ if (tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, + GSM48_IE_PROGR_IND, 0) < 0) { + LOGP(DCC, LOGL_ERROR, "%s(): tlv_parse() failed\n", __func__); + return -EINVAL; + } + memset(&progress, 0, sizeof(struct gsm_mncc)); progress.callref = trans->callref; - tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, - GSM48_IE_PROGR_IND, 0); /* progress */ if (TLVP_PRESENT(&tp, GSM48_IE_PROGR_IND)) { progress.fields |= MNCC_F_PROGRESS; @@ -654,13 +658,17 @@ struct tlv_parsed tp; struct gsm_mncc call_proc;
- LOGP(DCC, LOGL_INFO, "sending CALL PROCEEDING\n"); + LOGP(DCC, LOGL_INFO, "received CALL PROCEEDING\n"); + + if (tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0) < 0) { + LOGP(DCC, LOGL_ERROR, "%s(): tlv_parse() failed\n", __func__); + return -EINVAL; + }
gsm48_stop_cc_timer(trans);
memset(&call_proc, 0, sizeof(struct gsm_mncc)); call_proc.callref = trans->callref; - tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0); #if 0 /* repeat */ if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_CIR)) @@ -712,12 +720,16 @@
LOGP(DCC, LOGL_INFO, "received ALERTING\n");
+ if (tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0) < 0) { + LOGP(DCC, LOGL_ERROR, "%s(): tlv_parse() failed\n", __func__); + return -EINVAL; + } + gsm48_stop_cc_timer(trans); /* no T301 in MS call control */
memset(&alerting, 0, sizeof(struct gsm_mncc)); alerting.callref = trans->callref; - tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0); /* facility */ if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { alerting.fields |= MNCC_F_FACILITY; @@ -753,11 +765,15 @@
LOGP(DCC, LOGL_INFO, "received CONNECT\n");
+ if (tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0) < 0) { + LOGP(DCC, LOGL_ERROR, "%s(): tlv_parse() failed\n", __func__); + return -EINVAL; + } + gsm48_stop_cc_timer(trans);
memset(&connect, 0, sizeof(struct gsm_mncc)); connect.callref = trans->callref; - tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0); /* facility */ if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { connect.fields |= MNCC_F_FACILITY; @@ -823,10 +839,13 @@
LOGP(DCC, LOGL_INFO, "received SETUP\n");
+ if (tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0) < 0) { + LOGP(DCC, LOGL_ERROR, "%s(): tlv_parse() failed\n", __func__); + return -EINVAL; + } + memset(&setup, 0, sizeof(struct gsm_mncc)); setup.callref = trans->callref; - tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0); - /* bearer capability */ if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) { setup.fields |= MNCC_F_BEARER_CAP; @@ -1076,9 +1095,13 @@
LOGP(DCC, LOGL_INFO, "received START DTMF ACKNOWLEDGE\n");
+ if (tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0) < 0) { + LOGP(DCC, LOGL_ERROR, "%s(): tlv_parse() failed\n", __func__); + return -EINVAL; + } + memset(&dtmf, 0, sizeof(struct gsm_mncc)); dtmf.callref = trans->callref; - tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0); /* keypad facility */ if (TLVP_PRESENT(&tp, GSM48_IE_KPD_FACILITY)) { dtmf.fields |= MNCC_F_KEYPAD; @@ -1139,9 +1162,13 @@
LOGP(DCC, LOGL_INFO, "received STOP DTMF ACKNOWLEDGE\n");
+ if (tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0) < 0) { + LOGP(DCC, LOGL_ERROR, "%s(): tlv_parse() failed\n", __func__); + return -EINVAL; + } + memset(&dtmf, 0, sizeof(struct gsm_mncc)); dtmf.callref = trans->callref; - tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0);
return mncc_recvmsg(trans->ms, trans, MNCC_STOP_DTMF_RSP, &dtmf); } @@ -1335,15 +1362,18 @@
LOGP(DCC, LOGL_INFO, "received USERINFO\n");
- memset(&user, 0, sizeof(struct gsm_mncc)); - user.callref = trans->callref; if (payload_len < 1) { - LOGP(DCC, LOGL_NOTICE, "Short read of userinfo message " - "error.\n"); + LOGP(DCC, LOGL_NOTICE, "Short read of USERINFO message\n"); return -EINVAL; } - tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, - GSM48_IE_USER_USER, 0); + if (tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, + GSM48_IE_USER_USER, 0) < 0) { + LOGP(DCC, LOGL_ERROR, "%s(): tlv_parse() failed\n", __func__); + return -EINVAL; + } + + memset(&user, 0, sizeof(struct gsm_mncc)); + user.callref = trans->callref; /* user-user */ gsm48_decode_useruser(&user.useruser, TLVP_VAL(&tp, GSM48_IE_USER_USER)-1); @@ -1417,17 +1447,20 @@
LOGP(DCC, LOGL_INFO, "received MODIFY REJECT\n");
+ if (payload_len < 1) { + LOGP(DCC, LOGL_NOTICE, "Short read of MODIFY REJECT message\n"); + return -EINVAL; + } + if (tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, + GSM48_IE_BEARER_CAP, GSM48_IE_CAUSE) < 0) { + LOGP(DCC, LOGL_ERROR, "%s(): tlv_parse() failed\n", __func__); + return -EINVAL; + } + gsm48_stop_cc_timer(trans);
memset(&modify, 0, sizeof(struct gsm_mncc)); modify.callref = trans->callref; - if (payload_len < 1) { - LOGP(DCC, LOGL_NOTICE, "Short read of modify reject message " - "error.\n"); - return -EINVAL; - } - tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, - GSM48_IE_BEARER_CAP, GSM48_IE_CAUSE); /* bearer capability */ if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) { modify.fields |= MNCC_F_BEARER_CAP; @@ -1675,14 +1708,18 @@
LOGP(DCC, LOGL_INFO, "received DISCONNECT\n");
+ if (tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, + GSM48_IE_CAUSE, 0) < 0) { + LOGP(DCC, LOGL_ERROR, "%s(): tlv_parse() failed\n", __func__); + return -EINVAL; + } + gsm48_stop_cc_timer(trans);
new_cc_state(trans, GSM_CSTATE_DISCONNECT_IND);
memset(&disc, 0, sizeof(struct gsm_mncc)); disc.callref = trans->callref; - tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, - GSM48_IE_CAUSE, 0); /* cause */ if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) { disc.fields |= MNCC_F_CAUSE; @@ -1724,11 +1761,15 @@
LOGP(DCC, LOGL_INFO, "received RELEASE\n");
+ if (tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0) < 0) { + LOGP(DCC, LOGL_ERROR, "%s(): tlv_parse() failed\n", __func__); + return -EINVAL; + } + gsm48_stop_cc_timer(trans);
memset(&rel, 0, sizeof(struct gsm_mncc)); rel.callref = trans->callref; - tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0); /* cause */ if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) { rel.fields |= MNCC_F_CAUSE; @@ -1793,11 +1834,15 @@
LOGP(DCC, LOGL_INFO, "received RELEASE COMPLETE\n");
+ if (tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0) < 0) { + LOGP(DCC, LOGL_ERROR, "%s(): tlv_parse() failed\n", __func__); + return -EINVAL; + } + gsm48_stop_cc_timer(trans);
memset(&rel, 0, sizeof(struct gsm_mncc)); rel.callref = trans->callref; - tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0); /* cause */ if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) { rel.fields |= MNCC_F_CAUSE; diff --git a/src/host/layer23/src/mobile/gsm48_mm.c b/src/host/layer23/src/mobile/gsm48_mm.c index 378cd2d..16a9b07 100644 --- a/src/host/layer23/src/mobile/gsm48_mm.c +++ b/src/host/layer23/src/mobile/gsm48_mm.c @@ -2259,11 +2259,13 @@ struct tlv_parsed tp;
if (payload_len < 0) { - LOGP(DMM, LOGL_NOTICE, "Short read of MM INFORMATION message " - "error.\n"); + LOGP(DMM, LOGL_ERROR, "Short read of MM INFORMATION message\n"); return -EINVAL; } - tlv_parse(&tp, &gsm48_mm_att_tlvdef, gh->data, payload_len, 0, 0); + if (tlv_parse(&tp, &gsm48_mm_att_tlvdef, gh->data, payload_len, 0, 0) < 0) { + LOGP(DMM, LOGL_ERROR, "%s(): tlv_parse() failed\n", __func__); + return -EINVAL; + }
/* long name */ if (TLVP_PRESENT(&tp, GSM48_IE_NAME_LONG)) { @@ -2611,15 +2613,17 @@ struct tlv_parsed tp; struct msgb *nmsg;
- if (payload_len < sizeof(struct gsm48_loc_area_id)) { - short_read: - LOGP(DMM, LOGL_NOTICE, "Short read of LOCATION UPDATING ACCEPT " - "message error.\n"); + if (payload_len < 0) { +short_read: + LOGP(DMM, LOGL_ERROR, "Short read of LOCATION UPDATING ACCEPT message\n"); return -EINVAL; } - tlv_parse(&tp, &gsm48_mm_att_tlvdef, - gh->data + sizeof(struct gsm48_loc_area_id), - payload_len - sizeof(struct gsm48_loc_area_id), 0, 0); + if (tlv_parse(&tp, &gsm48_mm_att_tlvdef, + gh->data + sizeof(*lai), + payload_len - sizeof(*lai), 0, 0) < 0) { + LOGP(DMM, LOGL_ERROR, "%s(): tlv_parse() failed\n", __func__); + return -EINVAL; + }
/* update has finished */ mm->lupd_pending = 0; diff --git a/src/host/layer23/src/mobile/gsm48_rr.c b/src/host/layer23/src/mobile/gsm48_rr.c index 334fdaf..46a143c 100644 --- a/src/host/layer23/src/mobile/gsm48_rr.c +++ b/src/host/layer23/src/mobile/gsm48_rr.c @@ -3642,12 +3642,13 @@ struct tlv_parsed tp;
if (payload_len < 0) { - LOGP(DRR, LOGL_NOTICE, "Short read of ADDITIONAL ASSIGNMENT " - "message.\n"); - return gsm48_rr_tx_rr_status(ms, - GSM48_RR_CAUSE_PROT_ERROR_UNSPC); + LOGP(DRR, LOGL_NOTICE, "Short read of ADDITIONAL ASSIGNMENT message\n"); + return gsm48_rr_tx_rr_status(ms, GSM48_RR_CAUSE_PROT_ERROR_UNSPC); } - tlv_parse(&tp, &gsm48_rr_att_tlvdef, aa->data, payload_len, 0, 0); + if (tlv_parse(&tp, &gsm48_rr_att_tlvdef, aa->data, payload_len, 0, 0) < 0) { + LOGP(DRR, LOGL_ERROR, "%s(): tlv_parse() failed\n", __func__); + return gsm48_rr_tx_rr_status(ms, GSM48_RR_CAUSE_PROT_ERROR_UNSPC); + }
return gsm48_rr_tx_rr_status(ms, GSM48_RR_CAUSE_PROT_ERROR_UNSPC); } @@ -4338,12 +4339,13 @@ uint8_t *mode;
if (payload_len < 0) { - LOGP(DRR, LOGL_NOTICE, "Short read of CHANNEL RELEASE " - "message.\n"); - return gsm48_rr_tx_rr_status(ms, - GSM48_RR_CAUSE_PROT_ERROR_UNSPC); + LOGP(DRR, LOGL_NOTICE, "Short read of CHANNEL RELEASE message\n"); + return gsm48_rr_tx_rr_status(ms, GSM48_RR_CAUSE_PROT_ERROR_UNSPC); } - tlv_parse(&tp, &gsm48_rr_att_tlvdef, cr->data, payload_len, 0, 0); + if (tlv_parse(&tp, &gsm48_rr_att_tlvdef, cr->data, payload_len, 0, 0) < 0) { + LOGP(DRR, LOGL_ERROR, "%s(): tlv_parse() failed\n", __func__); + return gsm48_rr_tx_rr_status(ms, GSM48_RR_CAUSE_PROT_ERROR_UNSPC); + }
LOGP(DRR, LOGL_INFO, "channel release request with cause 0x%02x\n", cr->rr_cause); @@ -4391,10 +4393,13 @@ struct tlv_parsed tp;
if (payload_len < 0) { - LOGP(DRR, LOGL_NOTICE, "Short read of CHANNEL RELEASE message.\n"); + LOGP(DRR, LOGL_NOTICE, "Short read of CHANNEL RELEASE message\n"); return gsm48_rr_tx_rr_status(ms, GSM48_RR_CAUSE_PROT_ERROR_UNSPC); } - tlv_parse(&tp, &gsm48_rr_att_tlvdef, cr->data, payload_len, 0, 0); + if (tlv_parse(&tp, &gsm48_rr_att_tlvdef, cr->data, payload_len, 0, 0) < 0) { + LOGP(DRR, LOGL_ERROR, "%s(): tlv_parse() failed\n", __func__); + return gsm48_rr_tx_rr_status(ms, GSM48_RR_CAUSE_PROT_ERROR_UNSPC); + }
LOGP(DRR, LOGL_INFO, "CHANNEL RELESE via UI frame with cause 0x%02x\n", cr->rr_cause);
@@ -4715,12 +4720,13 @@ cdb->ind_tx_power = rr->cd_now.ind_tx_power;
if (payload_len < 0) { - LOGP(DRR, LOGL_NOTICE, "Short read of ASSIGNMENT COMMAND " - "message.\n"); - return gsm48_rr_tx_rr_status(ms, - GSM48_RR_CAUSE_PROT_ERROR_UNSPC); + LOGP(DRR, LOGL_NOTICE, "Short read of ASSIGNMENT COMMAND message\n"); + return gsm48_rr_tx_rr_status(ms, GSM48_RR_CAUSE_PROT_ERROR_UNSPC); } - tlv_parse(&tp, &gsm48_rr_att_tlvdef, ac->data, payload_len, 0, 0); + if (tlv_parse(&tp, &gsm48_rr_att_tlvdef, ac->data, payload_len, 0, 0) < 0) { + LOGP(DRR, LOGL_ERROR, "%s(): tlv_parse() failed\n", __func__); + return gsm48_rr_tx_rr_status(ms, GSM48_RR_CAUSE_PROT_ERROR_UNSPC); + }
/* decode channel description (before time) */ if (TLVP_PRESENT(&tp, GSM48_IE_CH_DESC_1_BEFORE)) { @@ -5102,10 +5108,12 @@ cdb->ind_tx_power = rr->cd_now.ind_tx_power;
if (payload_len < 0) { - LOGP(DRR, LOGL_NOTICE, "Short read of HANDOVER COMMAND " - "message.\n"); - return gsm48_rr_tx_rr_status(ms, - GSM48_RR_CAUSE_PROT_ERROR_UNSPC); + LOGP(DRR, LOGL_NOTICE, "Short read of HANDOVER COMMAND message\n"); + return gsm48_rr_tx_rr_status(ms, GSM48_RR_CAUSE_PROT_ERROR_UNSPC); + } + if (tlv_parse(&tp, &gsm48_rr_att_tlvdef, ho->data, payload_len, 0, 0) < 0) { + LOGP(DRR, LOGL_ERROR, "%s(): tlv_parse() failed\n", __func__); + return gsm48_rr_tx_rr_status(ms, GSM48_RR_CAUSE_PROT_ERROR_UNSPC); }
/* cell description */ @@ -5115,8 +5123,6 @@ rr->chan_req_val = ho->ho_ref; rr->chan_req_mask = 0x00;
- tlv_parse(&tp, &gsm48_rr_att_tlvdef, ho->data, payload_len, 0, 0); - /* sync ind */ if (TLVP_PRESENT(&tp, GSM48_IE_SYNC_IND)) { gsm48_decode_sync_ind(rr, (struct gsm48_sync_ind *)