diff options
Diffstat (limited to 'src/gb/gprs_bssgp.c')
-rw-r--r-- | src/gb/gprs_bssgp.c | 58 |
1 files changed, 27 insertions, 31 deletions
diff --git a/src/gb/gprs_bssgp.c b/src/gb/gprs_bssgp.c index 2784d0a8..38794c28 100644 --- a/src/gb/gprs_bssgp.c +++ b/src/gb/gprs_bssgp.c @@ -1170,20 +1170,19 @@ int bssgp_tx_dl_ud(struct msgb *msg, uint16_t pdu_lifetime, /* IMSI */ if (dup->imsi && strlen(dup->imsi)) { - struct osmo_mobile_identity mi = { .type = GSM_MI_TYPE_IMSI, }; - OSMO_STRLCPY_ARRAY(mi.imsi, dup->imsi); - msgb_tvl_put(msg, BSSGP_IE_IMSI, osmo_mobile_identity_encoded_len(&mi, NULL)); - if (osmo_mobile_identity_encode_msgb(msg, &mi, false) <= 0) { - if (log_check_level(DBSSGP, LOGL_NOTICE)) { - char strbuf[64]; - osmo_mobile_identity_to_str_buf(strbuf, sizeof(strbuf), &mi); - LOGP(DBSSGP, LOGL_ERROR, - "NSEI=%u/BVCI=%u Cannot encode Mobile Identity %s\n", - nsei, bvci, strbuf); - } - msgb_free(msg); - return -EINVAL; - } + uint8_t mi[GSM48_MID_MAX_SIZE]; +/* gsm48_generate_mid_from_imsi() is guaranteed to never return more than 11, + * but somehow gcc (8.2) is not smart enough to figure this out and claims that + * the memcpy in msgb_tvlv_put() below will cause and out-of-bounds access up to + * mi[131], which is wrong */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warray-bounds" + int imsi_len = gsm48_generate_mid_from_imsi(mi, dup->imsi); + OSMO_ASSERT(imsi_len <= GSM48_MID_MAX_SIZE); + if (imsi_len > 2) + msgb_tvlv_push(msg, BSSGP_IE_IMSI, + imsi_len-2, mi+2); +#pragma GCC diagnostic pop } /* DRX parameters */ @@ -1228,8 +1227,12 @@ int bssgp_tx_paging(uint16_t nsei, uint16_t ns_bvci, struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *) msgb_put(msg, sizeof(*bgph)); uint16_t drx_params = osmo_htons(pinfo->drx_params); + uint8_t mi[GSM48_MID_MAX_SIZE]; + int imsi_len = gsm48_generate_mid_from_imsi(mi, pinfo->imsi); struct gsm48_ra_id ra; - struct osmo_mobile_identity mi; + + if (imsi_len < 2) + return -EINVAL; msgb_nsei(msg) = nsei; msgb_bvci(msg) = ns_bvci; @@ -1238,23 +1241,16 @@ int bssgp_tx_paging(uint16_t nsei, uint16_t ns_bvci, bgph->pdu_type = BSSGP_PDUT_PAGING_PS; else bgph->pdu_type = BSSGP_PDUT_PAGING_CS; - /* IMSI */ - mi = (struct osmo_mobile_identity){ .type = GSM_MI_TYPE_IMSI, }; - OSMO_STRLCPY_ARRAY(mi.imsi, pinfo->imsi); - msgb_tvl_put(msg, BSSGP_IE_IMSI, osmo_mobile_identity_encoded_len(&mi, NULL)); - if (osmo_mobile_identity_encode_msgb(msg, &mi, false) <= 0) { - if (log_check_level(DBSSGP, LOGL_NOTICE)) { - char strbuf[64]; - osmo_mobile_identity_to_str_buf(strbuf, sizeof(strbuf), &mi); - LOGP(DBSSGP, LOGL_ERROR, - "NSEI=%u/BVCI=%u Cannot encode Mobile Identity %s\n", - nsei, ns_bvci, strbuf); - } - msgb_free(msg); - return -EINVAL; - } - +/* gsm48_generate_mid_from_imsi() is guaranteed to never return more than 11, + * but somehow gcc (8.2) is not smart enough to figure this out and claims that + * the memcpy in msgb_tvlv_put() below will cause and out-of-bounds access up to + * mi[131], which is wrong */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warray-bounds" + OSMO_ASSERT(imsi_len <= GSM48_MID_MAX_SIZE); + msgb_tvlv_put(msg, BSSGP_IE_IMSI, imsi_len-2, mi+2); +#pragma GCC diagnostic pop /* DRX Parameters */ msgb_tvlv_put(msg, BSSGP_IE_DRX_PARAMS, 2, (uint8_t *) &drx_params); |