aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Maier <pmaier@sysmocom.de>2019-03-18 16:35:29 +0100
committerHarald Welte <laforge@gnumonks.org>2019-03-27 08:01:38 +0000
commit023fc49ed614d1bd9522b84e4ab135a1524e5841 (patch)
tree45b1b61bd741966b542395083a477e5171097f69
parente51a0b53fc1c34291bdf8af0e64d93ae1af6b66b (diff)
osmo_bsc_bssap: check bssmap length field
At the moment the length field of the bssmap header is not parsed. Instead the length is computed out of the known header length and the number of bytes received. This is prone to error, lets make sure that extranous data at the end of a message is ignored by parsing the bssmap length correctly. Change-Id: Idef2e783d2377a2ad1f697ea4d26491a32b3e549 Related: OS#3806
-rw-r--r--src/osmo-bsc/osmo_bsc_bssap.c32
1 files changed, 31 insertions, 1 deletions
diff --git a/src/osmo-bsc/osmo_bsc_bssap.c b/src/osmo-bsc/osmo_bsc_bssap.c
index 85aab22d2..65618fdb3 100644
--- a/src/osmo-bsc/osmo_bsc_bssap.c
+++ b/src/osmo-bsc/osmo_bsc_bssap.c
@@ -1081,6 +1081,36 @@ int bsc_handle_udt(struct bsc_msc_data *msc,
return 0;
}
+/* Extract and verify the length information from the BSSMAP header. */
+static unsigned int bssmap_msg_len(struct msgb *msg, unsigned int length,
+ const struct gsm_subscriber_connection *conn)
+{
+ unsigned int expected_len;
+ unsigned int calculated_len;
+ struct bssmap_header *bssmap_header;
+
+ bssmap_header = (struct bssmap_header *)msg->l3h;
+
+ calculated_len = length - sizeof(struct bssmap_header);
+ expected_len = bssmap_header->length;
+
+ /* In case of contradictory length information, decide for the
+ * shorter length */
+ if (calculated_len > expected_len) {
+ LOGPFSML(conn->fi, LOGL_NOTICE,
+ "BSSMAP message contains extra data, expected %u bytes, got %u bytes, truncated\n",
+ expected_len, calculated_len);
+ return expected_len;
+ } else if (calculated_len < expected_len) {
+ LOGPFSML(conn->fi, LOGL_NOTICE,
+ "Short BSSMAP message, expected %u bytes, got %u bytes\n",
+ expected_len, calculated_len);
+ return calculated_len;
+ }
+
+ return expected_len;
+}
+
int bsc_handle_dt(struct gsm_subscriber_connection *conn,
struct msgb *msg, unsigned int len)
{
@@ -1093,7 +1123,7 @@ int bsc_handle_dt(struct gsm_subscriber_connection *conn,
switch (msg->l3h[0]) {
case BSSAP_MSG_BSS_MANAGEMENT:
msg->l4h = &msg->l3h[sizeof(struct bssmap_header)];
- bssmap_rcvmsg_dt1(conn, msg, len - sizeof(struct bssmap_header));
+ bssmap_rcvmsg_dt1(conn, msg, bssmap_msg_len(msg, len, conn));
break;
case BSSAP_MSG_DTAP:
dtap_rcvmsg(conn, msg, len);