aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2018-02-09 12:08:38 +0100
committerPau Espin Pedrol <pespin@sysmocom.de>2018-02-09 13:15:51 +0100
commit54be46949e93e07e9e57b706388ebb832e5fad0a (patch)
tree2af7bf4127d4c474e1c35e3038c301e491f3a8e5 /src
parent98f3f700797dcbf4777210c8100af79e27ffa7f1 (diff)
l1sap: Validate incoming RTP payload, drop bw-efficient AMR
A recurrent kernel crash in sysmobts (several kernel versions) corrupting kernel memory in random places has been investigated and reproduced by placing a call against an MSC sending RTP with bandwidth-efficient AMR payload to osmo-bts-sysmo. The osmo-bts-sysmo in turn sends the payload to the femtobts related kernel modules via a msgq, which most probably fail to handle correctly this bw-efficient AMR payload and corrupt the kernel memory. First approach was to drop the bw-efficient AMR payloads lower in the stack in sysmo specific code (l1if_tch_encode), but as there's no bts model in osmo-bts actually supporting bw-efficient AMR, let's drop it early in the incoming path for all models to avoid further problems. Related: SYS#4063 Change-Id: If0c9233c628c724de4ab74e58e3e2affac79e6d0
Diffstat (limited to 'src')
-rw-r--r--src/common/l1sap.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/src/common/l1sap.c b/src/common/l1sap.c
index e181a73b..1deee835 100644
--- a/src/common/l1sap.c
+++ b/src/common/l1sap.c
@@ -819,6 +819,47 @@ static int l1sap_handover_rach(struct gsm_bts_trx *trx,
return 0;
}
+static bool rtppayload_is_octet_aligned(const uint8_t *rtp_pl, uint8_t payload_len)
+{
+ /*
+ * Logic: If 1st bit padding is not zero, packet is either:
+ * - bandwidth-efficient AMR payload.
+ * - malformed packet.
+ * However, Bandwidth-efficient AMR 4,75 frame last in payload(F=0, FT=0)
+ * with 4th,5ht,6th AMR payload to 0 matches padding==0.
+ * Furthermore, both AMR 4,75 bw-efficient and octet alignment are 14 bytes long (AMR 4,75 encodes 95b):
+ * bw-efficient: 95b, + 4b hdr + 6b ToC = 105b, + padding = 112b = 14B.
+ * octet-aligned: 1B hdr + 1B ToC + 95b = 111b, + padding = 112b = 14B.
+ * We cannot use other fields to match since they are inside the AMR
+ * payload bits which are unknown.
+ * As a result, this function may return false positive (true) for some AMR
+ * 4,75 AMR frames, but given the length, CMR and FT read is the same as a
+ * consequence, the damage in here is harmless other than being unable to
+ * decode the audio at the other side.
+ */
+ #define AMR_PADDING1(rtp_pl) (rtp_pl[0] & 0x0f)
+ #define AMR_PADDING2(rtp_pl) (rtp_pl[1] & 0x03)
+
+ if(payload_len < 2 || AMR_PADDING1(rtp_pl) || AMR_PADDING2(rtp_pl))
+ return false;
+
+ return true;
+}
+
+static bool rtppayload_is_valid(struct gsm_lchan *lchan, struct msgb *resp_msg)
+{
+ /* Avoid sending bw-efficient AMR to lower layers, most bts models
+ * don't support it. */
+ if(lchan->tch_mode == GSM48_CMODE_SPEECH_AMR &&
+ !rtppayload_is_octet_aligned(resp_msg->data, resp_msg->len)) {
+ LOGP(DL1P, LOGL_NOTICE,
+ "%s RTP->L1: Dropping unexpected AMR encoding (bw-efficient?) %s\n",
+ gsm_lchan_name(lchan), osmo_hexdump(resp_msg->data, resp_msg->len));
+ return false;
+ }
+ return true;
+}
+
/* TCH-RTS-IND prim recevied from bts model */
static int l1sap_tch_rts_ind(struct gsm_bts_trx *trx,
struct osmo_phsap_prim *l1sap, struct ph_tch_param *rts_ind)
@@ -860,6 +901,10 @@ static int l1sap_tch_rts_ind(struct gsm_bts_trx *trx,
LOGP(DL1P, LOGL_DEBUG, "%s DL TCH Tx queue underrun\n",
gsm_lchan_name(lchan));
resp_l1sap = &empty_l1sap;
+ } else if(!rtppayload_is_valid(lchan, resp_msg)) {
+ msgb_free(resp_msg);
+ resp_msg = NULL;
+ resp_l1sap = &empty_l1sap;
} else {
/* Obtain RTP header Marker bit from control buffer */
marker = rtpmsg_marker_bit(resp_msg);