drivers/firmware/tegra/bpmp-debugfs.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-)
The BPMP debugfs response parser reads u32 fields and NUL-terminated
names from a size-delimited reply. seqbuf_read() currently clamps a
request to the remaining input bytes and can return success after a
short read. Consequently, a truncated u32 can be partially copied and
the directory parser can continue with an incomplete field.
seqbuf_read_str() also moves the cursor one byte beyond the current
range when no NUL terminator exists, and reports the failure only after
changing the parser state.
Make fixed-width reads fail when the full request is unavailable and
require a terminator within the current range before advancing the
cursor. Use a signed return type for the status helper so its error
contract matches its callers.
Fixes: f2381f652266 ("firmware: tegra: Add BPMP debugfs support")
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
---
drivers/firmware/tegra/bpmp-debugfs.c | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/drivers/firmware/tegra/bpmp-debugfs.c b/drivers/firmware/tegra/bpmp-debugfs.c
index 33c6300af964..bb2ce5be2e78 100644
--- a/drivers/firmware/tegra/bpmp-debugfs.c
+++ b/drivers/firmware/tegra/bpmp-debugfs.c
@@ -32,7 +32,7 @@ static size_t seqbuf_avail(struct seqbuf *seqbuf)
return seqbuf->pos < seqbuf->size ? seqbuf->size - seqbuf->pos : 0;
}
-static size_t seqbuf_status(struct seqbuf *seqbuf)
+static int seqbuf_status(struct seqbuf *seqbuf)
{
return seqbuf->pos <= seqbuf->size ? 0 : -EOVERFLOW;
}
@@ -44,7 +44,9 @@ static int seqbuf_eof(struct seqbuf *seqbuf)
static int seqbuf_read(struct seqbuf *seqbuf, void *buf, size_t nbyte)
{
- nbyte = min(nbyte, seqbuf_avail(seqbuf));
+ if (nbyte > seqbuf_avail(seqbuf))
+ return -EOVERFLOW;
+
memcpy(buf, seqbuf->buf + seqbuf->pos, nbyte);
seqbuf->pos += nbyte;
return seqbuf_status(seqbuf);
@@ -57,9 +59,16 @@ static int seqbuf_read_u32(struct seqbuf *seqbuf, u32 *v)
static int seqbuf_read_str(struct seqbuf *seqbuf, const char **str)
{
+ size_t avail;
+ size_t len;
+
+ avail = seqbuf_avail(seqbuf);
*str = seqbuf->buf + seqbuf->pos;
- seqbuf->pos += strnlen(*str, seqbuf_avail(seqbuf));
- seqbuf->pos++;
+ len = strnlen(*str, avail);
+ if (len == avail)
+ return -EOVERFLOW;
+
+ seqbuf->pos += len + 1;
return seqbuf_status(seqbuf);
}
--
2.43.0
© 2016 - 2026 Red Hat, Inc.