vlr_ciph_result: fix use after free of imeisv
Define the struct vlr_ciph_result member .imeisv not as a char* but a char[] of
appropriate length, to avoid the need to point to external memory.
Thus fix a use-after-free in msc_cipher_mode_compl(), which defined the
imeisv[] buffer in a sub-scope within that function, so that the .imeisv
pointer was already invalid when fed to vlr_subscr_rx_ciph_res().
Did you notice that the commit summary rhymes?
Closes: OS#3053
Change-Id: I90cfb952a7dec6d104200872164ebadb25d0260d
diff --git a/src/libmsc/osmo_msc.c b/src/libmsc/osmo_msc.c
index f6df0d2..323baf9 100644
--- a/src/libmsc/osmo_msc.c
+++ b/src/libmsc/osmo_msc.c
@@ -173,7 +173,6 @@
unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
struct tlv_parsed tp;
uint8_t mi_type;
- char imeisv[GSM48_MI_SIZE] = "";
if (!gh) {
LOGP(DRR, LOGL_ERROR, "invalid: msgb without l3 header\n");
@@ -187,10 +186,9 @@
mi_type = TLVP_VAL(&tp, GSM48_IE_MOBILE_ID)[0] & GSM_MI_TYPE_MASK;
if (mi_type == GSM_MI_TYPE_IMEISV
&& TLVP_LEN(&tp, GSM48_IE_MOBILE_ID) > 0) {
- gsm48_mi_to_string(imeisv, sizeof(imeisv),
+ gsm48_mi_to_string(ciph_res.imeisv, sizeof(ciph_res.imeisv),
TLVP_VAL(&tp, GSM48_IE_MOBILE_ID),
TLVP_LEN(&tp, GSM48_IE_MOBILE_ID));
- ciph_res.imeisv = imeisv;
}
}
}
diff --git a/src/libvlr/vlr_access_req_fsm.c b/src/libvlr/vlr_access_req_fsm.c
index 95a618d..3845f26 100644
--- a/src/libvlr/vlr_access_req_fsm.c
+++ b/src/libvlr/vlr_access_req_fsm.c
@@ -500,7 +500,7 @@
}
- if (res.imeisv) {
+ if (*res.imeisv) {
LOGPFSM(fi, "got IMEISV: %s\n", res.imeisv);
vlr_subscr_set_imeisv(vsub, res.imeisv);
}
diff --git a/src/libvlr/vlr_lu_fsm.c b/src/libvlr/vlr_lu_fsm.c
index c6fd080..9a4a239 100644
--- a/src/libvlr/vlr_lu_fsm.c
+++ b/src/libvlr/vlr_lu_fsm.c
@@ -1165,7 +1165,7 @@
return;
}
- if (res.imeisv) {
+ if (*res.imeisv) {
LOGPFSM(fi, "got IMEISV: %s\n", res.imeisv);
vlr_subscr_set_imeisv(vsub, res.imeisv);
}