* [PATCH] media: dib9000: bound the mailbox reply length in dib9000_mbx_get_message_attr
@ 2026-07-01 9:56 Maoyi Xie
0 siblings, 0 replies; only message in thread
From: Maoyi Xie @ 2026-07-01 9:56 UTC (permalink / raw)
To: Mauro Carvalho Chehab; +Cc: Kees Cook, linux-media, linux-kernel
dib9000_mbx_get_message_attr() copies a mailbox reply into the caller
buffer with a length the demod controls:
*size = (*block & 0xff) - 1;
memcpy(msg, block + 1, (*size) * 2);
*block is a cached mailbox word whose low byte comes from the DiB9000 demod
over I2C. *size is a u8. A low byte of 0 wraps to 255, so the memcpy runs
510 bytes. The callers pass small fixed stack buffers. check_version()
passes a u8 r[4] and the APB helpers a u16 mb[10], with no check. fw_init()
has a check but runs it after the copy. check_version() runs on the
firmware boot path, so a normal frontend bring-up reaches it.
dib9000_mbx_get_message_attr() now takes the buffer size in words and
rejects an oversized reply. Each caller passes its buffer size.
Fixes: dd316c6bacc2 ("[media] DIB9000: initial support added")
Cc: stable@vger.kernel.org
Signed-off-by: Maoyi Xie <maoyixie.tju@gmail.com>
---
drivers/media/dvb-frontends/dib9000.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/drivers/media/dvb-frontends/dib9000.c b/drivers/media/dvb-frontends/dib9000.c
index cb7c943225bd3..19c1853e6af2d 100644
--- a/drivers/media/dvb-frontends/dib9000.c
+++ b/drivers/media/dvb-frontends/dib9000.c
@@ -390,7 +390,7 @@ static inline int dib9000_write_word_attr(struct dib9000_state *state, u16 reg,
#define dib9000_write16_noinc_attr(state, reg, buf, len, attribute) dib9000_write16_attr(state, reg, buf, len, DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT | (attribute))
#define dib9000_mbx_send(state, id, data, len) dib9000_mbx_send_attr(state, id, data, len, 0)
-#define dib9000_mbx_get_message(state, id, msg, len) dib9000_mbx_get_message_attr(state, id, msg, len, 0)
+#define dib9000_mbx_get_message(state, id, msg, len, words) dib9000_mbx_get_message_attr(state, id, msg, len, words, 0)
#define MAC_IRQ (1 << 1)
#define IRQ_POL_MSK (1 << 4)
@@ -725,7 +725,7 @@ static int dib9000_mbx_process(struct dib9000_state *state, u16 attr)
return ret;
}
-static int dib9000_mbx_get_message_attr(struct dib9000_state *state, u16 id, u16 * msg, u8 * size, u16 attr)
+static int dib9000_mbx_get_message_attr(struct dib9000_state *state, u16 id, u16 *msg, u8 *size, u16 msg_words, u16 attr)
{
u8 i;
u16 *block;
@@ -738,6 +738,10 @@ static int dib9000_mbx_get_message_attr(struct dib9000_state *state, u16 id, u16
block = state->platform.risc.message_cache[i];
if ((*block >> 8) == id) {
*size = (*block & 0xff) - 1;
+ if (*size > msg_words) {
+ *block = 0;
+ return -1;
+ }
memcpy(msg, block + 1, (*size) * 2);
*block = 0; /* free the block */
i = 0; /* signal that we found a message */
@@ -770,7 +774,7 @@ static int dib9000_risc_check_version(struct dib9000_state *state)
if (dib9000_mbx_send(state, OUT_MSG_REQ_VERSION, &fw_version, 1) != 0)
return -EIO;
- if (dib9000_mbx_get_message(state, IN_MSG_VERSION, (u16 *) r, &size) < 0)
+ if (dib9000_mbx_get_message(state, IN_MSG_VERSION, (u16 *) r, &size, sizeof(r) / sizeof(u16)) < 0)
return -EIO;
fw_version = (r[0] << 8) | r[1];
@@ -1022,7 +1026,7 @@ static int dib9000_risc_apb_access_read(struct dib9000_state *state, u32 address
mb[0] = (u16) address;
mb[1] = len / 2;
dib9000_mbx_send_attr(state, OUT_MSG_BRIDGE_APB_R, mb, 2, attribute);
- switch (dib9000_mbx_get_message_attr(state, IN_MSG_END_BRIDGE_APB_RW, mb, &s, attribute)) {
+ switch (dib9000_mbx_get_message_attr(state, IN_MSG_END_BRIDGE_APB_RW, mb, &s, ARRAY_SIZE(mb), attribute)) {
case 1:
s--;
for (i = 0; i < s; i++) {
@@ -1056,7 +1060,7 @@ static int dib9000_risc_apb_access_write(struct dib9000_state *state, u32 addres
mb[1 + len / 2] = b[len - 1] << 8;
dib9000_mbx_send_attr(state, OUT_MSG_BRIDGE_APB_W, mb, (3 + len) / 2, attribute);
- return dib9000_mbx_get_message_attr(state, IN_MSG_END_BRIDGE_APB_RW, mb, &s, attribute) == 1 ? 0 : -EINVAL;
+ return dib9000_mbx_get_message_attr(state, IN_MSG_END_BRIDGE_APB_RW, mb, &s, ARRAY_SIZE(mb), attribute) == 1 ? 0 : -EINVAL;
}
static int dib9000_fw_memmbx_sync(struct dib9000_state *state, u8 i)
@@ -1135,7 +1139,7 @@ static int dib9000_fw_init(struct dib9000_state *state)
if (dib9000_mbx_send(state, OUT_MSG_FE_FW_DL, NULL, 0) != 0)
return -EIO;
- if (dib9000_mbx_get_message(state, IN_MSG_FE_FW_DL_DONE, b, &size) < 0)
+ if (dib9000_mbx_get_message(state, IN_MSG_FE_FW_DL_DONE, b, &size, ARRAY_SIZE(b)) < 0)
return -EIO;
if (size > ARRAY_SIZE(b)) {
--
2.34.1
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-07-01 9:56 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-07-01 9:56 [PATCH] media: dib9000: bound the mailbox reply length in dib9000_mbx_get_message_attr Maoyi Xie
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox