CVE-2026-45513 AI-generated analysis
platform/system/nfc (Android 14/15) and platform/packages/modules/Nfc libnfc-nci (Android 16/17), NCI transport / HAL receive path (src/nfc/nfc/nfc_main.cc)
Adds a length check in nfc_main_hal_data_cback (libnfc-nci nfc_main.cc). An incoming HAL data packet larger than the fixed NFC_NCI_POOL_ID GKI buffer capacity is now logged and dropped instead of being placed in a pool buffer that is too small.
Root cause
In nfc_main_hal_data_cback, when the build takes the #else branch, the receive message buffer comes from GKI_getpoolbuf(NFC_NCI_POOL_ID), which returns a fixed-size buffer from that pool. The incoming data_len from the HAL was never compared against the pool buffer size minus sizeof(NFC_HDR) and NFC_RECEIVE_MSGS_OFFSET. According to the commit message, a packet longer than that remaining capacity could therefore overflow the pool buffer. The sibling #if branch allocates with GKI_getbuf(sizeof(NFC_HDR) + NFC_RECEIVE_MSGS_OFFSET + data_len), which sizes the buffer from data_len, and the fix does not change it.
How the fix works
- src/nfc/nfc/nfc_main.cc:nfc_main_hal_data_cback (#else branch, before GKI_getpoolbuf): computes uint16_t max_len = GKI_get_pool_bufsize(NFC_NCI_POOL_ID) - sizeof(NFC_HDR) - NFC_RECEIVE_MSGS_OFFSET. If data_len > max_len, it logs both sizes with LOG(ERROR), calls android_errorWriteLog(0x534e4554, "508389591") and returns without allocating or queuing the message.
- Adds #include <log/log.h> to provide android_errorWriteLog.
- Note: the commit message names nfc_main_hal_read_cback, but the diff modifies nfc_main_hal_data_cback.
Completeness
- Covers the fixed-pool allocation path (#else branch) in nfc_main_hal_data_cback. In the shown code, this is the only place where a fixed-size buffer was used without a length check.
- The #if branch (GKI_getbuf sized from data_len) is left unchanged, because it sizes the allocation from data_len.
- The material does not show the code that copies p_data into p_msg after allocation. The diff therefore cannot confirm the exact overflow site, or whether other length assumptions exist downstream.
- The check assumes GKI_get_pool_bufsize(NFC_NCI_POOL_ID) is larger than sizeof(NFC_HDR) + NFC_RECEIVE_MSGS_OFFSET. The subtraction is stored in a uint16_t and would wrap if that were not true. The pool sizes are configuration constants and are not shown.
Behavior changes
- HAL data packets whose length exceeds the NFC_NCI_POOL_ID buffer capacity are now dropped, so they are not delivered to the NFC task. Each drop writes an error log line.
- Each drop also writes a SafetyNet-style event log entry (tag 0x534e4554, id 508389591).
- Packets that fit are handled as before. The callback is void, so callers get no new return codes.
Per major
- Android 14: same fix: platform/system/nfc 1dfa112088a9 in android-security-14.0.0_r29, src/nfc/nfc/nfc_main.cc. 7/7 lines present at android-security-14.0.0_r30. The added lines are identical to 15; the surrounding include context (base/logging.h, include order) and the hunk offsets differ.
- Android 15: same fix: platform/system/nfc 0a716527301d in android-security-15.0.0_r17, src/nfc/nfc/nfc_main.cc. 8/8 lines present at android-security-15.0.0_r18.
- Android 16: same fix, different project path: platform/packages/modules/Nfc 2db7814d87ba in android-security-16.0.0_r8, libnfc-nci/src/nfc/nfc/nfc_main.cc. 8/8 lines present at android-security-16.0.0_r9.
- Android 17: same fix, different project path: platform/packages/modules/Nfc 79b15334596b in android-security-17.0.0_r1, libnfc-nci/src/nfc/nfc/nfc_main.cc. 8/8 lines present at android-security-17.0.0_r2.
Unknowns
- The material does not include the code after allocation that copies data_len bytes into p_msg, which is the actual overflow site.
- The material does not show the name of the preprocessor macro that selects the #if (GKI_getbuf) or #else (GKI_getpoolbuf) branch, or which configuration Android builds use.
- The size of the NFC_NCI_POOL_ID buffers and the value of NFC_RECEIVE_MSGS_OFFSET are not shown.
- How nfc_main_hal_data_cback is registered and reached is not shown; the index search found no callers.
- The material does not show whether GKI_get_pool_bufsize already existed on all branches or was added separately. The patched lines are present in every branch's latest tag.