Merge branch 'security-aosp-qt-release' into int/10/fp2
* security-aosp-qt-release:
OOBR in nfc_ncif_proc_ee_discover_req()
Double Free in ce_t4t_data_cback
Out of Bounds Read in nfa_dm_check_set_config
Change-Id: Ic9d095c649568a6ff705c8caed28e0436aa8c786
diff --git a/src/nfa/dm/nfa_dm_discover.cc b/src/nfa/dm/nfa_dm_discover.cc
index 3414c91..8e5cd5c 100644
--- a/src/nfa/dm/nfa_dm_discover.cc
+++ b/src/nfa/dm/nfa_dm_discover.cc
@@ -76,7 +76,6 @@
static nfa_dm_p2p_prio_logic_t p2p_prio_logic_data;
-static void nfa_dm_send_tag_deselect_cmd(tNFA_NFC_PROTOCOL protocol);
/*******************************************************************************
**
@@ -2139,14 +2138,6 @@
switch (event) {
case NFA_DM_RF_DEACTIVATE_CMD:
- if (NFC_GetNCIVersion() == NCI_VERSION_2_0) {
- if ((nfa_dm_cb.disc_cb.activated_rf_interface == NFC_INTERFACE_FRAME) &&
- (p_data->deactivate_type == NFC_DEACTIVATE_TYPE_SLEEP)) {
- /* NCI 2.0- DH is responsible for sending deactivation commands before
- * RF_DEACTIVATE_CMD */
- nfa_dm_send_tag_deselect_cmd(nfa_dm_cb.disc_cb.activated_protocol);
- }
- }
if (nfa_dm_cb.disc_cb.activated_protocol == NCI_PROTOCOL_MIFARE) {
nfa_dm_cb.disc_cb.deact_pending = true;
@@ -2201,6 +2192,9 @@
}
if (p_data->nfc_discover.deactivate.reason !=
NFC_DEACTIVATE_REASON_DH_REQ_FAILED) {
+ /* count for number of times deactivate cmd sent */
+ nfa_dm_cb.deactivate_cmd_retry_count = 0;
+
sleep_wakeup_event = true;
nfa_dm_disc_notify_deactivation(NFA_DM_RF_DEACTIVATE_NTF,
&(p_data->nfc_discover));
@@ -2210,8 +2204,7 @@
NFC_DEACTIVATE_TYPE_SLEEP_AF)) {
if (p_data->nfc_discover.deactivate.reason !=
NFC_DEACTIVATE_REASON_DH_REQ_FAILED) {
- /* count for number of times deactivate cmd sent */
- nfa_dm_cb.deactivate_cmd_retry_count = 0;
+
nfa_dm_disc_new_state(NFA_DM_RFST_W4_HOST_SELECT);
}
if (old_sleep_wakeup_flag) {
@@ -2246,7 +2239,6 @@
(!nfa_dm_cb.disc_cb.deact_pending)) {
nfa_dm_send_deactivate_cmd(NFA_DEACTIVATE_TYPE_DISCOVERY);
}
- nfa_dm_cb.deactivate_cmd_retry_count = 0;
} else {
nfa_dm_cb.deactivate_cmd_retry_count++;
nfa_dm_send_deactivate_cmd(p_data->nfc_discover.deactivate.type);
@@ -2259,6 +2251,24 @@
} else if (p_data->nfc_discover.deactivate.type ==
NFC_DEACTIVATE_TYPE_DISCOVERY) {
nfa_dm_disc_new_state(NFA_DM_RFST_DISCOVERY);
+ /* if deactivation type is discovery and comes after 3 tentatives of
+ * unsuccessful deactivation to sleep then reset the counter and notify
+ * upper layer.
+ *
+ */
+ if (nfa_dm_cb.deactivate_cmd_retry_count == 3) {
+ nfa_dm_cb.deactivate_cmd_retry_count = 0;
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << __func__
+ << StringPrintf(
+ " NFA_DM_RF_DEACTIVATE_NTF to discovery after 3 attempt "
+ "of deactivate (sleep)");
+ if (p_data->nfc_discover.deactivate.reason ==
+ NFC_DEACTIVATE_REASON_DH_REQ_FAILED) {
+ nfa_dm_disc_notify_deactivation(NFA_DM_RF_DEACTIVATE_NTF,
+ &(p_data->nfc_discover));
+ }
+ }
if (nfa_dm_cb.disc_cb.disc_flags & NFA_DM_DISC_FLAGS_STOPPING) {
/* stop discovery */
NFC_Deactivate(NFA_DEACTIVATE_TYPE_IDLE);
@@ -3056,40 +3066,3 @@
memset(&p2p_prio_logic_data, 0x00, sizeof(nfa_dm_p2p_prio_logic_t));
}
-/*******************************************************************************
-**
-** Function nfa_dm_send_tag_deselect_cmd
-**
-** Description Send command to send tag in sleep state
-**
-** Returns void
-**
-*******************************************************************************/
-static void nfa_dm_send_tag_deselect_cmd(tNFA_NFC_PROTOCOL protocol) {
- NFC_HDR* p_msg;
- uint8_t* p;
-
- DLOG_IF(INFO, nfc_debug_enabled)
- << StringPrintf("nfa_dm_send_tag_deselect_cmd");
- p_msg = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
-
- if (p_msg) {
- if (protocol == NFC_PROTOCOL_ISO_DEP) {
- /* send one byte of 0xc2 as as deselect command to Tag */
- p_msg->len = 1;
- p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
- p = (uint8_t*)(p_msg + 1) + p_msg->offset;
- *p = NFA_RW_TAG_DESELECT_CMD;
- } else if (protocol == NFC_PROTOCOL_T2T) {
- p_msg->len = NFA_RW_TAG_SLP_REQ_LEN;
- p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
- p = (uint8_t*)(p_msg + 1) + p_msg->offset;
- memcpy((uint8_t*)(p_msg + 1) + p_msg->offset, NFA_RW_TAG_SLP_REQ,
- p_msg->len);
- } else {
- GKI_freebuf(p_msg);
- return;
- }
- NFC_SendData(NFC_RF_CONN_ID, p_msg);
- }
-}
diff --git a/src/nfa/dm/nfa_dm_ndef.cc b/src/nfa/dm/nfa_dm_ndef.cc
index e5361cd..48aa844 100644
--- a/src/nfa/dm/nfa_dm_ndef.cc
+++ b/src/nfa/dm/nfa_dm_ndef.cc
@@ -270,8 +270,9 @@
/* If absolute URI, then compare URI for match (skip over uri_id in
* ndef payload) */
if ((p_cb->p_ndef_handler[i]->uri_id != NFA_NDEF_URI_ID_ABSOLUTE) ||
- (memcmp(&p_payload[1], p_cb->p_ndef_handler[i]->name,
- p_cb->p_ndef_handler[i]->name_len) == 0)) {
+ ((payload_len > p_cb->p_ndef_handler[i]->name_len) &&
+ (memcmp(&p_payload[1], p_cb->p_ndef_handler[i]->name,
+ p_cb->p_ndef_handler[i]->name_len) == 0))) {
/* Handler found. */
break;
}
@@ -284,6 +285,9 @@
/* Handler is absolute URI but NDEF is using prefix abrieviation.
* Compare URI prefix */
if ((p_payload[0] < NFA_DM_NDEF_WKT_URI_STR_TBL_SIZE) &&
+ strlen(
+ (const char*)nfa_dm_ndef_wkt_uri_str_tbl[p_payload[0]]) >=
+ p_cb->p_ndef_handler[i]->name_len &&
(memcmp(p_cb->p_ndef_handler[i]->name,
(char*)nfa_dm_ndef_wkt_uri_str_tbl[p_payload[0]],
p_cb->p_ndef_handler[i]->name_len) == 0)) {
@@ -300,6 +304,8 @@
* URI. Compare URI prefix */
if ((p_cb->p_ndef_handler[i]->uri_id <
NFA_DM_NDEF_WKT_URI_STR_TBL_SIZE) &&
+ payload_len > strlen((const char*)nfa_dm_ndef_wkt_uri_str_tbl
+ [p_cb->p_ndef_handler[i]->uri_id]) &&
(memcmp(&p_payload[1],
nfa_dm_ndef_wkt_uri_str_tbl[p_cb->p_ndef_handler[i]
->uri_id],
diff --git a/src/nfa/hci/nfa_hci_act.cc b/src/nfa/hci/nfa_hci_act.cc
index 4ad9754..fbc4fbf 100644
--- a/src/nfa/hci/nfa_hci_act.cc
+++ b/src/nfa/hci/nfa_hci_act.cc
@@ -1413,7 +1413,7 @@
/* Something wrong, NVRAM data could be corrupt or first start with
* default session id */
nfa_hciu_send_clear_all_pipe_cmd();
- nfa_hci_cb.b_hci_netwk_reset = true;
+ nfa_hci_cb.b_hci_new_sessionId = true;
if (data_len < NFA_HCI_SESSION_ID_LEN) {
android_errorWriteLog(0x534e4554, "124524315");
}
@@ -1423,9 +1423,15 @@
case NFA_HCI_ANY_OPEN_PIPE:
nfa_hci_cb.cfg.admin_gate.pipe01_state = NFA_HCI_PIPE_OPENED;
-
if (nfa_hci_cb.b_hci_netwk_reset) {
+ /* Something wrong, NVRAM data could be corrupt or first start with
+ * default session id */
+ nfa_hciu_send_clear_all_pipe_cmd();
nfa_hci_cb.b_hci_netwk_reset = false;
+ nfa_hci_cb.b_hci_new_sessionId = true;
+ } else if (nfa_hci_cb.b_hci_new_sessionId) {
+ nfa_hci_cb.b_hci_new_sessionId = false;
+
/* Session ID is reset, Set New session id */
memcpy(
&nfa_hci_cb.cfg.admin_gate.session_id[NFA_HCI_SESSION_ID_LEN / 2],
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/nfa/hci/nfa_hci_utils.cc b/src/nfa/hci/nfa_hci_utils.cc
index d64fe6c..1751af3 100644
--- a/src/nfa/hci/nfa_hci_utils.cc
+++ b/src/nfa/hci/nfa_hci_utils.cc
@@ -25,6 +25,7 @@
#include <android-base/stringprintf.h>
#include <base/logging.h>
+#include <log/log.h>
#include "nfa_dm_int.h"
#include "nfa_hci_api.h"
@@ -305,8 +306,13 @@
bool first_pkt = true;
uint16_t data_len;
tNFA_STATUS status = NFA_STATUS_OK;
- uint16_t max_seg_hcp_pkt_size = nfa_hci_cb.buff_size - NCI_DATA_HDR_SIZE;
-
+ uint16_t max_seg_hcp_pkt_size;
+ if (nfa_hci_cb.buff_size > (NCI_DATA_HDR_SIZE + 2)) {
+ max_seg_hcp_pkt_size = nfa_hci_cb.buff_size - NCI_DATA_HDR_SIZE;
+ } else {
+ android_errorWriteLog(0x534e4554, "124521372");
+ return NFA_STATUS_NO_BUFFERS;
+ }
char buff[100];
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
@@ -349,8 +355,12 @@
memcpy(p_data, p_msg, data_len);
p_buf->len += data_len;
- msg_len -= data_len;
- if (msg_len > 0) p_msg += data_len;
+ if (msg_len >= data_len) {
+ msg_len -= data_len;
+ p_msg += data_len;
+ } else {
+ msg_len = 0;
+ }
}
if (HCI_LOOPBACK_DEBUG == NFA_HCI_DEBUG_ON)
diff --git a/src/nfa/include/nfa_hci_int.h b/src/nfa/include/nfa_hci_int.h
index 5d13f95..456c279 100644
--- a/src/nfa/include/nfa_hci_int.h
+++ b/src/nfa/include/nfa_hci_int.h
@@ -371,6 +371,7 @@
uint8_t active_host[NFA_HCI_MAX_HOST_IN_NETWORK];
uint8_t reset_host[NFA_HCI_MAX_HOST_IN_NETWORK]; /* List of host reseting */
bool b_low_power_mode; /* Host controller in low power mode */
+ bool b_hci_new_sessionId; /* Command sent to set a new session Id */
bool b_hci_netwk_reset; /* Command sent to reset HCI Network */
bool w4_hci_netwk_init; /* Wait for other host in network to initialize */
TIMER_LIST_ENT timer; /* Timer to avoid indefinitely waiting for response */
diff --git a/src/nfc/ndef/ndef_utils.cc b/src/nfc/ndef/ndef_utils.cc
index 128cb69..6a95ebe 100644
--- a/src/nfc/ndef/ndef_utils.cc
+++ b/src/nfc/ndef/ndef_utils.cc
@@ -198,6 +198,10 @@
}
/* Check for OOB */
+ if (payload_len + type_len + id_len < payload_len ||
+ payload_len + type_len + id_len > msg_len) {
+ return (NDEF_MSG_LENGTH_MISMATCH);
+ }
p_new = p_rec + (payload_len + type_len + id_len);
if (p_rec > p_new || p_end < p_new) {
android_errorWriteLog(0x534e4554, "126200054");
diff --git a/src/nfc/nfc/nfc_ncif.cc b/src/nfc/nfc/nfc_ncif.cc
index 464fb51..266ad90 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);
@@ -1546,6 +1564,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/ce_t4t.cc b/src/nfc/tags/ce_t4t.cc
index 74c2463..19dfa96 100644
--- a/src/nfc/tags/ce_t4t.cc
+++ b/src/nfc/tags/ce_t4t.cc
@@ -646,6 +646,13 @@
if (instruct == T4T_CMD_INS_SELECT) {
/* P1 Byte is already parsed */
if (select_type == T4T_CMD_P1_SELECT_BY_FILE_ID) {
+ /* CLA+INS+P1+P2+Lc+FILE_ID = T4T_CMD_MAX_HDR_SIZE + T4T_FILE_ID_SIZE */
+ if (p_c_apdu->len < (T4T_CMD_MAX_HDR_SIZE + T4T_FILE_ID_SIZE)) {
+ LOG(ERROR) << "Wrong length";
+ GKI_freebuf(p_c_apdu);
+ ce_t4t_send_status(T4T_RSP_WRONG_LENGTH);
+ return;
+ }
ce_t4t_process_select_file_cmd(p_cmd);
} else {
LOG(ERROR) << StringPrintf("CET4T: Bad P1 byte (0x%02X)", select_type);
diff --git a/src/nfc/tags/rw_i93.cc b/src/nfc/tags/rw_i93.cc
index 0f38ab7..1483cdc 100644
--- a/src/nfc/tags/rw_i93.cc
+++ b/src/nfc/tags/rw_i93.cc
@@ -1942,6 +1942,9 @@
block = (p_i93->rw_offset / p_i93->block_size);
last_block = (p_i93->ndef_tlv_last_offset / p_i93->block_size);
+ if (length == 0) {
+ rw_i93_handle_error(NFC_STATUS_FAILED);
+ }
if ((*p) & I93_BLOCK_LOCKED) {
if (block <= last_block) {
p_i93->intl_flags |= RW_I93_FLAG_READ_ONLY;
@@ -2616,7 +2619,7 @@
(p_i93->product_version == RW_I93_TAG_IT_HF_I_PRO_CHIP_INLAY) ||
((p_i93->uid[1] == I93_UID_IC_MFG_CODE_NXP) &&
(p_i93->ic_reference & I93_ICODE_IC_REF_MBREAD_MASK))) {
- if ((*p) & I93_BLOCK_LOCKED) {
+ if (length == 0 || ((*p) & I93_BLOCK_LOCKED)) {
rw_i93_handle_error(NFC_STATUS_FAILED);
break;
}
diff --git a/src/nfc/tags/rw_mfc.cc b/src/nfc/tags/rw_mfc.cc
index ef5bfdc..e78f3fc 100644
--- a/src/nfc/tags/rw_mfc.cc
+++ b/src/nfc/tags/rw_mfc.cc
@@ -405,10 +405,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]);
@@ -1349,6 +1346,7 @@
tRW_DETECT_NDEF_DATA ndef_data;
DLOG_IF(INFO, nfc_debug_enabled) << __func__ << " State=" << p_mfc->state;
+ evt_data.status = NFC_STATUS_FAILED;
/* Retry sending command if retry-count < max */
if (rw_cb.cur_retry < RW_MAX_RETRIES) {
diff --git a/src/nfc/tags/rw_t3t.cc b/src/nfc/tags/rw_t3t.cc
index e0121de..d017ac3 100644
--- a/src/nfc/tags/rw_t3t.cc
+++ b/src/nfc/tags/rw_t3t.cc
@@ -1026,6 +1026,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;
+ }
}
}
diff --git a/src/nfc/tags/rw_t4t.cc b/src/nfc/tags/rw_t4t.cc
index 92ff5d9..b7b6144 100644
--- a/src/nfc/tags/rw_t4t.cc
+++ b/src/nfc/tags/rw_t4t.cc
@@ -2116,7 +2116,8 @@
status = false;
if (option == RW_T4T_CHK_EMPTY_I_BLOCK) {
/* use empty I block for presence check */
- p_data = (NFC_HDR*)GKI_getbuf(NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE);
+ p_data = (NFC_HDR*)GKI_getbuf(sizeof(NFC_HDR) + NCI_MSG_OFFSET_SIZE +
+ NCI_DATA_HDR_SIZE);
if (p_data != nullptr) {
p_data->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
p_data->len = 0;