From: imaginos <imaginos32@gmail.com>
To: qemu-devel@nongnu.org
Cc: "Titus Rwantare" <titusr@google.com>,
"Tyrone Ting" <kfting@nuvoton.com>,
"Hao Wu" <wuhaotsh@google.com>,
"Philippe Mathieu-Daudé" <philmd@mailo.com>,
qemu-arm@nongnu.org, imaginos <imaginos32@gmail.com>
Subject: [PATCH] hw/i2c: pmbus: NUL-terminate strings received via block write
Date: Mon, 15 Jun 2026 00:21:31 +0200 [thread overview]
Message-ID: <20260614222131.5795-1-imaginos32@gmail.com> (raw)
The PMBus string registers (e.g. MFR_MODEL on the ADM1266) are writable
by the guest. pmbus_receive_block() can fill the destination field
completely, leaving no NUL terminator. When the value is later read back,
pmbus_send_string() calls strlen() on it, which reads past the end of the
array and returns a length that trips
g_assert(len + pmdev->out_buf_len < SMBUS_DATA_MAX_LEN);
aborting QEMU. This is guest-triggerable.
Add pmbus_receive_string(), the write-side mirror of pmbus_send_string(),
which reserves the last byte of the destination so the stored value is
always NUL-terminated, and use it for the ADM1266 MFR string registers.
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3388
Signed-off-by: imaginos <imaginos32@gmail.com>
---
hw/i2c/pmbus_device.c | 13 +++++++++++++
hw/sensor/adm1266.c | 7 +++----
include/hw/i2c/pmbus_device.h | 10 ++++++++++
3 files changed, 26 insertions(+), 4 deletions(-)
diff --git a/hw/i2c/pmbus_device.c b/hw/i2c/pmbus_device.c
index b1f9843f52..7c65d8c8b5 100644
--- a/hw/i2c/pmbus_device.c
+++ b/hw/i2c/pmbus_device.c
@@ -142,6 +142,19 @@ uint8_t pmbus_receive_block(PMBusDevice *pmdev, uint8_t *dest, size_t len)
return len;
}
+uint8_t pmbus_receive_string(PMBusDevice *pmdev, char *dest, size_t len)
+{
+ uint8_t rv;
+
+ if (len == 0) {
+ return 0;
+ }
+
+ rv = pmbus_receive_block(pmdev, (uint8_t *)dest, len - 1);
+ dest[len - 1] = '\0';
+ return rv;
+}
+
static uint64_t pmbus_receive_uint(PMBusDevice *pmdev)
{
diff --git a/hw/sensor/adm1266.c b/hw/sensor/adm1266.c
index 37d1cffd57..81545385a5 100644
--- a/hw/sensor/adm1266.c
+++ b/hw/sensor/adm1266.c
@@ -142,16 +142,15 @@ static int adm1266_write_data(PMBusDevice *pmdev, const uint8_t *buf,
switch (pmdev->code) {
case PMBUS_MFR_ID: /* R/W block */
- pmbus_receive_block(pmdev, (uint8_t *)s->mfr_id, sizeof(s->mfr_id));
+ pmbus_receive_string(pmdev, s->mfr_id, sizeof(s->mfr_id));
break;
case PMBUS_MFR_MODEL: /* R/W block */
- pmbus_receive_block(pmdev, (uint8_t *)s->mfr_model,
- sizeof(s->mfr_model));
+ pmbus_receive_string(pmdev, s->mfr_model, sizeof(s->mfr_model));
break;
case PMBUS_MFR_REVISION: /* R/W block*/
- pmbus_receive_block(pmdev, (uint8_t *)s->mfr_rev, sizeof(s->mfr_rev));
+ pmbus_receive_string(pmdev, s->mfr_rev, sizeof(s->mfr_rev));
break;
case ADM1266_SET_RTC: /* do nothing */
diff --git a/include/hw/i2c/pmbus_device.h b/include/hw/i2c/pmbus_device.h
index f195c11384..4c4d3e5ae2 100644
--- a/include/hw/i2c/pmbus_device.h
+++ b/include/hw/i2c/pmbus_device.h
@@ -518,6 +518,16 @@ void pmbus_send_string(PMBusDevice *state, const char *data);
*/
uint8_t pmbus_receive_block(PMBusDevice *pmdev, uint8_t *dest, size_t len);
+/**
+ * @brief Receive a Block Write and store it as a NUL-terminated string.
+ * Write-side mirror of pmbus_send_string(): guarantees dest is always a valid
+ * C string so later reads cannot run past the field. Use for string registers
+ * (e.g. MFR_ID, MFR_MODEL); use pmbus_receive_block() for binary blocks.
+ * @param dest - string buffer with enough capacity to receive the write
+ * @param len - the capacity of dest (the last byte is reserved for the NUL)
+ */
+uint8_t pmbus_receive_string(PMBusDevice *pmdev, char *dest, size_t len);
+
/**
* @brief Receive data over PMBus
* These methods help track how much data is being received over PMBus
--
2.43.0
reply other threads:[~2026-06-14 22:22 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260614222131.5795-1-imaginos32@gmail.com \
--to=imaginos32@gmail.com \
--cc=kfting@nuvoton.com \
--cc=philmd@mailo.com \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=titusr@google.com \
--cc=wuhaotsh@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.