On Tue, Jul 7, 2026 at 12:08 PM <[email protected]> wrote:
>
> From: Alistair Francis <[email protected]>
>
> It was possible that a guest could overflow the `doe_cap->write_mbox`
> buffer by writing more then PCI_DOE_DW_SIZE_MAX dwords.
> `doe_cap->write_mbox_len` would continue to increment and there were no
> bounds checks on the length when offsetting into doe_cap->write_mbox.
>
> This patch adds a check and reports a guest error if we would overflow.
>
> On an overflow we also silenty discard the entire object as instructed
> to do in the PCIe spec when the length specified in the header
> (up to PCI_DOE_DW_SIZE_MAX dwords) doesn't match the length of the
> object.
>
> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3679
> Signed-off-by: Alistair Francis <[email protected]>
Thanks!
Applied to riscv-to-apply.next
Alistair
> ---
> hw/pci/pcie_doe.c | 27 +++++++++++++++++++++++----
> 1 file changed, 23 insertions(+), 4 deletions(-)
>
> diff --git a/hw/pci/pcie_doe.c b/hw/pci/pcie_doe.c
> index 2210f86968..1bc2b45781 100644
> --- a/hw/pci/pcie_doe.c
> +++ b/hw/pci/pcie_doe.c
> @@ -78,14 +78,21 @@ static bool pcie_doe_discovery(DOECap *doe_cap)
> return true;
> }
>
> +static void pcie_doe_reset_write_mbox(DOECap *st)
> +{
> + st->write_mbox_len = 0;
> +
> + memset(st->write_mbox, 0, PCI_DOE_DW_SIZE_MAX * DWORD_BYTE);
> +}
> +
> static void pcie_doe_reset_mbox(DOECap *st)
> {
> st->read_mbox_idx = 0;
> st->read_mbox_len = 0;
> - st->write_mbox_len = 0;
>
> memset(st->read_mbox, 0, PCI_DOE_DW_SIZE_MAX * DWORD_BYTE);
> - memset(st->write_mbox, 0, PCI_DOE_DW_SIZE_MAX * DWORD_BYTE);
> +
> + pcie_doe_reset_write_mbox(st);
> }
>
> void pcie_doe_init(PCIDevice *dev, DOECap *doe_cap, uint16_t offset,
> @@ -356,8 +363,20 @@ void pcie_doe_write_config(DOECap *doe_cap,
> if (size != DWORD_BYTE) {
> return;
> }
> - doe_cap->write_mbox[doe_cap->write_mbox_len] = val;
> - doe_cap->write_mbox_len++;
> + if (doe_cap->write_mbox_len < PCI_DOE_DW_SIZE_MAX) {
> + doe_cap->write_mbox[doe_cap->write_mbox_len] = val;
> + doe_cap->write_mbox_len++;
> + } else {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "Mailbox write length (%d) overflow\n",
> + doe_cap->write_mbox_len);
> + /*
> + * Too much data has been written, it can't
> + * "match the Length indicated in DOE Data Object Header 2"
> + * so we drop the entire object.
> + */
> + pcie_doe_reset_write_mbox(doe_cap);
> + }
> break;
> case PCI_EXP_DOE_CAP:
> /* fallthrough */
> --
> 2.54.0
>