From 62a4fa1c9379064b3dcfd249a44b5b19500b9b05 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 1 Jul 2019 21:51:18 +0200 Subject: [PATCH] fix various potential buffer overruns this is based on suggested fixes by Dirk Grabinski and David who have fuzzed various parts of srsLTE using afl --- lib/src/asn1/asn1_utils.cc | 17 +++++++++++++++++ lib/src/asn1/liblte_mme.cc | 26 ++++++++++++++++++++++++-- srsenb/src/stack/upper/s1ap.cc | 7 ++++--- 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/lib/src/asn1/asn1_utils.cc b/lib/src/asn1/asn1_utils.cc index a5b60f64f..416f42771 100644 --- a/lib/src/asn1/asn1_utils.cc +++ b/lib/src/asn1/asn1_utils.cc @@ -711,6 +711,10 @@ dyn_octstring& dyn_octstring::from_string(const std::string& hexstr) SRSASN_CODE pack_common_bitstring(bit_ref& bref, const uint8_t* buf, uint32_t nbits) { uint32_t n_octs = (uint32_t)ceilf(nbits / 8.0f); + if (n_octs == 0) { + srsasn_log_print(LOG_LEVEL_ERROR, "Invalid number of octets (%d)\n", n_octs); + return SRSASN_ERROR_DECODE_FAIL; + } uint32_t offset = ((nbits - 1) % 8) + 1; HANDLE_CODE(bref.pack(buf[n_octs - 1], offset)); for (uint32_t i = 1; i < n_octs; ++i) { @@ -722,6 +726,10 @@ SRSASN_CODE pack_common_bitstring(bit_ref& bref, const uint8_t* buf, uint32_t nb SRSASN_CODE unpack_common_bitstring(uint8_t* buf, bit_ref& bref, uint32_t nbits) { uint32_t n_octs = (uint32_t)ceilf(nbits / 8.0f); + if (n_octs == 0) { + srsasn_log_print(LOG_LEVEL_ERROR, "Invalid number of octets (%d)\n", n_octs); + return SRSASN_ERROR_DECODE_FAIL; + } uint32_t offset = ((nbits - 1) % 8) + 1; HANDLE_CODE(bref.unpack(buf[n_octs - 1], offset)); for (uint32_t i = 1; i < n_octs; ++i) { @@ -948,6 +956,11 @@ SRSASN_CODE ext_groups_header::pack_nof_groups(bit_ref& bref) const SRSASN_CODE ext_groups_header::pack_group_flags(bit_ref& bref) const { + if (nof_groups > groups.size()) { + srsasn_log_print(LOG_LEVEL_ERROR, "Exceeded maximum number of groups (%d>%d)\n", nof_groups, groups.size()); + return SRSASN_ERROR_ENCODE_FAIL; + } + // NOTE: nof_groups is cached for (uint32_t i = 0; i < nof_groups; ++i) { HANDLE_CODE(bref.pack(groups[i], 1)); @@ -974,6 +987,10 @@ SRSASN_CODE ext_groups_header::unpack_nof_groups(bit_ref& bref) SRSASN_CODE ext_groups_header::unpack_group_flags(bit_ref& bref) { + if (nof_groups > groups.size()) { + srsasn_log_print(LOG_LEVEL_ERROR, "Exceeded maximum number of groups (%d>%d)\n", nof_groups, groups.size()); + return SRSASN_ERROR_DECODE_FAIL; + } for (uint32_t i = 0; i < nof_groups; ++i) { HANDLE_CODE(bref.unpack(groups[i], 1)); } diff --git a/lib/src/asn1/liblte_mme.cc b/lib/src/asn1/liblte_mme.cc index d05156cbe..7fbd55ae5 100644 --- a/lib/src/asn1/liblte_mme.cc +++ b/lib/src/asn1/liblte_mme.cc @@ -1697,7 +1697,8 @@ LIBLTE_ERROR_ENUM liblte_mme_pack_esm_message_container_ie(LIBLTE_BYTE_MSG_STRUC uint32 i; if(esm_msg != NULL && - ie_ptr != NULL) + ie_ptr != NULL && + esm_msg->N_bytes <= LIBLTE_MAX_MSG_SIZE_BYTES) { (*ie_ptr)[0] = esm_msg->N_bytes >> 8; (*ie_ptr)[1] = esm_msg->N_bytes & 0xFF; @@ -1723,6 +1724,11 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_message_container_ie(uint8 { esm_msg->N_bytes = (*ie_ptr)[0] << 8; esm_msg->N_bytes |= (*ie_ptr)[1]; + + if(esm_msg->N_bytes > LIBLTE_MAX_MSG_SIZE_BYTES ) { + return err; + } + for(i=0; iN_bytes; i++) { esm_msg->msg[i] = (*ie_ptr)[2+i]; @@ -3406,6 +3412,11 @@ LIBLTE_ERROR_ENUM liblte_mme_pack_emergency_number_list_ie(LIBLTE_MME_EMERGENCY_ { (*ie_ptr)[length++] = (emerg_num_list->emerg_num[i].N_emerg_num_digits/2) + 1; (*ie_ptr)[length++] = emerg_num_list->emerg_num[i].emerg_service_cat; + + if (emerg_num_list->emerg_num[i].N_emerg_num_digits / 2 > LIBLTE_MME_EMERGENCY_NUMBER_MAX_NUM_DIGITS) { + return err; + } + for(j=0; jemerg_num[i].N_emerg_num_digits/2; j++) { (*ie_ptr)[length] = emerg_num_list->emerg_num[i].emerg_num[j*2+0]; @@ -3449,6 +3460,11 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_emergency_number_list_ie(uint8 { idx = emerg_num_list->N_emerg_nums; emerg_num_list->emerg_num[idx].N_emerg_num_digits = ((*ie_ptr)[length++] - 1) * 2; + if (emerg_num_list->emerg_num[idx].N_emerg_num_digits > + LIBLTE_MME_EMERGENCY_NUMBER_MAX_NUM_DIGITS) { + return err; + } + emerg_num_list->emerg_num[idx].emerg_service_cat = (LIBLTE_MME_EMERGENCY_SERVICE_CATEGORY_ENUM)((*ie_ptr)[length++] & 0x1F); for(i=0; iemerg_num[idx].N_emerg_num_digits/2; i++) { @@ -3629,7 +3645,8 @@ LIBLTE_ERROR_ENUM liblte_mme_pack_generic_message_container_ie(LIBLTE_BYTE_MSG_S uint32 i; if(msg != NULL && - ie_ptr != NULL) + ie_ptr != NULL && + msg->N_bytes <= LIBLTE_MAX_MSG_SIZE_BYTES) { (*ie_ptr)[0] = msg->N_bytes >> 8; (*ie_ptr)[1] = msg->N_bytes & 0xFF; @@ -3655,6 +3672,11 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_generic_message_container_ie(uint8 { msg->N_bytes = (*ie_ptr)[0] << 8; msg->N_bytes |= (*ie_ptr)[1]; + + if(msg->N_bytes > LIBLTE_MAX_MSG_SIZE_BYTES){ + return err; + } + for(i=0; iN_bytes; i++) { msg->msg[i] = (*ie_ptr)[2+i]; diff --git a/srsenb/src/stack/upper/s1ap.cc b/srsenb/src/stack/upper/s1ap.cc index 376c70d24..019b905f0 100644 --- a/srsenb/src/stack/upper/s1ap.cc +++ b/srsenb/src/stack/upper/s1ap.cc @@ -123,9 +123,8 @@ void s1ap::run_thread() // S1AP rx loop while(running) { pdu->clear(); - pdu->N_bytes = recv(socket_fd, pdu->msg, sz, 0); - - if(pdu->N_bytes <= 0) { + ssize_t n_recv = recv(socket_fd, pdu->msg, sz, 0); + if (n_recv <= 0) { mme_connected = false; do { s1ap_log->error("Disconnected - attempting reconnection in 10 seconds\n"); @@ -141,6 +140,8 @@ void s1ap::run_thread() } } + pdu->N_bytes = static_cast(n_recv); + s1ap_log->info_hex(pdu->msg, pdu->N_bytes, "Received S1AP PDU"); handle_s1ap_rx_pdu(pdu.get()); }