gsm48: Add size checks to the paging response mi parsing.

We go from no size checks to some content checking. We should
refactor the whole classmark2 + mi parsing that is used throughout
the code into one place with proper size checking. This is the
start and requires a new libosmocore as well.
diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h
index 74dcbe5..a49f91e 100644
--- a/openbsc/include/openbsc/gsm_04_08.h
+++ b/openbsc/include/openbsc/gsm_04_08.h
@@ -52,7 +52,7 @@
 		      int h_len);
 
 int send_siemens_mrpci(struct gsm_lchan *lchan, u_int8_t *classmark2_lv);
-int gsm48_paging_extract_mi(struct msgb *msg, char *mi_string, u_int8_t *mi_type);
+int gsm48_paging_extract_mi(struct gsm48_pag_resp *pag, int length, char *mi_string, u_int8_t *mi_type);
 int gsm48_handle_paging_resp(struct msgb *msg, struct gsm_subscriber *subscr);
 
 int gsm48_lchan_modify(struct gsm_lchan *lchan, u_int8_t lchan_mode);
diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c
index eecf76f..06e19ac 100644
--- a/openbsc/src/gsm_04_08.c
+++ b/openbsc/src/gsm_04_08.c
@@ -785,13 +785,16 @@
 {
 	struct gsm_bts *bts = msg->lchan->ts->trx->bts;
 	struct gsm48_hdr *gh = msgb_l3(msg);
+	struct gsm48_pag_resp *resp;
 	u_int8_t *classmark2_lv = gh->data + 1;
 	u_int8_t mi_type;
 	char mi_string[GSM48_MI_SIZE];
 	struct gsm_subscriber *subscr = NULL;
 	int rc = 0;
 
-	gsm48_paging_extract_mi(msg, mi_string, &mi_type);
+	resp = (struct gsm48_pag_resp *) &gh->data[0];
+	gsm48_paging_extract_mi(resp, msgb_l3len(msg) - sizeof(*gh),
+				mi_string, &mi_type);
 	DEBUGP(DRR, "PAGING RESPONSE: mi_type=0x%02x MI(%s)\n",
 		mi_type, mi_string);
 
diff --git a/openbsc/src/gsm_04_08_utils.c b/openbsc/src/gsm_04_08_utils.c
index 1b3ed25..db8c3a5 100644
--- a/openbsc/src/gsm_04_08_utils.c
+++ b/openbsc/src/gsm_04_08_utils.c
@@ -243,13 +243,20 @@
 	return rsl_siemens_mrpci(lchan, &mrpci);
 }
 
-int gsm48_paging_extract_mi(struct msgb *msg, char *mi_string, u_int8_t *mi_type)
+int gsm48_paging_extract_mi(struct gsm48_pag_resp *resp, int length,
+			    char *mi_string, u_int8_t *mi_type)
 {
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	u_int8_t *classmark2_lv = gh->data + 1;
-	u_int8_t *mi_lv = gh->data + 2 + *classmark2_lv;
-	*mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
+	u_int8_t *classmark2_lv = (uint8_t *) &resp->classmark2;
 
+	/* Check the size for the classmark */
+	if (length < 2 + *classmark2_lv)
+		return -1;
+
+	u_int8_t *mi_lv = classmark2_lv + *classmark2_lv + 1;
+	if (length < 3 + *classmark2_lv + mi_lv[0])
+		return -2;
+
+	*mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
 	return gsm48_mi_to_string(mi_string, GSM48_MI_SIZE, mi_lv+1, *mi_lv);
 }