Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2024-20154 — Technical writeup for CVE-2024-20154 | Kitploit
Tools/GitHubGitHub/sneakid/cve-2024-20154
Embedded Systems SecurityIoT SecurityVulnerability AnalysisExploitationReverse EngineeringMobile SecurityPapers & ResearchLearning & EducationFirmware AnalysisBinary Exploitation
GitHubsneakid/cve-2024-20154
212 months agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2024-20154

Technical writeup for CVE-2024-20154

View Repository

CVE-2024-20154: NB-IoT SIB1-NB Stack Overflow in MediaTek MT6769 Baseband

Classification: CWE-121 — Stack-based Buffer Overflow
Severity: Critical (MediaTek bulletin) · 8.8 High, Attack Vector: Adjacent (CISA-ADP)
Type: Remote Code Execution — no user interaction, no prior association
Disclosure: MediaTek Security Bulletin, January 6, 2025 https://corp.mediatek.com/product-security-bulletin/January-2025 Analyzed target: Samsung Galaxy A14 SM-A145R — MT6769 family (Helio G80), within MediaTek's affected chipset list - Firmware was emulated under safe conditions. Status: Patched.


Background and motivation

This was my first published baseband research. I come from a background far away from telecoms infrastructure, lawful interception mediation layers, stingray and IMSI-catcher analysis, and embedded device security — I had not previously done deep firmware reverse engineering on a cellular modem. I wanted to prove to myself that a structured analytical methodology adapts across targets, and that familiarity with a specific platform can be replaced by rigorous chain-tracing. NB-IoT stood out because it sits at a genuinely dangerous intersection: the protocol is designed for constrained IoT devices, the attack surface is pre-association, and the modem stack processes it regardless of what the handset user is doing.

When the patched firmware was analyzed and the vulnerable pattern confirmed absent, the AI system used for mass analysis of the firmware before targeting specific functions

independently matched the reconstructed bug class, conditions, and affected firmware family to the description of CVE-2024-20154.

The technical conclusions are the analyst's own.


1. Introduction

The phone in your pocket contains at least two separate computers. The one you interact with runs Android. The other — the baseband — runs completely independently, handles all radio communication, and is almost entirely invisible to the operating system above it. Android may be fully patched. The browser may be sandboxed. The user may never tap a malicious link. None of that matters if the vulnerable code is in the modem firmware that processes radio signals before the application processor is involved.

CVE-2024-20154 is exactly that kind of vulnerability.

A malformed NB-IoT system-information broadcast causes the MediaTek modem firmware to accept an attacker-controlled scheduling count, carry that count through the RRC-to-L1 configuration path without ever clamping it, and eventually use it as the loop bound for a stack-writing loop inside the NB-IoT broadcast-channel handler. When the count exceeds the destination arrays' capacity, the loop writes past them, reaches saved registers on the stack, and overwrites the saved return address. The function then restores the corrupted value into the return-address register and jumps to it.

What makes the severity what it is:

  • The vulnerable code path is exercised during cell camping — after synchronizing to a cell but before any RRC connection, any authentication, any user interaction.
  • The input is an over-the-air broadcast. The phone cannot authenticate the source.
  • The baseband firmware in the analyzed build runs with no ASLR, no stack canaries, no non-executable stack, and no control-flow integrity. A saved-return-address overwrite translates directly to program-counter control.

The vulnerability was published in MediaTek's January 6, 2025 Security Bulletin with a Critical severity rating, affecting the LR12A modem family among others. Samsung incorporated the fix into their February 2025 Security Maintenance Release.

This post does not publish a weaponized exploit and is not reproducible from what is published here. The goal is to show where the chain breaks, why each layer failed to stop it, and what it takes to validate a baseband bug responsibly when you cannot attach a debugger to the live modem.


2. Target and Environment

2.1 Device and firmware

Primary target: Samsung Galaxy A14 (SM-A145R). The radio subsystem is driven by a MediaTek baseband processor in the MT6769 chipset family (Helio G80). The MT6769 family is explicitly listed in MediaTek's affected chipset list for CVE-2024-20154.

root@kitploit:~
AP/CP firmware:  A145RXXU1AWD1
Modem software:  MOLY LR12A.R3.TC10.6M.A14.PR.SP.V1.P5
Build date:      2023-04-18

The baseband firmware is not Android code. It is a separate embedded system on the radio subsystem of the SoC with its own CPU, its own RTOS, and its own memory space, outside the Android process sandbox.

2.2 Modem architecture

Analysis of the extracted binary shows the modem processor runs MIPS32 with MIPS16e2 compressed instructions in little-endian mode. MIPS16e2 is a 16-bit encoding extension for embedded code-size reduction — consistent with MediaTek's approach for Helio-generation basebands, confirmed by independent published baseband research on this SoC family.

The operating system is Nucleus RTOS, providing task scheduling, IPC message queues, and a pool-based memory allocator. There is no kernel/user privilege separation, no memory protection unit enforcement between tasks, and no hardware stack-guard mechanism.

All addresses in this post are virtual addresses, as loaded in Ghidra at base 0x90000000.

2.3 Mitigations (observed in analyzed build)

2.4 Analysis approach

Three parallel tracks:

Static analysis. Samsung firmware package → CP partition extraction → md1img.img → Ghidra (MIPS LE 32-bit, base 0x90000000) with MediaTek engineering symbols recovered from the firmware debug section using the NCC Group mtk_bp toolset.

Dynamic validation. Unicorn Engine (MIPS32 emulation) was used to execute specific firmware routines in isolation across two phases. Phase 1 attempted to prove the unclamped copy of si_count into channel context through the native instruction pair. Phase 2 executed the vulnerable loop on real firmware bytes and confirmed that the firmware's own instructions corrupt the saved return address. Where Phase 1 could not run fully natively — because the RTOS service-object environment required by the CPHY dispatch path was not reconstructed — the side effect was modeled directly and labeled as such in all output.

Radio-side validation. srsRAN 4G with a ZMQ loopback — software-only, no RF emission — confirmed that the test payload survives NB-IoT PHY encoding and transport-block delivery.


3. Attack Surface: NB-IoT and SIB1-NB

3.1 Pre-association attack surface

NB-IoT (Narrowband Internet of Things) is 3GPP Release 13, designed to connect constrained IoT devices using existing licensed LTE spectrum. It is implemented in a wide range of modern cellular SoCs including those in consumer smartphones.

While in RRC_IDLE, before any RRC connection is established, a device searching for service will:

  1. Synchronize with the cell's timing signals (NPSS/NSSS)
  2. Decode the Master Information Block over NPBCH (640 ms transmission window)
  3. Decode SIB1-NB from NPDSCH (2560 ms schedule)
  4. Use the scheduling information in SIB1-NB to locate additional system information blocks

At step 3, the modem processes a message from an entity it has not authenticated, before any connection or user interaction. A rogue transmitter satisfying normal cell selection conditions will be processed.

root@kitploit:~
+------------------+                   +---------------------+
|  Rogue Base Stn  |                   |  Target UE (Modem)  |
+--------+---------+                   +----------+----------+
         |                                        |
         |   NPSS/NSSS sync                      |
         |--------------------------------------->|
         |   MIB-NB (640 ms cycle)                |
         |--------------------------------------->|
         |   SIB1-NB (malformed, si_count > 8)    |
         |--------------------------------------->|   ← vulnerability triggered
         |   [no RRC connection established]      |

3.2 The scheduling count field

SIB1-NB is defined in 3GPP TS 36.331. Its schedulingInfoList field carries how many System Information messages the cell broadcasts, constrained by the spec to a maximum of 8 entries (1..maxSI-Message-NB-r13 = 8). This is a protocol-layer constraint. The memory-safety constraint — that the list length must not exceed the capacity of the destination arrays — must be enforced separately by the firmware.

It was not.


4. Firmware Extraction and Symbol Recovery

Firmware was obtained from a Samsung CP package and extracted using the NCC Group mtk_bp toolset:

root@kitploit:~
md1img.img  →  md1_extract.py    →  000_md1rom        (17.8 MB code image)
                                 →  017_md1_dbginfo   (XZ-compressed CATI debug symbols)

The CATI debug section was decompressed and parsed with mtk_dbg_extract.py symbols, then imported into Ghidra via ImportSymbolsScript.py. The result was full internal function names throughout the modem stack — ERRC layer, L1 channel management, IPC subsystem, and the NB-IoT BCCH handler chain — allowing semantics-guided chain reconstruction.

All function names in this post come from MediaTek's own embedded debug symbols extracted from the firmware image.


5. Vulnerability

5.1 The vulnerable loop

el1_ch_nbcch_resume_req (0x90213940) handles the NB-IoT broadcast-channel resume event. Its MIPS16e2 function prologue:

root@kitploit:~
90213940:  save  0xE8, ra, s0-s1

The SAVE instruction decrements sp by 0xE8 and stores callee-saved registers downward:

root@kitploit:~
old_sp  (= new_sp + 0xE8)
new_sp + 0xE4   saved ra   ← overflow target
new_sp + 0xE0   saved s1
new_sp + 0xDC   saved s0
new_sp + 0x98   si_sched_arr  [34 halfwords = 68 bytes]
new_sp + 0x78   si_type_arr   [32 bytes]
new_sp + 0x00   ← stack pointer after SAVE

From Ghidra decompile of the actual firmware binary:

root@kitploit:~
for (uVar6 = 0; uVar6 < (byte)param_2[0x40a]; uVar6 = uVar6 + 1) {
    si_type_arr[uVar6]  = /* SI type byte */;          // 1 byte/iter, base new_sp+0x78
    si_sched_arr[uVar6] = /* SI schedule halfword */;  // 2 bytes/iter, base new_sp+0x98
}

param_2[0x40a] is ch_ctx[+0x40A] — a persistent byte in the channel context BSS struct. The loop bound is used directly, with no prior comparison against the array capacities.

5.2 The overflow arithmetic

Stream A (halfword sh writes) starts at new_sp+0x98 and advances 2 bytes per iteration. It reaches the saved RA at new_sp+0xE4 at iteration 38:

root@kitploit:~
new_sp + 0x98 + i×2 = new_sp + 0xE4
i = (0xE4 - 0x98) / 2 = 0x4C / 2 = 38

Stream B (byte sb writes) starts at new_sp+0x78 and would require iteration 108 to reach the RA slot:

root@kitploit:~
new_sp + 0x78 + i = new_sp + 0xE4
i = 0xE4 - 0x78 = 108

With si_count = 40 (the demonstrator value, chosen to exceed the overflow threshold of 38) the loop runs 40 iterations. Stream B never reaches the RA slot. The RA corruption comes entirely from Stream A.

After 40 iterations the MIPS16e2 RESTORE instruction reloads the corrupted value from the stack into $ra, and jrc ra transfers control.

5.3 The unclamped copy — Layer B

ch_ctx[+0x40A] is written by el1_ch_nbcch_start at 0x90213444. Two consecutive MIPS instructions with nothing between them:

root@kitploit:~
; el1_ch_nbcch_start @ 0x90213444
lbu  v0, 0x99(s0)    ; read IPC_msg[+0x99] = si_count from CPHY_CFG_REQ
sb   v0, 0x40A(s1)   ; write to ch_ctx[+0x40A] — no clamp, no mask, no compare

5.4 The ERRC builder — Layer A

The CPHY_CFG_REQ buffer is built in the ERRC layer from the decoded SIB1-NB. The function errc_chm_l1_set_bcch_si_reception writes IPC_msg[+0x99]:

root@kitploit:~
// errc_chm_l1_set_bcch_si_reception — Layer A
// Loop bound: decoded schedulingInfoList entry count from SIB1-NB

while (bVar3 < *(byte *)(param_3 + 0x44) && (param_2 != 0)) {
    bVar3++;
    if (uVar2 != param_2) {
        *param_5 = *param_5 + 1;   // CPHY_CFG_REQ[+0x99]++ — no upper bound check
    }
}

The loop bound is the decoded entry count from SIB1-NB. The counter increments once per decoded entry, for as many entries as were decoded, with no maximum guard.

5.5 The IPC path

Once the CPHY_CFG_REQ buffer is populated, ERRC dispatches it to L1 with sap_id = 0x501F as the routing key:

root@kitploit:~
el1_ch_rcv_ilm  (sap 0x501F)
  → el1_chmgm_errc_cfg_req_in_idle      ← stores CPHY_CFG_REQ @ L1_ctx[+0x323C]
    → el1_chmgm_nbcch_handler
      → el1_ch_nbcch_main
        → el1_ch_nbcch_cphy_cfg_req_process   ← validates cell identity, no si_count check
          → el1_ch_nbcch_start @ 0x90213444  ← Layer B: lbu + sb, no clamp

5.6 Three-layer absence of clamping

Any single check at any one layer would have broken the chain.

5.7 Root cause

One violated invariant:

The number of SI scheduling entries must never exceed the destination array capacity.

3GPP provides the intended protocol bound (8 entries). The firmware needed to enforce the memory-safety bound at every layer where the count becomes an index or loop limit. In the vulnerable build, the count traveled from the SIB1-NB broadcast field through the ERRC decoder, into the CPHY_CFG_REQ message, across an IPC boundary into the L1 task, into channel context BSS, and into a stack-writing loop — without any layer clamping it.


6. The Call Chain — How It Was Found

6.1 The two-path confusion

Two structurally similar but distinct paths can deliver a 0x760-byte configuration buffer to el1_ch_nbcch_main:

Path B confirmed the message format — byte +0x99 is the SI count consumed by el1_ch_nbcch_start. Because its count is always hardcoded to 1, it cannot overflow. The externally influenced path is Path A.

6.2 The writer search

Pattern-searching the firmware for any instruction writing to offset +0x99 produced noise: T1 (direct sb, ~100 hits), T2 (split base, 5 hits), T3 (computed offset, 0), T4 (overlapping sh/sw, ~465). The ERRC channel management functions were absent from the msg_send6 cross-reference list because ERRC uses errc_com_send_msg. An emulation probe confirmed the write was ERRC-side: running the Unicorn harness from the L1 dispatcher and watching for writes to the buffer's +0x99 offset captured nothing from the L1 side.

root@kitploit:~
[RUN] dispatcher=0x90214418  watching IPC_msg+0x99

NO writes to IPC_msg+0x99 caught from dispatcher.
Write happened before el1_ch_nbcch_main — confirmed ERRC-side.

6.3 Resolution via IPC routing key

Following sap_id = 0x501F in errc_com_send_msg identified the routing to el1_chmgm_errc_cfg_req_in_idle, which stores the CPHY_CFG_REQ pointer at L1_ctx[+0x323C] and begins the downstream dispatch.

6.4 Confirmed call chain

root@kitploit:~
SIB1-NB schedulingInfoList.count (demonstrator: 40)
        │
        ▼  [ERRC task]
errc_chm_ch_ctrl_req_hdlr
  → errc_chm_call_ctrl
  → errc_chm_l1_main
  → errc_chm_l1_call_ctrl
  → errc_chm_l1_snd_cphy_cfg_req          ← allocates 0x760-byte CPHY_CFG_REQ
  → errc_chm_l1_set_cphy_req_nbcch_cfg
  → errc_chm_l1_set_bcch_inf
  → errc_chm_l1_set_bcch_si_reception     ← Layer A: CPHY_CFG_REQ[+0x99] = 40
  → errc_com_send_msg(sap=0x501F)         ← IPC to L1
        │
        ▼  [L1 task]
el1_ch_rcv_ilm  (sap 0x501F)
  → el1_chmgm_errc_cfg_req_in_idle        ← stores CPHY_CFG_REQ @ L1_ctx[+0x323C]
  → el1_chmgm_nbcch_handler
  → el1_ch_nbcch_main
  → el1_ch_nbcch_cphy_cfg_req_process     ← no si_count validation
  → el1_ch_nbcch_start @ 0x90213444      ← Layer B: lbu + sb, no clamp
        │
        ▼
ch_ctx[0x40A] = 40   (persists in BSS)
        │
        ▼  [state machine advances to 0x0B, event 0x2C]
el1_ch_nbcch_resume_req @ 0x90213940     ← Layer C: loop bound from ch_ctx[0x40A]
        │
        ▼
stack overflow → jrc ra → PC = attacker-controlled

7. Validation

This specific SM-A145R model does not appear to exercise the vulnerable NB-IoT code path in normal ship-build operation, which is why hybrid emulation and static analysis were used rather than direct hardware reproduction.

Proven statically. The firmware binary contains the vulnerable instruction pair. The call chain is reconstructed from symbols, cross-references, and decompiled function bodies.

Executed natively in emulation. The loop inside el1_ch_nbcch_resume_req ran on real MediaTek firmware bytes in Unicorn Engine (MIPS32). The firmware's own sh instruction at 0x90213B02 wrote to the saved return-address slot. The RESTORE instruction loaded the corrupted value into $ra, and jrc ra transferred control.

Modeled explicitly. The lbu/sb copy in el1_ch_nbcch_start could not be run fully natively because the RTOS callback-table dispatch path within el1_ch_nbcch_cphy_cfg_req_ process expected live Nucleus heap objects the flat emulator did not provide. The resume handler (el1_ch_nbcch_resume_req) in Phase 2 reads only from BSS-resident channel context and does not hit that same dispatch path, which is why Phase 2 ran natively without requiring the same scaffolding. The Phase 1 side effect — one byte from IPC_msg[+0x99] written to ch_ctx[+0x40A] — was modeled directly and labeled [PHASE1-MODEL].

Not claimed. A complete end-to-end over-the-air hardware reproduction.

7.1 Anti-tamper

The harness enforced one rule: no hook was permitted to write the proof marker into the saved return-address slot. Every non-firmware memory write was tracked.

root@kitploit:~
[PROOF-W] saved_RA write: pc=0x90213b02  addr=new_sp+0xE4  value=0xbeef
[PROOF-W] saved_RA write: pc=0x90213b02  addr=new_sp+0xE6  value=0xdead
[ANTI-TAMPER] no hook wrote RA=0xDEADBEEF — firmware only
anti_tamper_fail = False

0x90213B02 is the sh instruction inside the loop body. The firmware placed these bytes at the predicted stack offset. In little-endian storage, the halfwords 0xBEEF and 0xDEAD at new_sp+0xE4 and new_sp+0xE6 combine to [ef be ad de] = 0xDEADBEEF.

7.2 Emulation result

root@kitploit:~
[REGS]
  RA = 0xdeadbeef   ← firmware wrote this; decisive proof
  PC = 0x00000000   ← Unicorn unmapped-fetch artifact, not a hardware exception vector

[STACK]  new_sp+0xE4: [ef be ad de]   ← little-endian 0xDEADBEEF

[PC-EXPLAIN] PC=0 is an unmapped-fetch artifact; decisive proof is
             RA=0xDEADBEEF + stack bytes [ef be ad de] + [PROOF-JRC]
CONFIRMED: saved RA = 0xDEADBEEF

7.3 ZMQ delivery

To confirm the test payload survives NB-IoT PHY encoding and transport-block delivery, srsRAN 4G with a ZMQ loopback (no RF emission) was used. The payload was a deliberately non-conformant vector — the ASN.1 SIZE constraint on schedulingInfoList was relaxed to allow 40 entries, with pycrate round-trip decode confirming the count field at byte 14.

root@kitploit:~
SIB1 received
SIB2 activated
exit 0

This confirms transport-layer delivery. Firmware-side ASN.1 behavior is established by the Layer A static analysis.


8. Control-Flow Mechanics

8.1 Two phases, one task, persistent state

The el1_ch task has one stack. Phase 1 and Phase 2 are two separate IPC events processed sequentially by the same task, with the stack fully unwinding between them. The count persists in channel context BSS, not on the stack:

root@kitploit:~
EVENT: CPHY_CFG_REQ  (Phase 1)
  el1_ch_nbcch_start
    lbu v0, 0x99(s0)
    sb  v0, 0x40A(s1)   ← ch_ctx[0x40A] = attacker value, written to BSS
  returns — stack fully unwound

EVENT: resume (state 0x0B, msg 0x2C)  (Phase 2)
  el1_ch_nbcch_resume_req   ← frame 0xE8, reads ch_ctx[0x40A] as loop bound
    loop × 40 → saved RA corrupted
    jrc ra → attacker-controlled PC

ch_ctx[0x40A] lives in BSS and retains the attacker's value until the modem resets or a subsequent channel configuration overwrites it.

8.2 Stack frame

root@kitploit:~
old_sp  (= new_sp + 0xE8)
new_sp + 0xE4   saved ra
new_sp + 0xE0   saved s1
new_sp + 0xDC   saved s0
new_sp + 0x98   si_sched_arr  [34 halfwords = 68 bytes]
new_sp + 0x78   si_type_arr   [32 bytes]

Frame size confirmed by emulation measurement. Array positions confirmed by the emulation result — RA written at iteration 38, consistent with si_sched_arr starting at new_sp+0x98.


9. Evidence

9.1 Gates before the vulnerable loop

9.2 Functions confirmed not to clamp si_count


10. Patch Analysis

10.1 Versions

BuildModem firmwareBuild date
VulnerableA145RXXU1AWD1, MOLY LR12A...V1.P52023-04-18
PatchedA145RXXUDDZC2, MOLY LR12A...V3.P8

Build dates confirmed by extracting md1_dbginfo metadata from both images. Patch ID: MOLY00720348 · Issue ID: MSV-2392.

10.2 What changed

el1_ch_nbcch_start (0x90213444 in vulnerable binary): The lbu/sb instruction pair is absent. The direct copy of IPC_msg[+0x99] into ch_ctx[+0x40A] is gone.

el1_ch_nbcch_resume_req (0x90213940 in vulnerable binary): The stack-writing loop over ch_ctx[0x40A] is absent. The architecture where an untrusted byte becomes a loop bound over fixed-size stack arrays no longer exists. The function body is replaced with a different dispatch structure.

errc_chm_l1_set_bcch_si_reception: The unbounded counter loop is replaced with validation-oriented helper calls.

10.3 New validation functions

Two functions present in the patched binary are absent from the vulnerable binary:

root@kitploit:~
el1_ch_nbcch_param_check
el1_ch_scell_param_check

A single-line bounds check would appear as a few added instructions inside an existing function at the same address. What the patched binary shows is an architectural revision: the NBCCH scheduling path was redesigned so that the si_count-as-loop-bound pattern no longer exists anywhere in the path.

10.4 CVE attribution

The vulnerability described here matches CVE-2024-20154 as published by MediaTek on January 6, 2025. Confirmation basis:

  • Affected firmware family (LR12A) matches MediaTek's bulletin.
  • Vulnerability class — stack overflow, missing bounds check, RCE from rogue base station, no user interaction — matches the CVE description and NVD record.
  • The patched firmware removes exactly the code structures identified as vulnerable.
  • Patch ID MOLY00720348 confirmed from MediaTek's bulletin and the Android Security Bulletin (A-376809176).
  • AI-assisted analysis independently matched the reconstructed pattern to CVE-2024-20154 before manual confirmation.

11. Ethics and Responsible Disclosure

11.1 What this post does not contain

No weaponized exploit. No firmware binary content. No malformed payload bytes. No step-by-step procedure for triggering the vulnerability against a live device. The information needed to reproduce a working attack — complete payload construction for the specific modem decoder, RTOS heap-object scaffolding for full Phase 1 emulation, over-the-air radio configuration — is deliberately absent.

11.2 Why ZMQ loopback and emulation are the ethical approach

ZMQ loopback means no signal was ever transmitted over the air. No real device was targeted. No carrier network was involved. The proof runs entirely in a contained software environment on hardware owned by the analyst. This is the correct approach for validating a pre-association radio vulnerability — transmitting a malformed broadcast would affect any device within range.

Unicorn emulation demonstrates that the vulnerable behavior is in the firmware binary itself, reproducibly, independent of any specific device state or radio environment. This is a technically stronger claim than a single hardware crash, and it avoids deploying anything over the air.

11.3 MediaTek intellectual property

All analysis was performed on firmware legitimately obtained from a consumer device and from Samsung's publicly released firmware packages. No proprietary documentation was used. Internal MediaTek struct definitions and IPC message formats are described only to the extent necessary to explain the memory-safety failure. They are not published as specifications.


Download Tool
MitigationStatusEffect
ASLRAbsentFirmware addresses are static and predictable from the image
Stack canaryAbsentSAVE/RESTORE stores callee-saved registers with no guard value
NX / W^XAbsentStack memory is executable
CFIAbsentReturn addresses are not validated against any policy
Iterationsh writes toEffect
0–33si_sched_arr[0..33]In bounds
34–35new_sp+0xDC — saved s0s0 corrupted
36–37new_sp+0xE0 — saved s1s1 corrupted
38new_sp+0xE4 — saved ra [15:0]RA low halfword
39new_sp+0xE6 — saved ra [31:16]RA high halfword
LayerFunctionAddressClamp present?
A — ERRC buildererrc_chm_l1_set_bcch_si_receptionERRC rangeNone
B — L1 copyel1_ch_nbcch_start0x90213444None
C — L1 loopel1_ch_nbcch_resume_req0x90213940None
PathSource[+0x99] valueRelevance
Path A (ERRC → L1 IPC)ERRC builds CPHY_CFG_REQ from decoded SIB1-NBschedulingInfoList.count from OTAThe vulnerable path
Path B (L1 internal)el1_ch_scs_ind_send builds internal IPC bodyHardcoded 1Not vulnerable
GateConditionWhere checked
NB-IoT active pathcfg_type == 1el1_ch_nbcch_cphy_cfg_req_process
Channel not completedone_flag == 0ch_ctx[0x438]
State machine 0x0BNBCCH in resume stateel1_ch_nbcch_main dispatch
si_count nonzeroch_ctx[0x40A] > 0Loop condition
Band class ≤ 2Valid NB-IoT modeEntry of el1_ch_nbcch_resume_req
el1_chmgm_cell_info_get nonzeroCell in service tableCalled in el1_ch_nbcch_start
FunctionAddressRoleClamp?
errc_chm_l1_set_bcch_si_receptionERRC rangeWrites CPHY_CFG_REQ[+0x99]None
el1_ch_nbcch_cphy_cfg_req_process0x90213F80Routes CPHY config into L1N/A — does not read si_count
el1_chmgm_cell_info_get0x9020E0D0Validates EARFCN/PCIN/A
el1_ch_nbcch_start0x90213444Copies count to BSSNone
el1_ch_nbcch_resume_req0x90213940Uses count as loop boundNone
2025-04-23