diff mbox series

[v3,1/2] media: venus: fix TOCTOU vulnerability when reading packets from shared memory

Message ID 20250514-venus-fixes-v3-1-32298566011f@quicinc.com
State New
Headers show
Series venus driver fixes for vulnerabilities due to unexpected firmware payload | expand

Commit Message

Dikshita Agarwal May 14, 2025, 1:38 p.m. UTC
From: Vedang Nagar <quic_vnagar@quicinc.com>

Currently, Time-Of-Check to Time-Of-Use (TOCTOU) issue happens when
handling packets from firmware via shared memory.

The problematic code pattern:

u32 dwords = *rd_ptr >> 2;
if (!dwords || (dwords << 2) >  IFACEQ_VAR_HUGE_PKT_SIZE))
   return -EINVAL;

memcpy(pkt, rd_ptr, dwords << 2);

Here, *rd_ptr is used to determine the size of the packet and is
validated. However, since rd_ptr points to firmware-controlled memory,
the firmware could change the contents (e.g., embedded header fields
like pkt->hdr.size) after the size was validated but before or during
the memcpy() call.

This opens up a race window where a malicious or buggy firmware could
inject inconsistent or malicious data, potentially leading to
information leaks, driver crashes, or undefined behavior.

Fix this by rechecking the packet size field from shared memory
immediately before the memcpy() to ensure it has not beenn altered.

Fixes: d96d3f30c0f2 ("[media] media: venus: hfi: add Venus HFI files")
Signed-off-by: Vedang Nagar <quic_vnagar@quicinc.com>
Co-developed-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
---
 drivers/media/platform/qcom/venus/hfi_venus.c | 3 +++
 1 file changed, 3 insertions(+)
diff mbox series

Patch

diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c
index b5f2ea8799507f9b83f1529e70061ea89a9cc5c8..163c8d16530bc44a84b2b21076e6189d476fe360 100644
--- a/drivers/media/platform/qcom/venus/hfi_venus.c
+++ b/drivers/media/platform/qcom/venus/hfi_venus.c
@@ -295,6 +295,9 @@  static int venus_read_queue(struct venus_hfi_device *hdev,
 	new_rd_idx = rd_idx + dwords;
 	if (((dwords << 2) <= IFACEQ_VAR_HUGE_PKT_SIZE) && rd_idx <= qsize) {
 		if (new_rd_idx < qsize) {
+			if ((*rd_ptr >> 2) != dwords)
+				return -EINVAL;
+
 			memcpy(pkt, rd_ptr, dwords << 2);
 		} else {
 			size_t len;