Prevent Out of bounds read in llcp code

Modifies llcp_util.cc & llcp_link.cc to fix the OOB issues.

Test: Nfc Enable/Disable, Android Beam, Tag reading
Bug: 114237888
Bug: 114238578
Bug: 111699773
Bug: 111660010
Merged-In: Ie28888ddb9a5a2605ae32a27e3dba01c35ab3913
Change-Id: Ie28888ddb9a5a2605ae32a27e3dba01c35ab3913
(cherry picked from commit 23eb85a028780af14f617e27938540a52c18a8d5)
(cherry picked from commit b22787c49fb9e0e8233bd64cd11c5adafcd4d2db)
diff --git a/src/nfc/llcp/llcp_link.c b/src/nfc/llcp/llcp_link.c
index 5fa6a41..e2d2387 100644
--- a/src/nfc/llcp/llcp_link.c
+++ b/src/nfc/llcp/llcp_link.c
@@ -1128,7 +1128,7 @@
   agf_length = p_agf->len;
   p = (uint8_t*)(p_agf + 1) + p_agf->offset;
 
-  while (agf_length > 0) {
+  while (agf_length >= LLCP_PDU_HEADER_SIZE) {
     /* get length of PDU */
     p_pdu_length = p;
     BE_STREAM_TO_UINT16(pdu_length, p);
diff --git a/src/nfc/llcp/llcp_util.c b/src/nfc/llcp/llcp_util.c
index afd5749..6f10d12 100644
--- a/src/nfc/llcp/llcp_util.c
+++ b/src/nfc/llcp/llcp_util.c
@@ -22,7 +22,9 @@
  *
  ******************************************************************************/
 
+#include <log/log.h>
 #include <string.h>
+
 #include "bt_types.h"
 #include "gki.h"
 #include "llcp_defs.h"
@@ -43,19 +45,23 @@
 bool llcp_util_parse_link_params(uint16_t length, uint8_t* p_bytes) {
   uint8_t param_type, param_len, *p = p_bytes;
 
-  while (length) {
+  while (length >= 2) {
     BE_STREAM_TO_UINT8(param_type, p);
-    length--;
+    BE_STREAM_TO_UINT8(param_len, p);
+    if (length < param_len + 2) {
+      android_errorWriteLog(0x534e4554, "114238578");
+      LLCP_TRACE_ERROR0("llcp_util_parse_link_params (): Bad LTV's");
+      return false;
+    }
+    length -= param_len + 2;
 
     switch (param_type) {
       case LLCP_VERSION_TYPE:
-        BE_STREAM_TO_UINT8(param_len, p);
         BE_STREAM_TO_UINT8(llcp_cb.lcb.peer_version, p);
         LLCP_TRACE_DEBUG1("Peer Version - 0x%02X", llcp_cb.lcb.peer_version);
         break;
 
       case LLCP_MIUX_TYPE:
-        BE_STREAM_TO_UINT8(param_len, p);
         BE_STREAM_TO_UINT16(llcp_cb.lcb.peer_miu, p);
         llcp_cb.lcb.peer_miu &= LLCP_MIUX_MASK;
         llcp_cb.lcb.peer_miu += LLCP_DEFAULT_MIU;
@@ -63,20 +69,17 @@
         break;
 
       case LLCP_WKS_TYPE:
-        BE_STREAM_TO_UINT8(param_len, p);
         BE_STREAM_TO_UINT16(llcp_cb.lcb.peer_wks, p);
         LLCP_TRACE_DEBUG1("Peer WKS - 0x%04X", llcp_cb.lcb.peer_wks);
         break;
 
       case LLCP_LTO_TYPE:
-        BE_STREAM_TO_UINT8(param_len, p);
         BE_STREAM_TO_UINT8(llcp_cb.lcb.peer_lto, p);
         llcp_cb.lcb.peer_lto *= LLCP_LTO_UNIT; /* 10ms unit */
         LLCP_TRACE_DEBUG1("Peer LTO - %d ms", llcp_cb.lcb.peer_lto);
         break;
 
       case LLCP_OPT_TYPE:
-        BE_STREAM_TO_UINT8(param_len, p);
         BE_STREAM_TO_UINT8(llcp_cb.lcb.peer_opt, p);
         LLCP_TRACE_DEBUG1("Peer OPT - 0x%02X", llcp_cb.lcb.peer_opt);
         break;
@@ -88,13 +91,6 @@
         p += param_len;
         break;
     }
-
-    if (length >= param_len + 1)
-      length -= param_len + 1;
-    else {
-      LLCP_TRACE_ERROR0("llcp_util_parse_link_params (): Bad LTV's");
-      return false;
-    }
   }
   return true;
 }
@@ -465,13 +461,19 @@
   p_params->sn[0] = 0;
   p_params->sn[1] = 0;
 
-  while (length) {
+  while (length >= 2) {
     BE_STREAM_TO_UINT8(param_type, p);
-    length--;
+    BE_STREAM_TO_UINT8(param_len, p);
+    /* check remaining lengh */
+    if (length < param_len + 2) {
+      android_errorWriteLog(0x534e4554, "111660010");
+      LLCP_TRACE_ERROR0("llcp_util_parse_connect (): Bad LTV's");
+      return LLCP_STATUS_FAIL;
+    }
+    length -= param_len + 2;
 
     switch (param_type) {
       case LLCP_MIUX_TYPE:
-        BE_STREAM_TO_UINT8(param_len, p);
         BE_STREAM_TO_UINT16(p_params->miu, p);
         p_params->miu &= LLCP_MIUX_MASK;
         p_params->miu += LLCP_DEFAULT_MIU;
@@ -481,7 +483,6 @@
         break;
 
       case LLCP_RW_TYPE:
-        BE_STREAM_TO_UINT8(param_len, p);
         BE_STREAM_TO_UINT8(p_params->rw, p);
         p_params->rw &= 0x0F;
 
@@ -490,8 +491,6 @@
         break;
 
       case LLCP_SN_TYPE:
-        BE_STREAM_TO_UINT8(param_len, p);
-
         if (param_len == 0) {
           /* indicate that SN type is included without SN */
           p_params->sn[1] = LLCP_SN_TYPE;
@@ -515,14 +514,6 @@
         p += param_len;
         break;
     }
-
-    /* check remaining lengh */
-    if (length >= param_len + 1) {
-      length -= param_len + 1;
-    } else {
-      LLCP_TRACE_ERROR0("llcp_util_parse_connect (): Bad LTV's");
-      return LLCP_STATUS_FAIL;
-    }
   }
   return LLCP_STATUS_SUCCESS;
 }
@@ -599,13 +590,18 @@
   *p_miu = LLCP_DEFAULT_MIU;
   *p_rw = LLCP_DEFAULT_RW;
 
-  while (length) {
+  while (length >= 2) {
     BE_STREAM_TO_UINT8(param_type, p);
-    length--;
+    BE_STREAM_TO_UINT8(param_len, p);
+    if (length < param_len + 2) {
+      android_errorWriteLog(0x534e4554, "114237888");
+      LLCP_TRACE_ERROR0("llcp_util_parse_cc (): Bad LTV's");
+      return LLCP_STATUS_FAIL;
+    }
+    length -= param_len + 2;
 
     switch (param_type) {
       case LLCP_MIUX_TYPE:
-        BE_STREAM_TO_UINT8(param_len, p);
         BE_STREAM_TO_UINT16((*p_miu), p);
         (*p_miu) &= LLCP_MIUX_MASK;
         (*p_miu) += LLCP_DEFAULT_MIU;
@@ -614,7 +610,6 @@
         break;
 
       case LLCP_RW_TYPE:
-        BE_STREAM_TO_UINT8(param_len, p);
         BE_STREAM_TO_UINT8((*p_rw), p);
         (*p_rw) &= 0x0F;
 
@@ -628,13 +623,6 @@
         p += param_len;
         break;
     }
-
-    if (length >= param_len + 1)
-      length -= param_len + 1;
-    else {
-      LLCP_TRACE_ERROR0("llcp_util_parse_cc (): Bad LTV's");
-      return LLCP_STATUS_FAIL;
-    }
   }
   return LLCP_STATUS_SUCCESS;
 }