We have identified a new heap buffer overflow vulnerability in Mediatek’s baseband implementation. The vulnerability can be exploited to achieve arbitrary code execution in the baseband runtime.

The vulnerability we are disclosing in this advisory affected a wide range of Mediatek devices, including phones on the newest chipsets (Dimensity 700, 1000, etc). The July 2022 issue of the Mediatek Security Bulletin contains this vulnerability as CVE-2022-21744.

Vulnerability Details

The GPRS Packet Neighbour Cell Data (PNCD) message is an optional message sent by the network on the PACCH to provide system information required for initial access in a neighbouring cell. In the case of the MediaTek baseband firmware, this message is processed in the FDD_rmpc_mac_rmpc_pncd_ind_hdlr function. For context, here is the grammar definition of the CSN.1 encoded PNCD message from 3GPP 44.060 11.2.9e:

< Packet Neighbour Cell Data message content > ::=
  < PAGE_MODE : bit (2) >
  {0 <GlobalTFI:<GlobalTFIIE>>
    { < CONTAINER_ID : bit (2) >
      < spare : bit (1)
      < CONTAINER_INDEX : bit (5) >
      {0|1 <ARFCN:bit(10)>
           < BSIC : bit (6) > }
      < CONTAINER : < Container repetition struct > >
      < padding bits >
      ! < Non-distribution part error : bit (*) = < no string > > }
    ! < Address information part error : bit (*) = < no string > }
  ! < Distribution part error : bit (*) = < no string > > ;

< Container repetition struct > ::=
 {
   {   <PD:bit(3)>
       < CD_LENGTH : { bit (5) exclude 00000 exclude 11111 } >
       < CONTAINER_DATA : octet (val(CD_LENGTH)) > -- Final container segment. Next container follows.

   |   <PD:bit(3)>
       < CD_LENGTH : { bit (5) := 11111 } >
       < CONTAINER_DATA : octet ** > } ** -- Container continued in next message.

   {   < spare bit (3) >                         -- Repetition of the container repetition struct continues until:
       < CD_LENGTH : { bit (5) := 00000 } > }    -- A) val(CD_LENGTH) = 0 or
 }//;                                            -- B) end of PNCD message.

As it can be seen in the 3GPP specification (excerpt above), PNCD messages support fragmentation: individual messages may carry partial data and are identified by their Container Index value, which also defines the order among the maximum 32 PNCD messages that form parts of a total. Further, the implementation follows the 3GPP specification and it supports multiple Container repetition structs to be stored inside the Container field of a single PNCD packet. The Container Data inside the repeated structures carries at most 21 bytes of arbitrary data and is eventually saved by the FDD_rr_put_pncd_qmsg function, as the pseudocode outlined below shows:

def FDD_rr_put_pncd_qmsg(src, size, qmsg):
  # allocate the pointer array if this is the first element
  if qmsg->current_num == 0:
    # this is enough space for 32 pointers
    qmsg->ptr_to_msg_ptr_array = get_ctrl_buffer_ext(0x80)
    qmsg->valid = True

  # allocate and zero-initialize memory for the current message content
  ptr_to_msg_ptr_array[current_num] = get_ctrl_buffer_ext(28)
  memset(ptr_to_msg_ptr_array[current_num], 0, 28)

  # copy the data (size is always 21 when called from PNCD functions)
  memcpy(ptr_to_msg_ptr_array[current_num]->msg, src, size)
  ptr_to_msg_ptr_array[current_num]->msg_len = size * 8
  ptr_to_msg_ptr_array[current_num]->offset = 0

  # advance the queue state
  qmsg->current_num += 1
  qmsg->total_num = qmsg->current_num

The vulnerability comes from the fact that the specification does not define the maximum number of repetitions, and there is no boundary condition checking in the parsing code. But the same time the FDD_rr_put_pncd_qmsg does define an arbitrary (as in implementation specific) limit by allocating a 128 bytes long array to store the pointers of the collected Container Data messages. The size of a pointer on either modem architecture used by Mediatek basebands (interAptive and I7200-based) is always 4 bytes, so as a result there is only 32 allocated slots. Unfortunately here the boundary check is also missing, thus with more than 32 entries it is possibile to write past the allocated chunk (qmsg->ptr_to_msg_ptr_array).

In a single PNCD message roughly 20 bytes remain for the Container repetition struct part. A minimal Container field takes 16 bits when it contains only one byte of data and the mandatory fields. So that means that about 10 Container Data fields can be inserted into a single PNCD message, and calculating with the maximal 32 number of PNCD messages finally there could be more than 300 instances of Container Data. As the implementation only makes space for 32 of them, more than 300 data entries clearly writes beyond the originally allocated chunk’s end, leading to a heap buffer overflow with attacker controlled length.

The vulnerable function can be reached via the FDD_rmpc_mac_rmpc_pncd_ind_hdlr, FDD_rmpc_save_pncd_raw_data, FDD_rmc_save_pncd_raw_data and FDD_rr_put_pncd_qmsg function call chain.

Although the above description mentions function names prefixed with FDD_, those functions can be found with TDD_ prefixes as well, essentially doubling the vulnerability. These versions correspond of course to the time and frequency division duplex variants of the code, respectively.

Affected Devices

All Mediatek chipsets containing the baseband implementation, namely: MT2731, MT2735, MT6297, MT6725, MT6735, MT6737, MT6739, MT6750, MT6750S, MT6755, MT6757, MT6757P, MT6758, MT6761, MT6762, MT6762D, MT6762M, MT6763, MT6765, MT6765T, MT6767, MT6768, MT6769, MT6769T, MT6769Z, MT6771, MT6775, MT6779, MT6781, MT6783, MT6785, MT6785T, MT6789, MT6797, MT6799, MT6833, MT6853, MT6855, MT6873, MT6875, MT6877, MT6879, MT6880, MT6883, MT6885, MT6889, MT6890, MT6891, MT6893, MT6895, MT6983, MT8666, MT8667, MT8675, MT8735A, MT8735B, MT8765, MT8766, MT8768, MT8771, MT8781, MT8786, MT8788, MT8789, MT8791, MT8797

Fix

Mediatek OTA images, released after July 2022, contain the fix for the vulnerability.

Timeline

  • 2022.01.31. Bug reported to Mediatek PSIRT
  • 2022.03.02. Mediatek confirms vulnerability
  • 2022.05.03. Mediatek confirms CVE
  • 2022.07.04. Mediatek releases security bulletin
  • 2023.08.26. TASZK informs Mediatek of advisory disclosure plan
  • 2023.08.26. Mediatek requests two more months of delay
  • 2023.11.03. Vulnerability released at Hardwear.io
  • 2023.11.26. Advisory release