diff options
author | Caveh Jalali <caveh@chromium.org> | 2019-10-04 21:41:58 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2019-10-11 06:28:09 +0000 |
commit | 2461586d902615cf53f335c7d9ba161533dde4b8 (patch) | |
tree | e8f7bf90c533c1d39e36d7fedf2c6ad8a1fcd5e0 | |
parent | b9f24d30e9a379f1ab8d457e655b3e22301dd4ca (diff) | |
download | chrome-ec-2461586d902615cf53f335c7d9ba161533dde4b8.tar.gz |
tcpci: protect against buffer overflow
we need to sanity check data read from TCPCs to avoid buffer
overflows. the TCPC can return bogus size information which can cause
a buffer overflow when processing TCPM messages. if the claimed
message size is bogus, return an error.
BUG=b:142296767
BRANCH=none
TEST=EC no longer gets an exception
Change-Id: I7754c6e3d20847827b849423c5880756bae46393
Signed-off-by: Caveh Jalali <caveh@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1845587
Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
Commit-Queue: Caveh Jalali <caveh@google.com>
-rw-r--r-- | driver/tcpm/tcpci.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/driver/tcpm/tcpci.c b/driver/tcpm/tcpci.c index 9ceb4613e2..cc4a0341eb 100644 --- a/driver/tcpm/tcpci.c +++ b/driver/tcpm/tcpci.c @@ -7,6 +7,7 @@ #include "atomic.h" #include "anx74xx.h" +#include "compile_time_macros.h" #include "console.h" #include "ec_commands.h" #include "ps8xxx.h" @@ -414,6 +415,11 @@ int tcpci_tcpm_get_vbus_level(int port) } #endif +struct cached_tcpm_message { + uint32_t header; + uint32_t payload[7]; +}; + int tcpci_tcpm_get_message_raw(int port, uint32_t *payload, int *head) { int rv, cnt, reg = TCPC_REG_RX_DATA; @@ -428,6 +434,12 @@ int tcpci_tcpm_get_message_raw(int port, uint32_t *payload, int *head) rv = EC_ERROR_UNKNOWN; goto clear; } + cnt -= 3; + if (cnt > member_size(struct cached_tcpm_message, payload)) { + rv = EC_ERROR_UNKNOWN; + goto clear; + } + #ifdef CONFIG_USB_PD_DECODE_SOP rv = tcpc_read(port, TCPC_REG_RX_BUF_FRAME_TYPE, &frm); if (rv != EC_SUCCESS) { @@ -443,7 +455,6 @@ int tcpci_tcpm_get_message_raw(int port, uint32_t *payload, int *head) *head &= 0x0000ffff; *head |= PD_HEADER_SOP(frm & 7); #endif - cnt = cnt - 3; if (rv == EC_SUCCESS && cnt > 0) { tcpc_read_block(port, reg, (uint8_t *)payload, cnt); } @@ -455,11 +466,6 @@ clear: return rv; } -struct cached_tcpm_message { - uint32_t header; - uint32_t payload[7]; -}; - /* Cache depth needs to be power of 2 */ #define CACHE_DEPTH BIT(2) #define CACHE_DEPTH_MASK (CACHE_DEPTH - 1) |