@samitouri / QOSamiQemu / commits / c7e6185454

hw/pci/pcie_doe: Check mailbox length for overflows

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 <alistair.francis@wdc.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Reviewed-by: Tao Tang <tangtao1634@phytium.com.cn> Message-ID: <20260707020750.788960-1-alistair.francis@wdc.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>

Alistair Francis committed Jul 7, 2026 at 12:07 UTC c7e61854544be3ebcc001a33d41807947866a739
1 file changed +23 -4
hw/pci/pcie_doe.c
+23 -4
@@ -78,14 +78,21 @@ static bool pcie_doe_discovery(DOECap *doe_cap)
78 return true;
79 }
80
81 +static void pcie_doe_reset_write_mbox(DOECap *st)
82 +{
83 + st->write_mbox_len = 0;
84 +
85 + memset(st->write_mbox, 0, PCI_DOE_DW_SIZE_MAX * DWORD_BYTE);
86 +}
87 +
88 static void pcie_doe_reset_mbox(DOECap *st)
89 {
90 st->read_mbox_idx = 0;
91 st->read_mbox_len = 0;
85 - st->write_mbox_len = 0;
92
93 memset(st->read_mbox, 0, PCI_DOE_DW_SIZE_MAX * DWORD_BYTE);
88 - memset(st->write_mbox, 0, PCI_DOE_DW_SIZE_MAX * DWORD_BYTE);
94 +
95 + pcie_doe_reset_write_mbox(st);
96 }
97
98 void pcie_doe_init(PCIDevice *dev, DOECap *doe_cap, uint16_t offset,
@@ -356,8 +363,20 @@ void pcie_doe_write_config(DOECap *doe_cap,
363 if (size != DWORD_BYTE) {
364 return;
365 }
359 - doe_cap->write_mbox[doe_cap->write_mbox_len] = val;
360 - doe_cap->write_mbox_len++;
366 + if (doe_cap->write_mbox_len < PCI_DOE_DW_SIZE_MAX) {
367 + doe_cap->write_mbox[doe_cap->write_mbox_len] = val;
368 + doe_cap->write_mbox_len++;
369 + } else {
370 + qemu_log_mask(LOG_GUEST_ERROR,
371 + "Mailbox write length (%d) overflow\n",
372 + doe_cap->write_mbox_len);
373 + /*
374 + * Too much data has been written, it can't
375 + * "match the Length indicated in DOE Data Object Header 2"
376 + * so we drop the entire object.
377 + */
378 + pcie_doe_reset_write_mbox(doe_cap);
379 + }
380 break;
381 case PCI_EXP_DOE_CAP:
382 /* fallthrough */