virtio-serial migration restore DoS
Imported by the "Security Issuer Importer" bot, on behalf of the original reporter who disclosed via qemu-security list:
- From:
Feifan Qian <bea1e@proton.me> - Date:
10 May, 2026 - Message ID:
<euDwgu95pIALn8TxRSiWEM6wGlQ4nMOhtzrqXFnkhd7nLo46_kN0kE-WtVmVEn7Is7CxGrRAIiVeQiA8aWIouyeRIPYDyv-nhLHgMF7JKC8=@proton.me>
NOTE: the original reporter can not be copied on this issue so cannot view this ticket while it remains marked confidential. If further information is needed about the disclosure, contact the reporter directly.
NOTE: this disclosure includes a report.md file which provides a markdown formatted version of the disclosure which may include more information that this bug description.
I'm writing to report a security vulnerability in QEMU's virtio-serial migration restore path. The affected component is the virtio-console/virtio-serial device state loader, which reads the saved active-port count from an incoming migration stream.
The issue has been reproduced against QEMU 11.0.50 (v11.0.0-759-gee7eb612be, commit ee7eb612) in the x86_64-softmmu target. The affected path is not specific to the qtest accelerator used by the proof of concept; qtest is only used to keep the reproducer small and avoid guest boot noise.
A migration peer, or a management workflow that loads a crafted VM state file, can set the saved virtio-serial nr_active_ports field to a very large value while keeping the saved port bitmap valid. The destination QEMU process then attempts an attacker-sized heap allocation before validating individual port records. The demonstrated impact is denial of service of the destination QEMU process during restore. I assess this as CVSS v3.1 6.5 Medium (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H).
I have attached disclosure.zip with a detailed technical report, full reproduction steps, and a minimal proof of concept. The PoC generates a real QEMU migration stream, patches only the saved nr_active_ports field, restores the mutated stream through QEMU's normal -incoming path, and shows GLib aborting after a failed 4 GiB allocation. The included debugger backtrace confirms the allocation occurs in fetch_active_ports_list() before per-port validation.
Please let me know if you need additional details, a different reproducer format, or coordination on disclosure timing. I can be reached by replying to this email.