Skip to content

Commit adf3d0a

Browse files
committed
FROMLIST: rpmsg: glink: smem: validate index before fifo read write
Fifo head and tail index can be modified with wrong values from untrusted remote procs. Glink smem is not validating these index before using to read or write fifo. This can result in out of bound memory access if head and tail have incorrect values. Add check for validation of head and tail index. This check will put index within fifo boundaries, so that no invalid memory access is made. Further this may result in certain packet drops unless glink finds a valid packet header in fifo again and recovers. Crash signature and calltrace with wrong head and tail values: Internal error: Oops: 96000007 [#1] PREEMPT SMP pc : __memcpy_fromio+0x34/0xb4 lr : glink_smem_rx_peak+0x68/0x94 __memcpy_fromio+0x34/0xb4 glink_smem_rx_peak+0x68/0x94 qcom_glink_native_intr+0x90/0x888 Link: https://lore.kernel.org/r/20231201110631.669085-1-quic_deesin@quicinc.com Signed-off-by: Deepak Kumar Singh <quic_deesin@quicinc.com>
1 parent 82f2b0b commit adf3d0a

File tree

1 file changed

+18
-3
lines changed

1 file changed

+18
-3
lines changed

drivers/rpmsg/qcom_glink_smem.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,14 @@ static size_t glink_smem_rx_avail(struct qcom_glink_pipe *np)
8686
tail = le32_to_cpu(*pipe->tail);
8787

8888
if (head < tail)
89-
return pipe->native.length - tail + head;
89+
len = pipe->native.length - tail + head;
9090
else
91-
return head - tail;
91+
len = head - tail;
92+
93+
if (WARN_ON_ONCE(len > pipe->native.length))
94+
len = 0;
95+
96+
return len;
9297
}
9398

9499
static void glink_smem_rx_peek(struct qcom_glink_pipe *np,
@@ -99,6 +104,10 @@ static void glink_smem_rx_peek(struct qcom_glink_pipe *np,
99104
u32 tail;
100105

101106
tail = le32_to_cpu(*pipe->tail);
107+
108+
if (WARN_ON_ONCE(tail > pipe->native.length))
109+
return;
110+
102111
tail += offset;
103112
if (tail >= pipe->native.length)
104113
tail -= pipe->native.length;
@@ -121,7 +130,7 @@ static void glink_smem_rx_advance(struct qcom_glink_pipe *np,
121130

122131
tail += count;
123132
if (tail >= pipe->native.length)
124-
tail -= pipe->native.length;
133+
tail %= pipe->native.length;
125134

126135
*pipe->tail = cpu_to_le32(tail);
127136
}
@@ -146,6 +155,9 @@ static size_t glink_smem_tx_avail(struct qcom_glink_pipe *np)
146155
else
147156
avail -= FIFO_FULL_RESERVE + TX_BLOCKED_CMD_RESERVE;
148157

158+
if (WARN_ON_ONCE(avail > pipe->native.length))
159+
avail = 0;
160+
149161
return avail;
150162
}
151163

@@ -155,6 +167,9 @@ static unsigned int glink_smem_tx_write_one(struct glink_smem_pipe *pipe,
155167
{
156168
size_t len;
157169

170+
if (WARN_ON_ONCE(head > pipe->native.length))
171+
return head;
172+
158173
len = min_t(size_t, count, pipe->native.length - head);
159174
if (len)
160175
memcpy(pipe->fifo + head, data, len);

0 commit comments

Comments
 (0)