Improve AGF PDU integrity check to prevent OOB error
Test: Nfc Enable/Disable; Android Beam; Tag reading
Bug: 116791157
Merged-In: I981e867301007b7398d59727f60892824b722735
Change-Id: I981e867301007b7398d59727f60892824b722735
(cherry picked from commit 4ec764241242ae18ec50dbc7af1fa093dc8e2662)
diff --git a/src/nfc/llcp/llcp_link.c b/src/nfc/llcp/llcp_link.c
index e2d2387..78d3b51 100644
--- a/src/nfc/llcp/llcp_link.c
+++ b/src/nfc/llcp/llcp_link.c
@@ -22,6 +22,7 @@
*
******************************************************************************/
+#include <log/log.h>
#include <string.h>
#include "bt_types.h"
#include "gki.h"
@@ -1088,7 +1089,7 @@
static void llcp_link_proc_agf_pdu(NFC_HDR* p_agf) {
uint16_t agf_length;
uint8_t *p, *p_info, *p_pdu_length;
- uint16_t pdu_hdr, pdu_length;
+ uint16_t pdu_hdr, pdu_length, pdu_num;
uint8_t dsap, ptype, ssap;
p_agf->len -= LLCP_PDU_HEADER_SIZE;
@@ -1099,10 +1100,16 @@
*/
agf_length = p_agf->len;
p = (uint8_t*)(p_agf + 1) + p_agf->offset;
+ pdu_num = 0;
while (agf_length > 0) {
if (agf_length > LLCP_PDU_AGF_LEN_SIZE) {
BE_STREAM_TO_UINT16(pdu_length, p);
+ if (pdu_length < LLCP_PDU_HEADER_SIZE) {
+ LLCP_TRACE_ERROR0(
+ "llcp_link_proc_agf_pdu (): Received invalid encapsulated PDU");
+ break;
+ }
agf_length -= LLCP_PDU_AGF_LEN_SIZE;
} else {
break;
@@ -1111,12 +1118,14 @@
if (pdu_length <= agf_length) {
p += pdu_length;
agf_length -= pdu_length;
+ pdu_num++;
} else {
break;
}
}
- if (agf_length != 0) {
+ if (agf_length != 0 || pdu_num < 2) {
+ android_errorWriteLog(0x534e4554, "116791157");
LLCP_TRACE_ERROR0("llcp_link_proc_agf_pdu (): Received invalid AGF PDU");
GKI_freebuf(p_agf);
return;
@@ -1154,6 +1163,9 @@
GKI_freebuf(p_agf);
llcp_link_deactivate(LLCP_LINK_REMOTE_INITIATED);
return;
+ } else if (ptype == LLCP_PDU_AGF_TYPE) {
+ LLCP_TRACE_ERROR0(
+ "llcp_link_proc_agf_pdu (): AGF PDU shall not be in AGF");
} else if (ptype == LLCP_PDU_SYMM_TYPE) {
LLCP_TRACE_ERROR0(
"llcp_link_proc_agf_pdu (): SYMM PDU exchange shall not be in AGF");