Commit a2fbf1785b for qemu.org

commit a2fbf1785b7a464d61c0f60c4ad0a86d82925e5d
Author: Denis V. Lunev <den@openvz.org>
Date:   Mon Aug 17 23:44:59 2026 +0200

    hw/ide/ahci: clear cur_cmd when the command list is unmapped

    ahci_unmap_clb_address() drops the CLB mapping but leaves cur_cmd
    pointing into it. The cancel added by commit d9f78431d8 covers the
    buffered reads, and ide_cancel_dma_sync() drains bus->dma->aiocb, but
    neither reaches IDEState::pio_aiocb: a PIO write started before the
    guest cleared PxCMD.ST completes afterwards and runs its second DRQ
    phase against the stale header.

    That is harmless while the CLB is direct RAM, because unmapping it
    changes nothing. It is a use-after-free once PxCLB points at an MMIO
    region, where address_space_map() hands out a bounce buffer that
    dma_memory_unmap() then frees.

    Clear cur_cmd after the cancel, so nothing reachable from a later
    completion still refers to the freed mapping.

    Reported-by: Katherine Leaver <katherine.j.leaver@gmail.com>
    Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3719
    Resolves: https://gitlab.com/qemu-project/qemu/-/issues/4043
    Cc: John Snow <jsnow@redhat.com>
    Cc: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
    Signed-off-by: Denis V. Lunev <den@openvz.org>

diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 995b40efd5..4c138b0c51 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -743,6 +743,12 @@ static void ahci_unmap_clb_address(AHCIDevice *ad)
     /* Cancel in-flight reads that would complete against a cleared cur_cmd. */
     ide_cancel_dma_sync(ide_bus_active_if(&ad->port));

+    /*
+     * Whatever survives the cancel must not be left pointing into the
+     * mapping this function is about to drop.
+     */
+    ad->cur_cmd = NULL;
+
     if (ad->lst == NULL) {
         trace_ahci_unmap_clb_address_null(ad->hba, ad->port_no);
         return;