From a38da14678b3f3eecc807683ef39fd04256f4d0f Mon Sep 17 00:00:00 2001 From: Deepak Kumar Singh Date: Fri, 1 Mar 2019 19:42:22 +0530 Subject: [PATCH] rpmsg : glink: validate head and tail index before fifo read write We are not validating head and tail index of tx and rx fifo before using to read or write fifo. This can result in out of bound memory access if head and tail have incorrect values. This patch adds check for validation of head and tail index. CRs-Fixed: 2398099 Change-Id: Ia8725a731cc7a45f7e13b09e1e62842ff44d53f3 Signed-off-by: Deepak Kumar Singh --- drivers/rpmsg/qcom_glink_smem.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/rpmsg/qcom_glink_smem.c b/drivers/rpmsg/qcom_glink_smem.c index 64a5ce324c7f..3ac53c9dcde4 100644 --- a/drivers/rpmsg/qcom_glink_smem.c +++ b/drivers/rpmsg/qcom_glink_smem.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (c) 2016, Linaro Ltd + * Copyright (c) 2016, 2019 Linaro Ltd */ #include @@ -71,9 +71,14 @@ static size_t glink_smem_rx_avail(struct qcom_glink_pipe *np) tail = le32_to_cpu(*pipe->tail); if (head < tail) - return pipe->native.length - tail + head; + len = pipe->native.length - tail + head; else - return head - tail; + len = head - tail; + + if (WARN_ON_ONCE(len > pipe->native.length)) + len = 0; + + return len; } static void glink_smem_rx_peak(struct qcom_glink_pipe *np, @@ -84,6 +89,10 @@ static void glink_smem_rx_peak(struct qcom_glink_pipe *np, u32 tail; tail = le32_to_cpu(*pipe->tail); + + if (WARN_ON_ONCE(tail > pipe->native.length)) + return; + tail += offset; if (tail >= pipe->native.length) tail -= pipe->native.length; @@ -106,7 +115,7 @@ static void glink_smem_rx_advance(struct qcom_glink_pipe *np, tail += count; if (tail > pipe->native.length) - tail -= pipe->native.length; + tail %= pipe->native.length; *pipe->tail = cpu_to_le32(tail); } @@ -131,6 +140,9 @@ static size_t glink_smem_tx_avail(struct qcom_glink_pipe *np) else avail -= FIFO_FULL_RESERVE + TX_BLOCKED_CMD_RESERVE; + if (WARN_ON_ONCE(avail > pipe->native.length)) + avail = 0; + return avail; } @@ -140,6 +152,9 @@ static unsigned int glink_smem_tx_write_one(struct glink_smem_pipe *pipe, { size_t len; + if (WARN_ON_ONCE(head > pipe->native.length)) + return head; + len = min_t(size_t, count, pipe->native.length - head); if (len) memcpy(pipe->fifo + head, data, len);