Merge "Prevent OOB read in nfa_dm_handle_message" into qt-qpr1-dev
diff --git a/src/nfa/hci/nfa_hci_main.cc b/src/nfa/hci/nfa_hci_main.cc
index d6667e1..b4c43be 100644
--- a/src/nfa/hci/nfa_hci_main.cc
+++ b/src/nfa/hci/nfa_hci_main.cc
@@ -741,11 +741,26 @@
p = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
pkt_len = p_pkt->len;
+ if (pkt_len < 1) {
+ LOG(ERROR) << StringPrintf("Insufficient packet length! Dropping :%u bytes",
+ pkt_len);
+ /* release GKI buffer */
+ GKI_freebuf(p_pkt);
+ return;
+ }
+
chaining_bit = ((*p) >> 0x07) & 0x01;
pipe = (*p++) & 0x7F;
if (pkt_len != 0) pkt_len--;
if (nfa_hci_cb.assembling == false) {
+ if (pkt_len < 1) {
+ LOG(ERROR) << StringPrintf(
+ "Insufficient packet length! Dropping :%u bytes", pkt_len);
+ /* release GKI buffer */
+ GKI_freebuf(p_pkt);
+ return;
+ }
/* First Segment of a packet */
nfa_hci_cb.type = ((*p) >> 0x06) & 0x03;
nfa_hci_cb.inst = (*p++ & 0x3F);
diff --git a/src/nfc/nfc/nfc_ncif.cc b/src/nfc/nfc/nfc_ncif.cc
index 0322a97..f14e6f2 100644
--- a/src/nfc/nfc/nfc_ncif.cc
+++ b/src/nfc/nfc/nfc_ncif.cc
@@ -370,16 +370,34 @@
**
*******************************************************************************/
bool nfc_ncif_process_event(NFC_HDR* p_msg) {
- uint8_t mt, pbf, gid, *p, *pp;
+ uint8_t mt, pbf, gid, *p;
bool free = true;
uint8_t oid;
+ uint16_t len;
uint8_t *p_old, old_gid, old_oid, old_mt;
p = (uint8_t*)(p_msg + 1) + p_msg->offset;
- pp = p;
- NCI_MSG_PRS_HDR0(pp, mt, pbf, gid);
- oid = ((*pp) & NCI_OID_MASK);
+ if (p_msg->len < 3) {
+ // Per NCI spec, every packets should have at least 3 bytes: HDR0, HDR1, and
+ // LEN field.
+ LOG(ERROR) << StringPrintf("Invalid NCI packet: p_msg->len: %d",
+ p_msg->len);
+ return free;
+ }
+
+ // LEN field contains the size of the payload, not including the 3-byte packet
+ // header.
+ len = p[2] + 3;
+ if (p_msg->len < len) {
+ // Making sure the packet holds enough data than it claims.
+ LOG(ERROR) << StringPrintf("Invalid NCI packet: p_msg->len (%d) < len (%d)",
+ p_msg->len, len);
+ return free;
+ }
+
+ NCI_MSG_PRS_HDR0(p, mt, pbf, gid);
+ oid = ((*p) & NCI_OID_MASK);
if (nfc_cb.rawVsCbflag == true &&
nfc_ncif_proc_proprietary_rsp(mt, gid, oid) == true) {
nci_proc_prop_raw_vs_rsp(p_msg);
@@ -398,7 +416,7 @@
case NCI_MT_RSP:
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("NFC received rsp gid:%d", gid);
- oid = ((*pp) & NCI_OID_MASK);
+ oid = ((*p) & NCI_OID_MASK);
p_old = nfc_cb.last_hdr;
NCI_MSG_PRS_HDR0(p_old, old_mt, pbf, old_gid);
old_oid = ((*p_old) & NCI_OID_MASK);
@@ -1541,6 +1559,10 @@
uint8_t status;
uint8_t num_responses;
+ if (plen < NFC_TL_SIZE) {
+ return;
+ }
+
/* Pass result to RW_T3T for processing */
STREAM_TO_UINT8(status, p);
STREAM_TO_UINT8(num_responses, p);
diff --git a/src/nfc/tags/rw_mfc.cc b/src/nfc/tags/rw_mfc.cc
index 22cfc35..7fff8c8 100644
--- a/src/nfc/tags/rw_mfc.cc
+++ b/src/nfc/tags/rw_mfc.cc
@@ -404,10 +404,7 @@
if (p_mfc->work_offset == p_mfc->ndef_length) {
UINT8_TO_BE_STREAM(p, 0xFE);
- index = index + 1;
- }
-
- if (p_mfc->work_offset > p_mfc->ndef_length) {
+ } else if (p_mfc->work_offset > p_mfc->ndef_length) {
UINT8_TO_BE_STREAM(p, 0x00);
} else {
UINT8_TO_BE_STREAM(p, p_mfc->p_ndef_buffer[p_mfc->work_offset]);
diff --git a/src/nfc/tags/rw_t3t.cc b/src/nfc/tags/rw_t3t.cc
index 6ac933d..dce6ba8 100644
--- a/src/nfc/tags/rw_t3t.cc
+++ b/src/nfc/tags/rw_t3t.cc
@@ -1018,6 +1018,14 @@
/* Add service code to T3T message */
UINT16_TO_STREAM((*p), cur_service_code);
+
+ /* Validate num_services */
+ if (num_services >= T3T_MSG_SERVICE_LIST_MAX) {
+ LOG(ERROR) << StringPrintf(
+ "RW T3T: num_services (%i) reaches maximum (%i)", num_services,
+ T3T_MSG_SERVICE_LIST_MAX);
+ break;
+ }
}
}