Virtuozzo QEMU development (svt-core@virtuozzo.com)
 help / color / mirror / Atom feed
From: no-reply@sashiko.virtuozzo.com
To: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>,
	 svt-core@virtuozzo.com
Cc: andrey.drobyshev@virtuozzo.com
Subject: Re: [PATCH QEMU HCI-8.1 v2 21/24] VZ: migration/cpr-exec: abort cpr-exec if memory can't be preserved
Date: Tue, 13 Oct 2026 15:55:26 +0000	[thread overview]
Message-ID: <010701a135f9cf1b-7caf89c8-3dbd-4d4e-91c8-2c2c150a0dee-000000@eu-central-1.amazonses.com> (raw)
In-Reply-To: <20261013-vfio_v1-v2-21-433455c0a294@virtuozzo.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Low] migration: preserve_ram() leaks original Error after migrate_set_error()
- [Low] migration: cpr-exec fail path leaves RAM read-only after execvp() failure
--

commit 02a023bc5ba37bcad09a7328d397c6b940edac14
Author: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>

VZ: migration/cpr-exec: abort cpr-exec if memory can't be preserved

This patch makes cpr_exec_cb() treat a failed MADV_DOEXEC on any saved
ramblock as a failed cpr-exec. It jumps to a shared fail: label, which is
also reached when execvp() fails. That label restores close-on-exec on the
fds and clears MADV_DOEXEC on the ramblocks, so the VM keeps running in the
old QEMU.

> diff --git a/migration/cpr-exec.c b/migration/cpr-exec.c
> index 7b7609e19cd9..cb962ce72529 100644
> --- a/migration/cpr-exec.c
> +++ b/migration/cpr-exec.c

[ ... ]

> @@ -202,7 +215,10 @@ static void cpr_exec_cb(void *opaque)
>       */
>      cpr_exec_preserve_fds();
>  
> -    cpr_walk_ramblock(preserve_ram);
> +    if (!cpr_walk_ramblock(preserve_ram)) {
> +        /* preserve_ram() has already reported the error and failed migration */
> +        goto fail;
> +    }

[Severity: Low]
Does this new goto fail path leak the original Error object?

preserve_ram() builds the error like this:

    error_setg_errno(&err, errno, "MADV_DOEXEC failed on memory region %s:"
                     " addr=%p length=%zu", name, (void *) ram.addr,
                     ram.length);
    error_report_err(error_copy(err));
    migrate_set_state(&s->state, s->state, MIGRATION_STATUS_FAILED);
    migrate_set_error(s, err);
    return false;

error_report_err(error_copy(err)) frees only the copy, and
migrate_set_error() stores its own error_copy() without taking ownership.
No error_free(err) is reached before return false, so the original Error
(the struct and its msg string) is never freed.

The execvp() failure path in cpr_exec_cb() does call error_free(err) after
migrate_set_error(). The leak in preserve_ram() predates this patch, but
this patch now relies on that path to handle the failure. Would an
error_free(err) before return false in preserve_ram() be appropriate?

>      if (cpr_ram_rdonly) {
>          cpr_walk_ramblock(mark_ram_rdonly);
>      }

[ ... ]

> @@ -221,15 +237,17 @@ static void cpr_exec_cb(void *opaque)
>       * or the system is very short on resources.
>       */
>      error_setg_errno(&err, errno, "execvp %s failed", argv[0]);
> -    g_clear_pointer(&argv, g_strfreev);
> -    cpr_exec_unpreserve_fds();
> -
>      error_report_err(error_copy(err));
>      migrate_set_state(&s->state, s->state, MIGRATION_STATUS_FAILED);
>      migrate_set_error(s, err);
>      error_free(err);
>      err = NULL;
>  
> +fail:
> +    g_clear_pointer(&argv, g_strfreev);
> +    cpr_exec_unpreserve_fds();
> +    cpr_exec_unpreserve_ram();
> +

[Severity: Low]
Can the guest be resumed on read-only RAM when execvp() fails?

If cpr_ram_rdonly is set, cpr_exec_cb() calls:

    if (cpr_ram_rdonly) {
        cpr_walk_ramblock(mark_ram_rdonly);
    }

before execvp(). If execvp() then fails, the code reaches fail:, which
clears MADV_DOEXEC and restores close-on-exec, but nothing restores the
RAM protection. cpr_ram_restore_rw() exists:

    void cpr_ram_restore_rw(void)
    {
        cpr_walk_ramblock(mark_ram_rw);
    }

but its only caller is system/vl.c, which runs in the new QEMU after a
successful exec.

The code after the label then runs:

    if (runstate_is_live(s->vm_old_state)) {
        vm_start();
    }

With RAM still PROT_READ, can the first guest write, or a device emulation
write into guest memory, raise SIGSEGV and kill the VM? That seems contrary
to the commit message's statement that "the VM keeps running in the old
QEMU".

The preserve_ram() failure path jumps to fail: before mark_ram_rdonly() and
vhost_net_cpr_reset_owners() run, so it is not affected. The execvp()
failure path is affected. cpr_ram_rdonly is documented as a debug-only
option, which limits the exposure. Should the fail: path call
cpr_ram_restore_rw() when cpr_ram_rdonly is set?

Later patches in the series (the one that takes the vhost-net devices back
if exec fails) add a vhost_net_cpr_set_owners() call before the fail:
label. None of the later patches in the series restore RAM to read-write
on this path.

>      /* Note, we can go from state COMPLETED to FAILED */
>      migration_call_notifiers(MIG_EVENT_PRECOPY_FAILED, NULL);
>

-- 
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20261013-vfio_v1-v2-0-433455c0a294@virtuozzo.com?part=21

  reply	other threads:[~2026-10-13 15:55 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-13 15:28 [PATCH QEMU HCI-8.1 v2 00/24] vfio: support qemu-update with passed through GPU's and vGPU's #VSTOR-103860 Andrey Drobyshev
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 01/24] migration: Plug memory leaks after migrate_set_error() Andrey Drobyshev
2026-10-13 15:30   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 02/24] hw/vfio: Fix liveness check in vfio_connect_kvm_msi_virq() Andrey Drobyshev
2026-10-13 15:30   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 03/24] vfio/pci: Reject invalid MSI-X Table and PBA BIR values Andrey Drobyshev
2026-10-13 15:31   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 04/24] vfio/pci: Fix information leak in vfio_rom_read() Andrey Drobyshev
2026-10-13 15:31   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 05/24] vfio/pci: Initialize rom_read_failed in vfio_pci_load_rom() Andrey Drobyshev
2026-10-13 15:33   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 06/24] vfio/pci: Grow buffer in vfio_pci_host_match() Andrey Drobyshev
2026-10-13 15:32   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 07/24] q35: Fix migration of SMRAM state Andrey Drobyshev
2026-10-13 15:35   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 08/24] migration: ensure APIC is loaded prior to VFIO PCI devices Andrey Drobyshev
2026-10-13 15:33   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 09/24] migration: Fix regression of passing error_fatal into vmstate_load_state() Andrey Drobyshev
2026-10-13 15:36   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 10/24] migration: vmstate_save_state_v: fix double error_setg Andrey Drobyshev
2026-10-13 15:38   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 11/24] migration: yank: Move register instance earlier Andrey Drobyshev
2026-10-13 15:41   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 12/24] migration: Free cpr-transfer MigrationAddress along with gsource Andrey Drobyshev
2026-10-13 15:39   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 13/24] migration: Move CPR HUP watch to cpr-transfer.c Andrey Drobyshev
2026-10-13 15:40   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 14/24] migration: Fix crash on second migration when cancel early Andrey Drobyshev
2026-10-13 15:45   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 15/24] kvm: tolerate ioctls after kvm_close() Andrey Drobyshev
2026-10-13 15:44   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 16/24] kvm: fix coalesced MMIO flush racing with kvm_close() Andrey Drobyshev
2026-10-13 15:47   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 17/24] migration/cpr: add cpr_is_in_progress() Andrey Drobyshev
2026-10-13 15:47   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 18/24] vfio/migration: don't migrate device state during CPR Andrey Drobyshev
2026-10-13 15:53   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 19/24] vfio/listener: skip dirty page tracking " Andrey Drobyshev
2026-10-13 15:50   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 20/24] VZ: vfio/cpr: don't close KVM on cpr-exec Andrey Drobyshev
2026-10-13 15:53   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 21/24] VZ: migration/cpr-exec: abort cpr-exec if memory can't be preserved Andrey Drobyshev
2026-10-13 15:55   ` no-reply [this message]
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 22/24] VZ: migration/cpr-exec: take the vhost-net devices back if exec fails Andrey Drobyshev
2026-10-13 15:55   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 23/24] VZ: vfio/region: preserve BAR mappings across cpr-exec #VSTOR-103860 Andrey Drobyshev
2026-10-13 16:00   ` no-reply
2026-10-13 15:28 ` [PATCH QEMU HCI-8.1 v2 24/24] VZ: migration/cpr-exec: allow cpr-exec with VFIO devices #VSTOR-103860 Andrey Drobyshev
2026-10-13 15:57   ` no-reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=010701a135f9cf1b-7caf89c8-3dbd-4d4e-91c8-2c2c150a0dee-000000@eu-central-1.amazonses.com \
    --to=no-reply@sashiko.virtuozzo.com \
    --cc=andrey.drobyshev@virtuozzo.com \
    --cc=svt-core@virtuozzo.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox