diff --git a/LIBVIRT-11.9.0-UPGRADE.md b/LIBVIRT-11.9.0-UPGRADE.md new file mode 100644 index 00000000000..58ad14cedff --- /dev/null +++ b/LIBVIRT-11.9.0-UPGRADE.md @@ -0,0 +1,152 @@ +# libvirt 11.9.0 Package Upgrade + +This document records the Azure Linux `libvirt` package changes made while +upgrading from 10.10.0-2 to 11.9.0-1. The Azure Linux 4.0 and CentOS Stream 9 +specs were used as packaging references, while the upstream libvirt 11.9.0 +spec and source tree were used to determine the version-specific build and +file-list changes. + +## Version and source metadata + +- Changed `Version` from `10.10.0` to `11.9.0` and reset `Release` from `2` to + `1`, as required for the first Azure Linux package release of a new upstream + version. +- Replaced the source entry in `libvirt.signatures.json` with + `libvirt-11.9.0.tar.xz` and SHA-256 + `104f70ee591e72989d4f8c6caa79ed9dacd5dc84efdb0125b848afe544ad0c2d`. + The checksum was verified against the official archive from + `download.libvirt.org`. +- Added an 11.9.0 changelog entry and corrected the pre-existing chronological + placement of the 10.0.0-5 entry so RPM changelog validation succeeds. + +The Azure Linux source storage endpoint did not yet contain the 11.9.0 archive +during local validation. A verified copy was therefore placed next to the spec +for the build. Source archives in that location are ignored by the repository +and are not part of the tracked package change. + +## Feature macros + +- Added `arches_ch` for the architectures supported by the Cloud Hypervisor + driver (`x86_64` and `aarch64`). +- Added `with_ch` and kept it disabled for Azure Linux. libvirt 11.x has an + explicit Cloud Hypervisor driver option, so declaring the feature state is + preferable to relying on Meson auto-detection. +- Added `with_userfaultfd_sysctl` and enabled it. This controls installation of + libvirt's sysctl configuration for QEMU post-copy migration. +- Added `firewall_backend_priority` with `iptables,nftables`. libvirt 11.x can + select between firewall backends; this preserves the iptables-first behavior + of earlier Azure Linux packages rather than accepting a changed upstream + default. + +## Patch set + +The following patches remain in the spec because they apply cleanly to the +11.9.0 source and their behavior is not present in that release: + +- `libvirt-conf.patch` preserves the Azure Linux default connection URI. +- `CVE-2025-13193.patch` retains the applicable security fix. + +The following patch references and files were removed after checking them +against the exact 11.9.0 source: + +- `CVE-2025-12748.patch` is fixed or superseded in 11.9.0. +- `libvirt-qemu-tpm-do-not-update-profile-name-for-transient-domains.patch` is + obsolete with the 11.9.0 QEMU TPM implementation. +- `libvirt-qemu-Rename-outgoingMigration-parameter-in-various-TPM-functions.patch` + is already represented by the updated upstream TPM migration code. +- `libvirt-qemu-Properly-propagate-migration-state-to-TPM-cleanup-code.patch` + is already represented by the updated upstream TPM migration code. + +Keeping obsolete patches would either fail `%prep` or reapply behavior already +implemented upstream. + +## Build dependencies + +- Raised the minimum `glib2-devel` version from 2.56 to 2.66 to match the + minimum required by libvirt 11.9.0. +- Removed `kmod` from `BuildRequires` and added it to the daemon runtime + requirements. libvirt invokes `modprobe` and `rmmod` at runtime; it does not + need the executable to compile. +- Removed build-only entries for `polkit`, `util-linux`, `lvm2`, + `iscsi-initiator-utils`, and `numad`. These commands and services are runtime + concerns and are already associated with the subpackages that use them; the + 11.9.0 build does not require their executables. +- Removed the duplicate `util-linux` build requirement while retaining + `nfs-utils`, which is still used for network filesystem discovery. +- Added an exact-version requirement from the lockd plugin to + `libvirt-daemon-common`, reflecting its dependency on common daemon content. +- Added an `Obsoletes` entry for `libvirt-daemon-driver-storage-zfs < 11.4.0` + when ZFS support is disabled. This permits clean upgrades from installations + that still contain the former ZFS storage-driver subpackage. + +## Meson configuration + +- Split the ESX driver and curl settings into `arg_esx` and `arg_curl`. Curl is + needed by either ESX or Cloud Hypervisor, so tying it only to ESX would be + incorrect once `driver_ch` is modeled explicitly. +- Added `arg_ch` and pass `-Ddriver_ch=enabled` or `disabled` according to + `with_ch`. Azure Linux currently passes the disabled form. +- Added `arg_userfaultfd_sysctl` and pass the corresponding 11.9.0 Meson + option. This keeps the installed sysctl file synchronized with the feature + selection. +- Pass `-Dunitdir=%{_unitdir}` and `-Dsysusersdir=%{_sysusersdir}` so Meson + installs systemd units and sysusers definitions into the RPM macro-defined + locations. +- Pass `-Dsysctl_config=enabled` to install the supported sysctl configuration. +- Pass `-Dssh_proxy=enabled` to retain the SSH proxy transport expected by the + client package. +- Pass `-Dfirewall_backend_priority=%{firewall_backend_priority}` to preserve + Azure Linux firewall backend ordering. + +These options are explicit because several defaults and option relationships +changed in libvirt 11.x. Explicit values make the resulting package independent +of build-host auto-detection. + +## Install cleanup + +- Remove the Cloud Hypervisor Augeas lens and its test when `with_ch` is + disabled. Upstream installs these data files independently of whether Azure + Linux ships the driver, so cleanup keeps the package contents aligned with + the selected feature set. + +## File lists and ownership + +- Added ownership of the Augeas lens and lens-test directories to the daemon + common package. The package now owns the parent directories containing its + installed lenses. +- Moved ownership of `%{_libdir}/libvirt/lock-driver/` from the lockd plugin to + the daemon common package. The directory is shared infrastructure; the + plugin subpackage continues to own `lockd.so` itself. +- Added `%{_sysusersdir}/libvirt.conf` to the daemon common package for the + common libvirt system users installed by 11.9.0. +- Removed `libvirt_storage_file_fs.so` from the storage-core file list because + libvirt 11.9.0 no longer builds or installs that module. The remaining + `libvirt_storage_backend_fs.so` backend is still packaged. +- Made the QEMU post-copy migration sysctl file conditional on + `with_userfaultfd_sysctl`, matching the Meson option and avoiding a missing + file when the feature is disabled. +- Changed the QEMU sysusers file path from the hard-coded + `%{_prefix}/lib/sysusers.d/libvirt-qemu.conf` to + `%{_sysusersdir}/libvirt-qemu.conf`, matching the build option and RPM macro. +- Added explicit owner, group, and mode attributes to the QEMU runtime ghost + directories. The top-level, `passt`, and `slirp` directories use mode 0755; + the `dbus` and `swtpm` directories use mode 0770. All are owned by the + configured QEMU user and group. This matches the directories created at + runtime and prevents RPM from recording them as root-owned defaults. + +## Validation + +The completed package change was validated as follows: + +- `rpmspec -P` parsed the updated spec successfully. +- `rpmspec -q` resolved the expected 11.9.0-1 subpackage set. +- `libvirt.signatures.json` passed JSON validation. +- The official 11.9.0 archive matched the recorded SHA-256 checksum. +- Both retained patches applied cleanly to the exact 11.9.0 source. +- `git diff --check` reported no whitespace errors. +- A targeted Azure Linux toolkit build completed successfully with + `SRPM_PACK_LIST="libvirt"` and `PACKAGE_REBUILD_LIST="libvirt"`. +- The build produced 33 binary RPMs at version `11.9.0-1.azl3`, including all + daemon drivers, client libraries, development files, documentation, NSS, and + debuginfo packages. +- Representative built RPMs passed digest verification. diff --git a/SPECS/kubevirt/CVE-2026-35469.patch b/SPECS/kubevirt/CVE-2026-35469.patch deleted file mode 100644 index 9064cf5acae..00000000000 --- a/SPECS/kubevirt/CVE-2026-35469.patch +++ /dev/null @@ -1,624 +0,0 @@ -From 4c3257fa67d5ef36060edaffcb35962be8a3bb28 Mon Sep 17 00:00:00 2001 -From: AllSpark -Date: Wed, 6 May 2026 09:35:52 +0000 -Subject: [PATCH] Backport: SPDY framer options and limits; guard against - oversized control frames and excessive headers; add NewConnectionWithOptions - and option helpers - -The "github.com/moby/spdystream" vendor package has been upgraded to version 0.5.1 with -this patch. But go.mod, go.sum and vendor/module.txt files have not been modified. - -Signed-off-by: Azure Linux Security Servicing Account -Upstream Patch Reference: https://github.com/moby/spdystream/releases/tag/v0.5.1 ---- - vendor/github.com/moby/spdystream/BUILD.bazel | 16 ---- - vendor/github.com/moby/spdystream/NOTICE | 12 +++ - .../github.com/moby/spdystream/connection.go | 11 ++- - .../moby/spdystream/spdy/BUILD.bazel | 14 ---- - .../github.com/moby/spdystream/spdy/LICENSE | 27 +++++++ - .../github.com/moby/spdystream/spdy/PATENTS | 22 +++++ - .../moby/spdystream/spdy/dictionary.go | 16 ---- - .../moby/spdystream/spdy/options.go | 25 ++++++ - .../github.com/moby/spdystream/spdy/read.go | 58 ++++++++----- - .../github.com/moby/spdystream/spdy/types.go | 49 +++++++---- - .../github.com/moby/spdystream/spdy/write.go | 81 ++++++++++++------- - 11 files changed, 218 insertions(+), 113 deletions(-) - delete mode 100644 vendor/github.com/moby/spdystream/BUILD.bazel - delete mode 100644 vendor/github.com/moby/spdystream/spdy/BUILD.bazel - create mode 100644 vendor/github.com/moby/spdystream/spdy/LICENSE - create mode 100644 vendor/github.com/moby/spdystream/spdy/PATENTS - create mode 100644 vendor/github.com/moby/spdystream/spdy/options.go - -diff --git a/vendor/github.com/moby/spdystream/BUILD.bazel b/vendor/github.com/moby/spdystream/BUILD.bazel -deleted file mode 100644 -index d26e907..0000000 ---- a/vendor/github.com/moby/spdystream/BUILD.bazel -+++ /dev/null -@@ -1,16 +0,0 @@ --load("@io_bazel_rules_go//go:def.bzl", "go_library") -- --go_library( -- name = "go_default_library", -- srcs = [ -- "connection.go", -- "handlers.go", -- "priority.go", -- "stream.go", -- "utils.go", -- ], -- importmap = "kubevirt.io/kubevirt/vendor/github.com/moby/spdystream", -- importpath = "github.com/moby/spdystream", -- visibility = ["//visibility:public"], -- deps = ["//vendor/github.com/moby/spdystream/spdy:go_default_library"], --) -diff --git a/vendor/github.com/moby/spdystream/NOTICE b/vendor/github.com/moby/spdystream/NOTICE -index b9b11c9..24e2e2a 100644 ---- a/vendor/github.com/moby/spdystream/NOTICE -+++ b/vendor/github.com/moby/spdystream/NOTICE -@@ -3,3 +3,15 @@ Copyright 2014-2021 Docker Inc. - - This product includes software developed at - Docker Inc. (https://www.docker.com/). -+ -+SPDY implementation (spdy/) -+ -+The spdy directory contains code derived from the Go project (golang.org/x/net). -+ -+Copyright 2009-2013 The Go Authors. -+Licensed under the BSD 3-Clause License. -+ -+Modifications Copyright 2014-2021 Docker Inc. -+ -+The BSD license text and Go patent grant are included in -+spdy/LICENSE and spdy/PATENTS. -diff --git a/vendor/github.com/moby/spdystream/connection.go b/vendor/github.com/moby/spdystream/connection.go -index 1394d0a..69ce477 100644 ---- a/vendor/github.com/moby/spdystream/connection.go -+++ b/vendor/github.com/moby/spdystream/connection.go -@@ -224,7 +224,13 @@ type Connection struct { - // NewConnection creates a new spdy connection from an existing - // network connection. - func NewConnection(conn net.Conn, server bool) (*Connection, error) { -- framer, framerErr := spdy.NewFramer(conn, conn) -+ return NewConnectionWithOptions(conn, server) -+} -+ -+// NewConnectionWithOptions creates a new spdy connection and applies frame -+// parsing limits via options. -+func NewConnectionWithOptions(conn net.Conn, server bool, opts ...spdy.FramerOption) (*Connection, error) { -+ framer, framerErr := spdy.NewFramerWithOptions(conn, conn, opts...) - if framerErr != nil { - return nil, framerErr - } -@@ -350,6 +356,9 @@ Loop: - } else { - debugMessage("(%p) EOF received", s) - } -+ if spdyErr, ok := err.(*spdy.Error); ok && spdyErr.Err == spdy.InvalidControlFrame { -+ _ = s.conn.Close() -+ } - break - } - var priority uint8 -diff --git a/vendor/github.com/moby/spdystream/spdy/BUILD.bazel b/vendor/github.com/moby/spdystream/spdy/BUILD.bazel -deleted file mode 100644 -index f65271e..0000000 ---- a/vendor/github.com/moby/spdystream/spdy/BUILD.bazel -+++ /dev/null -@@ -1,14 +0,0 @@ --load("@io_bazel_rules_go//go:def.bzl", "go_library") -- --go_library( -- name = "go_default_library", -- srcs = [ -- "dictionary.go", -- "read.go", -- "types.go", -- "write.go", -- ], -- importmap = "kubevirt.io/kubevirt/vendor/github.com/moby/spdystream/spdy", -- importpath = "github.com/moby/spdystream/spdy", -- visibility = ["//visibility:public"], --) -diff --git a/vendor/github.com/moby/spdystream/spdy/LICENSE b/vendor/github.com/moby/spdystream/spdy/LICENSE -new file mode 100644 -index 0000000..6a66aea ---- /dev/null -+++ b/vendor/github.com/moby/spdystream/spdy/LICENSE -@@ -0,0 +1,27 @@ -+Copyright (c) 2009 The Go Authors. All rights reserved. -+ -+Redistribution and use in source and binary forms, with or without -+modification, are permitted provided that the following conditions are -+met: -+ -+ * Redistributions of source code must retain the above copyright -+notice, this list of conditions and the following disclaimer. -+ * Redistributions in binary form must reproduce the above -+copyright notice, this list of conditions and the following disclaimer -+in the documentation and/or other materials provided with the -+distribution. -+ * Neither the name of Google Inc. nor the names of its -+contributors may be used to endorse or promote products derived from -+this software without specific prior written permission. -+ -+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -diff --git a/vendor/github.com/moby/spdystream/spdy/PATENTS b/vendor/github.com/moby/spdystream/spdy/PATENTS -new file mode 100644 -index 0000000..7330990 ---- /dev/null -+++ b/vendor/github.com/moby/spdystream/spdy/PATENTS -@@ -0,0 +1,22 @@ -+Additional IP Rights Grant (Patents) -+ -+"This implementation" means the copyrightable works distributed by -+Google as part of the Go project. -+ -+Google hereby grants to You a perpetual, worldwide, non-exclusive, -+no-charge, royalty-free, irrevocable (except as stated in this section) -+patent license to make, have made, use, offer to sell, sell, import, -+transfer and otherwise run, modify and propagate the contents of this -+implementation of Go, where such license applies only to those patent -+claims, both currently owned or controlled by Google and acquired in -+the future, licensable by Google that are necessarily infringed by this -+implementation of Go. This grant does not include claims that would be -+infringed only as a consequence of further modification of this -+implementation. If you or your agent or exclusive licensee institute or -+order or agree to the institution of patent litigation against any -+entity (including a cross-claim or counterclaim in a lawsuit) alleging -+that this implementation of Go or any code incorporated within this -+implementation of Go constitutes direct or contributory patent -+infringement, or inducement of patent infringement, then any patent -+rights granted to you under this License for this implementation of Go -+shall terminate as of the date such litigation is filed. -diff --git a/vendor/github.com/moby/spdystream/spdy/dictionary.go b/vendor/github.com/moby/spdystream/spdy/dictionary.go -index 392232f..5a5ff0e 100644 ---- a/vendor/github.com/moby/spdystream/spdy/dictionary.go -+++ b/vendor/github.com/moby/spdystream/spdy/dictionary.go -@@ -1,19 +1,3 @@ --/* -- Copyright 2014-2021 Docker Inc. -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. -- You may obtain a copy of the License at -- -- http://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -- See the License for the specific language governing permissions and -- limitations under the License. --*/ -- - // Copyright 2013 The Go Authors. All rights reserved. - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. -diff --git a/vendor/github.com/moby/spdystream/spdy/options.go b/vendor/github.com/moby/spdystream/spdy/options.go -new file mode 100644 -index 0000000..ec03e0b ---- /dev/null -+++ b/vendor/github.com/moby/spdystream/spdy/options.go -@@ -0,0 +1,25 @@ -+package spdy -+ -+// FramerOption allows callers to customize frame parsing limits. -+type FramerOption func(*Framer) -+ -+// WithMaxControlFramePayloadSize sets the control-frame payload limit. -+func WithMaxControlFramePayloadSize(size uint32) FramerOption { -+ return func(f *Framer) { -+ f.maxFrameLength = size -+ } -+} -+ -+// WithMaxHeaderFieldSize sets the per-header name/value size limit. -+func WithMaxHeaderFieldSize(size uint32) FramerOption { -+ return func(f *Framer) { -+ f.maxHeaderFieldSize = size -+ } -+} -+ -+// WithMaxHeaderCount sets the maximum number of headers in a frame. -+func WithMaxHeaderCount(count uint32) FramerOption { -+ return func(f *Framer) { -+ f.maxHeaderCount = count -+ } -+} -diff --git a/vendor/github.com/moby/spdystream/spdy/read.go b/vendor/github.com/moby/spdystream/spdy/read.go -index 75ea045..2abb694 100644 ---- a/vendor/github.com/moby/spdystream/spdy/read.go -+++ b/vendor/github.com/moby/spdystream/spdy/read.go -@@ -1,19 +1,3 @@ --/* -- Copyright 2014-2021 Docker Inc. -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. -- You may obtain a copy of the License at -- -- http://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -- See the License for the specific language governing permissions and -- limitations under the License. --*/ -- - // Copyright 2011 The Go Authors. All rights reserved. - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. -@@ -24,6 +8,7 @@ import ( - "compress/zlib" - "encoding/binary" - "io" -+ "io/ioutil" - "net/http" - "strings" - ) -@@ -59,6 +44,11 @@ func (frame *SettingsFrame) read(h ControlFrameHeader, f *Framer) error { - if err := binary.Read(f.r, binary.BigEndian, &numSettings); err != nil { - return err - } -+ // Each setting is 8 bytes (4-byte id + 4-byte value). -+ // Payload is 4 bytes for numSettings + numSettings*8. -+ if h.length < 4 || numSettings > (h.length-4)/8 { -+ return &Error{InvalidControlFrame, 0} -+ } - frame.FlagIdValues = make([]SettingsFlagIdValue, numSettings) - for i := uint32(0); i < numSettings; i++ { - if err := binary.Read(f.r, binary.BigEndian, &frame.FlagIdValues[i].Id); err != nil { -@@ -177,8 +167,19 @@ func (f *Framer) parseControlFrame(version uint16, frameType ControlFrameType) ( - if err := binary.Read(f.r, binary.BigEndian, &length); err != nil { - return nil, err - } -+ maxControlFramePayload := uint32(MaxDataLength) -+ if f.maxFrameLength > 0 { -+ maxControlFramePayload = f.maxFrameLength -+ } -+ - flags := ControlFlags((length & 0xff000000) >> 24) - length &= 0xffffff -+ if length > maxControlFramePayload { -+ if _, err := io.CopyN(ioutil.Discard, f.r, int64(length)); err != nil { -+ return nil, err -+ } -+ return nil, &Error{InvalidControlFrame, 0} -+ } - header := ControlFrameHeader{version, frameType, flags, length} - cframe, err := newControlFrame(frameType) - if err != nil { -@@ -190,11 +191,22 @@ func (f *Framer) parseControlFrame(version uint16, frameType ControlFrameType) ( - return cframe, nil - } - --func parseHeaderValueBlock(r io.Reader, streamId StreamId) (http.Header, error) { -+func (f *Framer) parseHeaderValueBlock(r io.Reader, streamId StreamId) (http.Header, error) { - var numHeaders uint32 - if err := binary.Read(r, binary.BigEndian, &numHeaders); err != nil { - return nil, err - } -+ maxHeaders := defaultMaxHeaderCount -+ if f.maxHeaderCount > 0 { -+ maxHeaders = f.maxHeaderCount -+ } -+ if numHeaders > maxHeaders { -+ return nil, &Error{InvalidControlFrame, streamId} -+ } -+ maxFieldSize := defaultMaxHeaderFieldSize -+ if f.maxHeaderFieldSize > 0 { -+ maxFieldSize = f.maxHeaderFieldSize -+ } - var e error - h := make(http.Header, int(numHeaders)) - for i := 0; i < int(numHeaders); i++ { -@@ -202,6 +214,9 @@ func parseHeaderValueBlock(r io.Reader, streamId StreamId) (http.Header, error) - if err := binary.Read(r, binary.BigEndian, &length); err != nil { - return nil, err - } -+ if length > maxFieldSize { -+ return nil, &Error{InvalidControlFrame, streamId} -+ } - nameBytes := make([]byte, length) - if _, err := io.ReadFull(r, nameBytes); err != nil { - return nil, err -@@ -217,6 +232,9 @@ func parseHeaderValueBlock(r io.Reader, streamId StreamId) (http.Header, error) - if err := binary.Read(r, binary.BigEndian, &length); err != nil { - return nil, err - } -+ if length > maxFieldSize { -+ return nil, &Error{InvalidControlFrame, streamId} -+ } - value := make([]byte, length) - if _, err := io.ReadFull(r, value); err != nil { - return nil, err -@@ -256,7 +274,7 @@ func (f *Framer) readSynStreamFrame(h ControlFrameHeader, frame *SynStreamFrame) - } - reader = f.headerDecompressor - } -- frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId) -+ frame.Headers, err = f.parseHeaderValueBlock(reader, frame.StreamId) - if !f.headerCompressionDisabled && (err == io.EOF && f.headerReader.N == 0 || f.headerReader.N != 0) { - err = &Error{WrongCompressedPayloadSize, 0} - } -@@ -288,7 +306,7 @@ func (f *Framer) readSynReplyFrame(h ControlFrameHeader, frame *SynReplyFrame) e - } - reader = f.headerDecompressor - } -- frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId) -+ frame.Headers, err = f.parseHeaderValueBlock(reader, frame.StreamId) - if !f.headerCompressionDisabled && (err == io.EOF && f.headerReader.N == 0 || f.headerReader.N != 0) { - err = &Error{WrongCompressedPayloadSize, 0} - } -@@ -320,7 +338,7 @@ func (f *Framer) readHeadersFrame(h ControlFrameHeader, frame *HeadersFrame) err - } - reader = f.headerDecompressor - } -- frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId) -+ frame.Headers, err = f.parseHeaderValueBlock(reader, frame.StreamId) - if !f.headerCompressionDisabled && (err == io.EOF && f.headerReader.N == 0 || f.headerReader.N != 0) { - err = &Error{WrongCompressedPayloadSize, 0} - } -diff --git a/vendor/github.com/moby/spdystream/spdy/types.go b/vendor/github.com/moby/spdystream/spdy/types.go -index a254a43..a552861 100644 ---- a/vendor/github.com/moby/spdystream/spdy/types.go -+++ b/vendor/github.com/moby/spdystream/spdy/types.go -@@ -1,23 +1,9 @@ --/* -- Copyright 2014-2021 Docker Inc. -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. -- You may obtain a copy of the License at -- -- http://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -- See the License for the specific language governing permissions and -- limitations under the License. --*/ -- - // Copyright 2011 The Go Authors. All rights reserved. - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - -+// Modifications Copyright 2014-2021 Docker Inc. -+ - // Package spdy implements the SPDY protocol (currently SPDY/3), described in - // http://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3. - package spdy -@@ -63,8 +49,20 @@ const ( - ) - - // MaxDataLength is the maximum number of bytes that can be stored in one frame. -+// -+// SPDY frame headers encode the payload length using a 24-bit field, -+// so the maximum representable size for both data and control frames -+// is 2^24-1 bytes. -+// -+// See the SPDY/3 specification, "Frame Format": -+// https://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3-1/ - const MaxDataLength = 1<<24 - 1 - -+const ( -+ defaultMaxHeaderFieldSize uint32 = 1 << 20 -+ defaultMaxHeaderCount uint32 = 1000 -+) -+ - // headerValueSepator separates multiple header values. - const headerValueSeparator = "\x00" - -@@ -269,6 +267,10 @@ type Framer struct { - r io.Reader - headerReader io.LimitedReader - headerDecompressor io.ReadCloser -+ -+ maxFrameLength uint32 // overrides the default frame payload length limit. -+ maxHeaderFieldSize uint32 // overrides the default per-header name/value length limit. -+ maxHeaderCount uint32 // overrides the default header count limit. - } - - // NewFramer allocates a new Framer for a given SPDY connection, represented by -@@ -276,6 +278,16 @@ type Framer struct { - // from/to the Reader and Writer, so the caller should pass in an appropriately - // buffered implementation to optimize performance. - func NewFramer(w io.Writer, r io.Reader) (*Framer, error) { -+ return newFramer(w, r) -+} -+ -+// NewFramerWithOptions allocates a new Framer for a given SPDY connection and -+// applies frame parsing limits via options. -+func NewFramerWithOptions(w io.Writer, r io.Reader, opts ...FramerOption) (*Framer, error) { -+ return newFramer(w, r, opts...) -+} -+ -+func newFramer(w io.Writer, r io.Reader, opts ...FramerOption) (*Framer, error) { - compressBuf := new(bytes.Buffer) - compressor, err := zlib.NewWriterLevelDict(compressBuf, zlib.BestCompression, []byte(headerDictionary)) - if err != nil { -@@ -287,5 +299,10 @@ func NewFramer(w io.Writer, r io.Reader) (*Framer, error) { - headerCompressor: compressor, - r: r, - } -+ for _, opt := range opts { -+ if opt != nil { -+ opt(framer) -+ } -+ } - return framer, nil - } -diff --git a/vendor/github.com/moby/spdystream/spdy/write.go b/vendor/github.com/moby/spdystream/spdy/write.go -index ab6d91f..75084d3 100644 ---- a/vendor/github.com/moby/spdystream/spdy/write.go -+++ b/vendor/github.com/moby/spdystream/spdy/write.go -@@ -1,19 +1,3 @@ --/* -- Copyright 2014-2021 Docker Inc. -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. -- You may obtain a copy of the License at -- -- http://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -- See the License for the specific language governing permissions and -- limitations under the License. --*/ -- - // Copyright 2011 The Go Authors. All rights reserved. - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. -@@ -23,6 +7,7 @@ package spdy - import ( - "encoding/binary" - "io" -+ "math" - "net/http" - "strings" - ) -@@ -63,13 +48,21 @@ func (frame *RstStreamFrame) write(f *Framer) (err error) { - func (frame *SettingsFrame) write(f *Framer) (err error) { - frame.CFHeader.version = Version - frame.CFHeader.frameType = TypeSettings -- frame.CFHeader.length = uint32(len(frame.FlagIdValues)*8 + 4) -+ payloadLen := len(frame.FlagIdValues)*8 + 4 -+ if payloadLen > MaxDataLength { -+ return &Error{InvalidControlFrame, 0} -+ } -+ frame.CFHeader.length = uint32(payloadLen) - - // Serialize frame to Writer. - if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil { - return - } -- if err = binary.Write(f.w, binary.BigEndian, uint32(len(frame.FlagIdValues))); err != nil { -+ n := len(frame.FlagIdValues) -+ if uint64(n) > math.MaxUint32 { -+ return &Error{InvalidControlFrame, 0} -+ } -+ if err = binary.Write(f.w, binary.BigEndian, uint32(n)); err != nil { - return - } - for _, flagIdValue := range frame.FlagIdValues { -@@ -170,29 +163,41 @@ func writeControlFrameHeader(w io.Writer, h ControlFrameHeader) error { - - func writeHeaderValueBlock(w io.Writer, h http.Header) (n int, err error) { - n = 0 -- if err = binary.Write(w, binary.BigEndian, uint32(len(h))); err != nil { -+ numHeaders := len(h) -+ if numHeaders > math.MaxInt32 { -+ return n, &Error{InvalidControlFrame, 0} -+ } -+ if err = binary.Write(w, binary.BigEndian, uint32(numHeaders)); err != nil { - return - } -- n += 2 -+ n += 4 - for name, values := range h { -- if err = binary.Write(w, binary.BigEndian, uint32(len(name))); err != nil { -+ nameLen := len(name) -+ if nameLen > math.MaxInt32 { -+ return n, &Error{InvalidControlFrame, 0} -+ } -+ if err = binary.Write(w, binary.BigEndian, uint32(nameLen)); err != nil { - return - } -- n += 2 -+ n += 4 - name = strings.ToLower(name) - if _, err = io.WriteString(w, name); err != nil { - return - } -- n += len(name) -+ n += nameLen - v := strings.Join(values, headerValueSeparator) -- if err = binary.Write(w, binary.BigEndian, uint32(len(v))); err != nil { -+ vLen := len(v) -+ if vLen > math.MaxInt32 { -+ return n, &Error{InvalidControlFrame, 0} -+ } -+ if err = binary.Write(w, binary.BigEndian, uint32(vLen)); err != nil { - return - } -- n += 2 -+ n += 4 - if _, err = io.WriteString(w, v); err != nil { - return - } -- n += len(v) -+ n += vLen - } - return - } -@@ -216,7 +221,11 @@ func (f *Framer) writeSynStreamFrame(frame *SynStreamFrame) (err error) { - // Set ControlFrameHeader. - frame.CFHeader.version = Version - frame.CFHeader.frameType = TypeSynStream -- frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 10) -+ hLen := len(f.headerBuf.Bytes()) + 10 -+ if hLen > MaxDataLength { -+ return &Error{InvalidControlFrame, 0} -+ } -+ frame.CFHeader.length = uint32(hLen) - - // Serialize frame to Writer. - if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil { -@@ -260,7 +269,11 @@ func (f *Framer) writeSynReplyFrame(frame *SynReplyFrame) (err error) { - // Set ControlFrameHeader. - frame.CFHeader.version = Version - frame.CFHeader.frameType = TypeSynReply -- frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 4) -+ hLen := len(f.headerBuf.Bytes()) + 4 -+ if hLen > MaxDataLength { -+ return &Error{InvalidControlFrame, 0} -+ } -+ frame.CFHeader.length = uint32(hLen) - - // Serialize frame to Writer. - if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil { -@@ -295,7 +308,11 @@ func (f *Framer) writeHeadersFrame(frame *HeadersFrame) (err error) { - // Set ControlFrameHeader. - frame.CFHeader.version = Version - frame.CFHeader.frameType = TypeHeaders -- frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 4) -+ hLen := len(f.headerBuf.Bytes()) + 4 -+ if hLen > MaxDataLength { -+ return &Error{InvalidControlFrame, 0} -+ } -+ frame.CFHeader.length = uint32(hLen) - - // Serialize frame to Writer. - if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil { -@@ -323,7 +340,11 @@ func (f *Framer) writeDataFrame(frame *DataFrame) (err error) { - if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil { - return - } -- flagsAndLength := uint32(frame.Flags)<<24 | uint32(len(frame.Data)) -+ dLen := len(frame.Data) -+ if dLen > MaxDataLength { -+ return &Error{InvalidDataFrame, frame.StreamId} -+ } -+ flagsAndLength := uint32(frame.Flags)<<24 | uint32(dLen) - if err = binary.Write(f.w, binary.BigEndian, flagsAndLength); err != nil { - return - } --- -2.45.4 - diff --git a/SPECS/kubevirt/CVE-2026-7374.patch b/SPECS/kubevirt/CVE-2026-7374.patch deleted file mode 100644 index 960dd1d1f8f..00000000000 --- a/SPECS/kubevirt/CVE-2026-7374.patch +++ /dev/null @@ -1,180 +0,0 @@ -From 0b495d25ad05cb724f94908e8f4d7a84d58ca41c Mon Sep 17 00:00:00 2001 -From: Jed Lejosne -Date: Tue, 21 Apr 2026 16:09:50 -0400 -Subject: [PATCH 1/2] Use safepath for virt-launcher console socket paths - -The console handler was directly constructing paths to virt-launcher -sockets (virt-serial0, virt-vnc, virt-usbredir) through /proc//root -without safepath protection, making it vulnerable to symlink attacks. - -Switch getUnixSocketPath to use res.MountRoot() with safepath's -AppendAndResolveWithRelativeRoot, and perform net.Dial inside -ExecuteNoFollow so the connection uses a kernel-managed fd path. Also -use /run instead of /var/run since the latter is a symlink. - -Assisted-by: Claude (Anthropic AI assistant) -Made-with: Cursor -Signed-off-by: Jed Lejosne -(cherry picked from commit aa2b64ecdc784743901a728f52bd76fd213054de) -Signed-off-by: Jed Lejosne ---- - pkg/virt-handler/rest/BUILD.bazel | 1 + - pkg/virt-handler/rest/console.go | 42 ++++++++++++++++--------------- - 2 files changed, 23 insertions(+), 20 deletions(-) - -diff --git a/pkg/virt-handler/rest/BUILD.bazel b/pkg/virt-handler/rest/BUILD.bazel -index 8d14d89..7ef7998 100644 ---- a/pkg/virt-handler/rest/BUILD.bazel -+++ b/pkg/virt-handler/rest/BUILD.bazel -@@ -11,6 +11,7 @@ go_library( - importpath = "kubevirt.io/kubevirt/pkg/virt-handler/rest", - visibility = ["//visibility:public"], - deps = [ -+ "//pkg/safepath:go_default_library", - "//pkg/util:go_default_library", - "//pkg/virt-handler/cmd-client:go_default_library", - "//pkg/virt-handler/isolation:go_default_library", -diff --git a/pkg/virt-handler/rest/console.go b/pkg/virt-handler/rest/console.go -index bcad432..9a853da 100644 ---- a/pkg/virt-handler/rest/console.go -+++ b/pkg/virt-handler/rest/console.go -@@ -26,8 +26,6 @@ import ( - "io" - "net" - "net/http" -- "os" -- "path" - "strconv" - "sync" - -@@ -41,6 +39,7 @@ import ( - kvcorev1 "kubevirt.io/client-go/kubevirt/typed/core/v1" - "kubevirt.io/client-go/log" - -+ "kubevirt.io/kubevirt/pkg/safepath" - "kubevirt.io/kubevirt/pkg/util" - "kubevirt.io/kubevirt/pkg/virt-handler/isolation" - ) -@@ -86,7 +85,7 @@ func (t *ConsoleHandler) USBRedirHandler(request *restful.Request, response *res - uid := vmi.GetUID() - stopChan := make(chan struct{}) - var slotId int -- var unixSocketPath string -+ var unixSocketPath *safepath.Path - ok := func() bool { - // For simplicity, we handle one usbredir request at the time, for all VMIs - // handled by virt-handler -@@ -287,30 +286,33 @@ func deleteStopChan(uid types.UID, stopChn chan struct{}, lock *sync.Mutex, stop - } - } - --func (t *ConsoleHandler) getUnixSocketPath(vmi *v1.VirtualMachineInstance, socketName string) (string, error) { -+func (t *ConsoleHandler) getUnixSocketPath(vmi *v1.VirtualMachineInstance, socketName string) (*safepath.Path, error) { - result, err := t.podIsolationDetector.Detect(vmi) - if err != nil { -- return "", err -+ return nil, err - } -- socketDir := path.Join("/proc", strconv.Itoa(result.Pid()), "root", "var", "run", "kubevirt-private", string(vmi.GetUID())) -- socketPath := path.Join(socketDir, socketName) -- if _, err = os.Stat(socketPath); errors.Is(err, os.ErrNotExist) { -- return "", err -+ root, err := result.MountRoot() -+ if err != nil { -+ return nil, err - } -- -- return socketPath, nil -+ return root.AppendAndResolveWithRelativeRoot("run", "kubevirt-private", string(vmi.GetUID()), socketName) - } - --func unixSocketDialer(vmi *v1.VirtualMachineInstance, unixSocketPath string) func() (net.Conn, error) { -+func unixSocketDialer(vmi *v1.VirtualMachineInstance, socketPath *safepath.Path) func() (net.Conn, error) { - return func() (net.Conn, error) { -- log.Log.Object(vmi).Infof("Connecting to %s", unixSocketPath) -- fd, err := net.Dial("unix", unixSocketPath) -- if err != nil { -- log.Log.Object(vmi).Reason(err).Errorf("failed to dial unix socket %s", unixSocketPath) -- return nil, err -- } -- log.Log.Object(vmi).Infof("Connected to %s", unixSocketPath) -- return fd, nil -+ var conn net.Conn -+ err := socketPath.ExecuteNoFollow(func(safePath string) error { -+ log.Log.Object(vmi).Infof("Connecting to %s", safePath) -+ var dialErr error -+ conn, dialErr = net.Dial("unix", safePath) -+ if dialErr != nil { -+ log.Log.Object(vmi).Reason(dialErr).Errorf("failed to dial unix socket %s", safePath) -+ return dialErr -+ } -+ log.Log.Object(vmi).Infof("Connected to %s", safePath) -+ return nil -+ }) -+ return conn, err - } - } - --- -2.45.4 - - -From 596d34ecda8e1db2b10b61a8a29d093889d3b203 Mon Sep 17 00:00:00 2001 -From: Jed Lejosne -Date: Tue, 21 Apr 2026 16:12:23 -0400 -Subject: [PATCH 2/2] Add unit tests for console handler safepath usage - -Test getUnixSocketPath and unixSocketDialer to verify: -- socket paths are resolved via MountRoot + safepath -- paths containing symlinks are rejected -- missing sockets and isolation errors are handled -- dialer connects through ExecuteNoFollow - -Assisted-by: Claude (Anthropic AI assistant) -Made-with: Cursor -Signed-off-by: Jed Lejosne -(cherry picked from commit fdce2270a11e3e1b38d6b7aac4239ce185c7ac64) -Signed-off-by: Jed Lejosne -Signed-off-by: Azure Linux Security Servicing Account -Upstream-reference: https://github.com/kubevirt/kubevirt/pull/17920.patch ---- - pkg/virt-handler/rest/BUILD.bazel | 22 +++++++++++++++++++++- - 1 file changed, 21 insertions(+), 1 deletion(-) - -diff --git a/pkg/virt-handler/rest/BUILD.bazel b/pkg/virt-handler/rest/BUILD.bazel -index 7ef7998..d7206b5 100644 ---- a/pkg/virt-handler/rest/BUILD.bazel -+++ b/pkg/virt-handler/rest/BUILD.bazel -@@ -1,4 +1,4 @@ --load("@io_bazel_rules_go//go:def.bzl", "go_library") -+load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") - - go_library( - name = "go_default_library", -@@ -28,3 +28,23 @@ go_library( - "//vendor/k8s.io/client-go/util/certificate:go_default_library", - ], - ) -+ -+go_test( -+ name = "go_default_test", -+ srcs = [ -+ "console_test.go", -+ "rest_suite_test.go", -+ ], -+ embed = [":go_default_library"], -+ race = "on", -+ deps = [ -+ "//pkg/safepath:go_default_library", -+ "//pkg/unsafepath:go_default_library", -+ "//pkg/virt-handler/isolation:go_default_library", -+ "//staging/src/kubevirt.io/client-go/api:go_default_library", -+ "//staging/src/kubevirt.io/client-go/testutils:go_default_library", -+ "//vendor/github.com/onsi/ginkgo/v2:go_default_library", -+ "//vendor/github.com/onsi/gomega:go_default_library", -+ "//vendor/go.uber.org/mock/gomock:go_default_library", -+ ], -+) --- -2.45.4 - diff --git a/SPECS/kubevirt/kubevirt.signatures.json b/SPECS/kubevirt/kubevirt.signatures.json index 56c8d12b9d6..1c2ef344f1f 100644 --- a/SPECS/kubevirt/kubevirt.signatures.json +++ b/SPECS/kubevirt/kubevirt.signatures.json @@ -1,5 +1,5 @@ { "Signatures": { - "kubevirt-1.7.1.tar.gz": "2a613fe591ddd1a0f70fa459065c17180ec7f67cf0906ec13f352b51b3cd2c2d" + "kubevirt-1.8.4.tar.gz": "5bfd1d3490b1abb0e9dfe43d4f7034f8e8e8a97cdc0889b8abf396a0fb77ee35" } } diff --git a/SPECS/kubevirt/kubevirt.spec b/SPECS/kubevirt/kubevirt.spec index 3ddf87ce505..67b7d77e92a 100644 --- a/SPECS/kubevirt/kubevirt.spec +++ b/SPECS/kubevirt/kubevirt.spec @@ -19,8 +19,8 @@ Summary: Container native virtualization Name: kubevirt -Version: 1.7.1 -Release: 8%{?dist} +Version: 1.8.4 +Release: 1%{?dist} License: ASL 2.0 Vendor: Microsoft Corporation Distribution: Azure Linux @@ -28,23 +28,21 @@ Group: System/Management URL: https://github.com/kubevirt/kubevirt Source0: https://github.com/kubevirt/kubevirt/archive/refs/tags/v%{version}.tar.gz#/%{name}-%{version}.tar.gz Patch0: CVE-2025-11065.patch -Patch1: CVE-2026-35469.patch -Patch2: CVE-2026-39829.patch -Patch3: CVE-2026-42506.patch -Patch4: CVE-2026-46597.patch -Patch5: CVE-2026-39821.patch -Patch6: CVE-2026-39830.patch -Patch7: CVE-2026-39834.patch -Patch8: CVE-2026-27136.patch -Patch9: CVE-2026-25680.patch -Patch10: CVE-2026-25681.patch -Patch11: CVE-2026-39827.patch -Patch12: CVE-2026-39828.patch -Patch13: CVE-2026-39835.patch -Patch14: CVE-2026-42502.patch -Patch15: CVE-2026-7374.patch -Patch16: CVE-2026-33814.patch -Patch17: CVE-2026-56852.patch +Patch1: CVE-2026-39829.patch +Patch2: CVE-2026-42506.patch +Patch3: CVE-2026-46597.patch +Patch4: CVE-2026-39821.patch +Patch5: CVE-2026-39830.patch +Patch6: CVE-2026-39834.patch +Patch7: CVE-2026-27136.patch +Patch8: CVE-2026-25680.patch +Patch9: CVE-2026-25681.patch +Patch10: CVE-2026-39827.patch +Patch11: CVE-2026-39828.patch +Patch12: CVE-2026-39835.patch +Patch13: CVE-2026-42502.patch +Patch14: CVE-2026-33814.patch +Patch15: CVE-2026-56852.patch %global debug_package %{nil} BuildRequires: swtpm-tools @@ -55,6 +53,7 @@ BuildRequires: golang-packaging BuildRequires: pkgconfig BuildRequires: rsync BuildRequires: sed +BuildRequires: pkgconfig(libnbd) BuildRequires: pkgconfig(libvirt) ExclusiveArch: x86_64 aarch64 diff --git a/SPECS/libvirt/CVE-2025-12748.patch b/SPECS/libvirt/CVE-2025-12748.patch deleted file mode 100644 index a29b69c4da6..00000000000 --- a/SPECS/libvirt/CVE-2025-12748.patch +++ /dev/null @@ -1,1055 +0,0 @@ -From 6953acaafe8fc77684efe6a978691b8a28a7ad12 Mon Sep 17 00:00:00 2001 -From: Marc Deslauriers -Date: Mon, 8 Dec 2025 10:52:22 -0500 -Subject: [PATCH] CVE-2025-12748 - -Combined backported patches for CVE-2025-12748. - -NOTE: The original Ubuntu patches use 'header->compressed' but libvirt -10.9.0+ renamed this field to 'header->format' (upstream commit bd6d7ebf6). -This patch has been adjusted accordingly. - -Pre-requisite patch reference: -1. https://git.launchpad.net/ubuntu/+source/libvirt/patch/?id=42813e33416a8b4c052829bea5e8a938a7ba9eca -2. https://git.launchpad.net/ubuntu/+source/libvirt/patch/?id=d7d1c76f23d767698ce0838ec4eddf1b214c4bbf -3. https://git.launchpad.net/ubuntu/+source/libvirt/patch/?id=1991519ee70ae620312e808c5bfd1bc296208431 - -CVE-2025-12748.patch patch reference: -1. https://git.launchpad.net/ubuntu/+source/libvirt/patch/?id=4ceddd072ab794135b59364cb95386ef70b51b92 -2. https://git.launchpad.net/ubuntu/+source/libvirt/patch/?id=97a53db9756cbc880ed3f4dc054e9a15690a2176 -3. https://git.launchpad.net/ubuntu/+source/libvirt/patch/?id=1b8d1bd4b10e8eaa9a247487d709440ebba014ed -4. https://git.launchpad.net/ubuntu/+source/libvirt/patch/?id=7a62099efb32ca270e1808fead3263569b81eeea -5. https://git.launchpad.net/ubuntu/+source/libvirt/patch/?id=b4b37eb7ae3296c8b8520b5ad5e4cbce4dbcb8ca -6. https://git.launchpad.net/ubuntu/+source/libvirt/patch/?id=8928cf500e1a94b6f78bc5b1840fa300f18406dd -7. https://git.launchpad.net/ubuntu/+source/libvirt/patch/?id=e8e0d3ce28a0856c14d1fe3d2b5977f164938b9a -8. https://git.launchpad.net/ubuntu/+source/libvirt/patch/?id=6ab6e8705128808aa90b9281bcf046a8cf61dbba ---- -diff --git a/src/bhyve/bhyve_driver.c b/src/bhyve/bhyve_driver.c -index 2bd1e4c38..fdbdc3118 100644 ---- a/src/bhyve/bhyve_driver.c -+++ b/src/bhyve/bhyve_driver.c -@@ -505,6 +505,15 @@ bhyveDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flag - if (!caps) - return NULL; - -+ /* Avoid parsing the whole domain definition for ACL checks */ -+ if (!(def = virDomainDefIDsParseString(xml, privconn->xmlopt, parse_flags))) -+ return NULL; -+ -+ if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0) -+ return NULL; -+ -+ g_clear_pointer(&def, virDomainDefFree); -+ - if ((def = virDomainDefParseString(xml, privconn->xmlopt, - NULL, parse_flags)) == NULL) - goto cleanup; -@@ -512,9 +521,6 @@ bhyveDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flag - if (virXMLCheckIllegalChars("name", def->name, "\n") < 0) - goto cleanup; - -- if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0) -- goto cleanup; -- - if (bhyveDomainAssignAddresses(def, NULL) < 0) - goto cleanup; - -@@ -878,11 +884,17 @@ bhyveDomainCreateXML(virConnectPtr conn, - if (flags & VIR_DOMAIN_START_AUTODESTROY) - start_flags |= VIR_BHYVE_PROCESS_START_AUTODESTROY; - -- if ((def = virDomainDefParseString(xml, privconn->xmlopt, -- NULL, parse_flags)) == NULL) -- goto cleanup; -+ /* Avoid parsing the whole domain definition for ACL checks */ -+ if (!(def = virDomainDefIDsParseString(xml, privconn->xmlopt, parse_flags))) -+ return NULL; - - if (virDomainCreateXMLEnsureACL(conn, def) < 0) -+ return NULL; -+ -+ g_clear_pointer(&def, virDomainDefFree); -+ -+ if ((def = virDomainDefParseString(xml, privconn->xmlopt, -+ NULL, parse_flags)) == NULL) - goto cleanup; - - if (bhyveDomainAssignAddresses(def, NULL) < 0) -diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c -index 6a8da5f35..be93a3ae6 100644 ---- a/src/ch/ch_driver.c -+++ b/src/ch/ch_driver.c -@@ -215,14 +215,19 @@ chDomainCreateXML(virConnectPtr conn, - if (flags & VIR_DOMAIN_START_VALIDATE) - parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA; - -+ /* Avoid parsing the whole domain definition for ACL checks */ -+ if (!(vmdef = virDomainDefIDsParseString(xml, driver->xmlopt, parse_flags))) -+ return NULL; -+ -+ if (virDomainCreateXMLEnsureACL(conn, vmdef) < 0) -+ return NULL; -+ -+ g_clear_pointer(&vmdef, virDomainDefFree); - - if ((vmdef = virDomainDefParseString(xml, driver->xmlopt, - NULL, parse_flags)) == NULL) - goto cleanup; - -- if (virDomainCreateXMLEnsureACL(conn, vmdef) < 0) -- goto cleanup; -- - if (!(vm = virDomainObjListAdd(driver->domains, - &vmdef, - driver->xmlopt, -@@ -346,6 +351,15 @@ chDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flags) - if (flags & VIR_DOMAIN_START_VALIDATE) - parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA; - -+ /* Avoid parsing the whole domain definition for ACL checks */ -+ if (!(vmdef = virDomainDefIDsParseString(xml, driver->xmlopt, parse_flags))) -+ return NULL; -+ -+ if (virDomainDefineXMLFlagsEnsureACL(conn, vmdef) < 0) -+ return NULL; -+ -+ g_clear_pointer(&vmdef, virDomainDefFree); -+ - if ((vmdef = virDomainDefParseString(xml, driver->xmlopt, - NULL, parse_flags)) == NULL) - goto cleanup; -@@ -353,9 +367,6 @@ chDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flags) - if (virXMLCheckIllegalChars("name", vmdef->name, "\n") < 0) - goto cleanup; - -- if (virDomainDefineXMLFlagsEnsureACL(conn, vmdef) < 0) -- goto cleanup; -- - if (!(vm = virDomainObjListAdd(driver->domains, &vmdef, - driver->xmlopt, - 0, &oldDef))) -diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c -index 4ad8289b8..3b4b426b6 100644 ---- a/src/conf/domain_conf.c -+++ b/src/conf/domain_conf.c -@@ -19940,6 +19940,35 @@ virDomainDefParse(const char *xmlStr, - return virDomainDefParseNode(ctxt, xmlopt, parseOpaque, flags); - } - -+virDomainDef * -+virDomainDefIDsParseString(const char *xmlStr, -+ virDomainXMLOption *xmlopt, -+ unsigned int flags) -+{ -+ g_autoptr(virDomainDef) def = NULL; -+ g_autoptr(xmlDoc) xml = NULL; -+ g_autoptr(xmlXPathContext) ctxt = NULL; -+ bool uuid_generated = false; -+ -+ xml = virXMLParseWithIndent(NULL, xmlStr, _("(domain_definition)"), -+ "domain", &ctxt, "domain.rng", false); -+ -+ if (!xml) -+ return NULL; -+ -+ def = virDomainDefNew(xmlopt); -+ if (!def) -+ return NULL; -+ -+ if (virDomainDefParseIDs(def, ctxt, flags, &uuid_generated) < 0) -+ return NULL; -+ -+ if (uuid_generated) -+ memset(def->uuid, 0, VIR_UUID_BUFLEN); -+ -+ return g_steal_pointer(&def); -+} -+ - virDomainDef * - virDomainDefParseString(const char *xmlStr, - virDomainXMLOption *xmlopt, -diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h -index a187ab408..c748837ce 100644 ---- a/src/conf/domain_conf.h -+++ b/src/conf/domain_conf.h -@@ -3832,6 +3832,9 @@ virDomainDiskDef *virDomainDiskDefParse(const char *xmlStr, - virStorageSource *virDomainDiskDefParseSource(const char *xmlStr, - virDomainXMLOption *xmlopt, - unsigned int flags); -+virDomainDef * virDomainDefIDsParseString(const char *xmlStr, -+ virDomainXMLOption *xmlopt, -+ unsigned int flags); - virDomainDef *virDomainDefParseString(const char *xmlStr, - virDomainXMLOption *xmlopt, - void *parseOpaque, -diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms -index c931003fa..fb673576b 100644 ---- a/src/libvirt_private.syms -+++ b/src/libvirt_private.syms -@@ -347,6 +347,7 @@ virDomainDefHasSpiceGraphics; - virDomainDefHasUSB; - virDomainDefHasVcpusOffline; - virDomainDefHasVDPANet; -+virDomainDefIDsParseString; - virDomainDefLifecycleActionAllowed; - virDomainDefMaybeAddController; - virDomainDefMaybeAddInput; -diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c -index e72553603..df475a969 100644 ---- a/src/libxl/libxl_driver.c -+++ b/src/libxl/libxl_driver.c -@@ -1036,13 +1036,18 @@ libxlDomainCreateXML(virConnectPtr conn, const char *xml, - if (flags & VIR_DOMAIN_START_VALIDATE) - parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA; - -- if (!(def = virDomainDefParseString(xml, driver->xmlopt, -- NULL, parse_flags))) -+ if (!(def = virDomainDefIDsParseString(xml, driver->xmlopt, parse_flags))) - goto cleanup; - - if (virDomainCreateXMLEnsureACL(conn, def) < 0) - goto cleanup; - -+ g_clear_pointer(&def, virDomainDefFree); -+ -+ if (!(def = virDomainDefParseString(xml, driver->xmlopt, -+ NULL, parse_flags))) -+ goto cleanup; -+ - if (!(vm = virDomainObjListAdd(driver->domains, &def, - driver->xmlopt, - VIR_DOMAIN_OBJ_LIST_ADD_LIVE | -@@ -2822,6 +2827,14 @@ libxlDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flag - if (flags & VIR_DOMAIN_DEFINE_VALIDATE) - parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA; - -+ if (!(def = virDomainDefIDsParseString(xml, driver->xmlopt, parse_flags))) -+ goto cleanup; -+ -+ if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0) -+ goto cleanup; -+ -+ g_clear_pointer(&def, virDomainDefFree); -+ - if (!(def = virDomainDefParseString(xml, driver->xmlopt, - NULL, parse_flags))) - goto cleanup; -@@ -2829,9 +2842,6 @@ libxlDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flag - if (virXMLCheckIllegalChars("name", def->name, "\n") < 0) - goto cleanup; - -- if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0) -- goto cleanup; -- - if (!(vm = virDomainObjListAdd(driver->domains, &def, - driver->xmlopt, - 0, -diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c -index d682e7168..8c0aa61e9 100644 ---- a/src/lxc/lxc_driver.c -+++ b/src/lxc/lxc_driver.c -@@ -409,6 +409,15 @@ lxcDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flags) - if (!(caps = virLXCDriverGetCapabilities(driver, false))) - goto cleanup; - -+ /* Avoid parsing the whole domain definition for ACL checks */ -+ if (!(def = virDomainDefIDsParseString(xml, driver->xmlopt, parse_flags))) -+ goto cleanup; -+ -+ if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0) -+ goto cleanup; -+ -+ g_clear_pointer(&def, virDomainDefFree); -+ - if (!(def = virDomainDefParseString(xml, driver->xmlopt, - NULL, parse_flags))) - goto cleanup; -@@ -416,9 +425,6 @@ lxcDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flags) - if (virXMLCheckIllegalChars("name", def->name, "\n") < 0) - goto cleanup; - -- if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0) -- goto cleanup; -- - if (virSecurityManagerVerify(driver->securityManager, def) < 0) - goto cleanup; - -@@ -1078,13 +1084,19 @@ lxcDomainCreateXMLWithFiles(virConnectPtr conn, - if (!(caps = virLXCDriverGetCapabilities(driver, false))) - goto cleanup; - -- if (!(def = virDomainDefParseString(xml, driver->xmlopt, -- NULL, parse_flags))) -+ /* Avoid parsing the whole domain definition for ACL checks */ -+ if (!(def = virDomainDefIDsParseString(xml, driver->xmlopt, parse_flags))) - goto cleanup; - - if (virDomainCreateXMLWithFilesEnsureACL(conn, def) < 0) - goto cleanup; - -+ g_clear_pointer(&def, virDomainDefFree); -+ -+ if (!(def = virDomainDefParseString(xml, driver->xmlopt, -+ NULL, parse_flags))) -+ goto cleanup; -+ - if (virSecurityManagerVerify(driver->securityManager, def) < 0) - goto cleanup; - -diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c -index 09f7edda7..96e0cb88b 100644 ---- a/src/qemu/qemu_driver.c -+++ b/src/qemu/qemu_driver.c -@@ -1588,11 +1588,17 @@ static virDomainPtr qemuDomainCreateXML(virConnectPtr conn, - if (flags & VIR_DOMAIN_START_RESET_NVRAM) - start_flags |= VIR_QEMU_PROCESS_START_RESET_NVRAM; - -- if (!(def = virDomainDefParseString(xml, driver->xmlopt, -- NULL, parse_flags))) -- goto cleanup; -+ /* Avoid parsing the whole domain definition for ACL checks */ -+ if (!(def = virDomainDefIDsParseString(xml, driver->xmlopt, parse_flags))) -+ return NULL; - - if (virDomainCreateXMLEnsureACL(conn, def) < 0) -+ return NULL; -+ -+ g_clear_pointer(&def, virDomainDefFree); -+ -+ if (!(def = virDomainDefParseString(xml, driver->xmlopt, -+ NULL, parse_flags))) - goto cleanup; - - if (!(vm = virDomainObjListAdd(driver->domains, &def, -@@ -5769,13 +5775,13 @@ qemuDomainRestoreInternal(virConnectPtr conn, - if (flags & VIR_DOMAIN_SAVE_RESET_NVRAM) - reset_nvram = true; - -- fd = qemuSaveImageOpen(driver, NULL, path, &def, &data, -- (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0, -- &wrapperFd, false, false); -- if (fd < 0) -+ if (qemuSaveImageGetMetadata(driver, NULL, path, ensureACL, conn, &def, &data) < 0) - goto cleanup; - -- if (ensureACL(conn, def) < 0) -+ fd = qemuSaveImageOpen(driver, path, -+ (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0, -+ &wrapperFd, false); -+ if (fd < 0) - goto cleanup; - - if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) { -@@ -5900,25 +5906,19 @@ qemuDomainSaveImageGetXMLDesc(virConnectPtr conn, const char *path, - virQEMUDriver *driver = conn->privateData; - char *ret = NULL; - g_autoptr(virDomainDef) def = NULL; -- int fd = -1; - virQEMUSaveData *data = NULL; - - virCheckFlags(VIR_DOMAIN_SAVE_IMAGE_XML_SECURE, NULL); - -- fd = qemuSaveImageOpen(driver, NULL, path, &def, &data, -- false, NULL, false, false); -- -- if (fd < 0) -- goto cleanup; -- -- if (virDomainSaveImageGetXMLDescEnsureACL(conn, def) < 0) -+ if (qemuSaveImageGetMetadata(driver, NULL, path, -+ virDomainSaveImageGetXMLDescEnsureACL, -+ conn, &def, &data) < 0) - goto cleanup; - - ret = qemuDomainDefFormatXML(driver, NULL, def, flags); - - cleanup: - virQEMUSaveDataFree(data); -- VIR_FORCE_CLOSE(fd); - return ret; - } - -@@ -5942,13 +5942,13 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path, - else if (flags & VIR_DOMAIN_SAVE_PAUSED) - state = 0; - -- fd = qemuSaveImageOpen(driver, NULL, path, &def, &data, -- false, NULL, true, false); -- -- if (fd < 0) -+ if (qemuSaveImageGetMetadata(driver, NULL, path, -+ virDomainSaveImageDefineXMLEnsureACL, -+ conn, &def, &data) < 0) - goto cleanup; - -- if (virDomainSaveImageDefineXMLEnsureACL(conn, def) < 0) -+ fd = qemuSaveImageOpen(driver, path, 0, NULL, false); -+ if (fd < 0) - goto cleanup; - - if (STREQ(data->xml, dxml) && -@@ -6001,7 +6001,6 @@ qemuDomainManagedSaveGetXMLDesc(virDomainPtr dom, unsigned int flags) - g_autofree char *path = NULL; - char *ret = NULL; - g_autoptr(virDomainDef) def = NULL; -- int fd = -1; - virQEMUSaveData *data = NULL; - qemuDomainObjPrivate *priv; - -@@ -6023,15 +6022,14 @@ qemuDomainManagedSaveGetXMLDesc(virDomainPtr dom, unsigned int flags) - goto cleanup; - } - -- if ((fd = qemuSaveImageOpen(driver, priv->qemuCaps, path, &def, &data, -- false, NULL, false, false)) < 0) -+ if (qemuSaveImageGetMetadata(driver, priv->qemuCaps, path, -+ NULL, NULL, &def, &data) < 0) - goto cleanup; - - ret = qemuDomainDefFormatXML(driver, priv->qemuCaps, def, flags); - - cleanup: - virQEMUSaveDataFree(data); -- VIR_FORCE_CLOSE(fd); - virDomainObjEndAPI(&vm); - return ret; - } -@@ -6087,14 +6085,26 @@ qemuDomainObjRestore(virConnectPtr conn, - virQEMUSaveData *data = NULL; - virFileWrapperFd *wrapperFd = NULL; - -- fd = qemuSaveImageOpen(driver, NULL, path, &def, &data, -- bypass_cache, &wrapperFd, false, true); -- if (fd < 0) { -- if (fd == -3) -- ret = 1; -+ ret = qemuSaveImageGetMetadata(driver, NULL, path, NULL, NULL, &def, &data); -+ if (ret < 0) { -+ if (qemuSaveImageIsCorrupt(driver, path)) { -+ if (unlink(path) < 0) { -+ virReportSystemError(errno, -+ _("cannot remove corrupt file: %1$s"), -+ path); -+ ret = -1; -+ } else { -+ virResetLastError(); -+ ret = 1; -+ } -+ } - goto cleanup; - } - -+ fd = qemuSaveImageOpen(driver, path, bypass_cache, &wrapperFd, false); -+ if (fd < 0) -+ goto cleanup; -+ - if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) { - int hookret; - -@@ -6423,6 +6433,15 @@ qemuDomainDefineXMLFlags(virConnectPtr conn, - if (flags & VIR_DOMAIN_DEFINE_VALIDATE) - parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA; - -+ /* Avoid parsing the whole domain definition for ACL checks */ -+ if (!(def = virDomainDefIDsParseString(xml, driver->xmlopt, parse_flags))) -+ return NULL; -+ -+ if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0) -+ return NULL; -+ -+ g_clear_pointer(&def, virDomainDefFree); -+ - if (!(def = virDomainDefParseString(xml, driver->xmlopt, - NULL, parse_flags))) - return NULL; -@@ -6430,9 +6449,6 @@ qemuDomainDefineXMLFlags(virConnectPtr conn, - if (virXMLCheckIllegalChars("name", def->name, "\n") < 0) - goto cleanup; - -- if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0) -- goto cleanup; -- - if (!(vm = virDomainObjListAdd(driver->domains, &def, - driver->xmlopt, - 0, &oldDef))) -@@ -10667,10 +10683,9 @@ qemuDomainMigratePrepareTunnel(virConnectPtr dconn, - return -1; - } - -- if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname))) -- return -1; -- -- if (virDomainMigratePrepareTunnelEnsureACL(dconn, def) < 0) -+ if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname, -+ dconn, -+ virDomainMigratePrepareTunnelEnsureACL))) - return -1; - - return qemuMigrationDstPrepareTunnel(driver, dconn, -@@ -10720,10 +10735,9 @@ qemuDomainMigratePrepare2(virConnectPtr dconn, - return -1; - } - -- if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname))) -- return -1; -- -- if (virDomainMigratePrepare2EnsureACL(dconn, def) < 0) -+ if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname, -+ dconn, -+ virDomainMigratePrepare2EnsureACL))) - return -1; - - /* Do not use cookies in v2 protocol, since the cookie -@@ -10943,10 +10957,9 @@ qemuDomainMigratePrepare3(virConnectPtr dconn, - QEMU_MIGRATION_DESTINATION))) - return -1; - -- if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname))) -- return -1; -- -- if (virDomainMigratePrepare3EnsureACL(dconn, def) < 0) -+ if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname, -+ dconn, -+ virDomainMigratePrepare3EnsureACL))) - return -1; - - return qemuMigrationDstPrepareDirect(driver, dconn, -@@ -11046,10 +11059,9 @@ qemuDomainMigratePrepare3Params(virConnectPtr dconn, - return -1; - } - -- if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname))) -- return -1; -- -- if (virDomainMigratePrepare3ParamsEnsureACL(dconn, def) < 0) -+ if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname, -+ dconn, -+ virDomainMigratePrepare3ParamsEnsureACL))) - return -1; - - return qemuMigrationDstPrepareDirect(driver, dconn, -@@ -11091,10 +11103,9 @@ qemuDomainMigratePrepareTunnel3(virConnectPtr dconn, - QEMU_MIGRATION_DESTINATION))) - return -1; - -- if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname))) -- return -1; -- -- if (virDomainMigratePrepareTunnel3EnsureACL(dconn, def) < 0) -+ if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname, -+ dconn, -+ virDomainMigratePrepareTunnel3EnsureACL))) - return -1; - - return qemuMigrationDstPrepareTunnel(driver, dconn, -@@ -11143,10 +11154,9 @@ qemuDomainMigratePrepareTunnel3Params(virConnectPtr dconn, - QEMU_MIGRATION_DESTINATION))) - return -1; - -- if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname))) -- return -1; -- -- if (virDomainMigratePrepareTunnel3ParamsEnsureACL(dconn, def) < 0) -+ if (!(def = qemuMigrationAnyPrepareDef(driver, NULL, dom_xml, dname, &origname, -+ dconn, -+ virDomainMigratePrepareTunnel3ParamsEnsureACL))) - return -1; - - return qemuMigrationDstPrepareTunnel(driver, dconn, -diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c -index 26a92d8ee..9c6b76728 100644 ---- a/src/qemu/qemu_migration.c -+++ b/src/qemu/qemu_migration.c -@@ -3957,7 +3957,9 @@ qemuMigrationAnyPrepareDef(virQEMUDriver *driver, - virQEMUCaps *qemuCaps, - const char *dom_xml, - const char *dname, -- char **origname) -+ char **origname, -+ virConnectPtr sconn, -+ int (*ensureACL)(virConnectPtr, virDomainDef *)) - { - virDomainDef *def; - char *name = NULL; -@@ -3968,6 +3970,24 @@ qemuMigrationAnyPrepareDef(virQEMUDriver *driver, - return NULL; - } - -+ if (ensureACL) { -+ g_autoptr(virDomainDef) aclDef = NULL; -+ -+ /* Avoid parsing the whole domain definition for ACL checks */ -+ if (!(aclDef = virDomainDefIDsParseString(dom_xml, driver->xmlopt, -+ VIR_DOMAIN_DEF_PARSE_INACTIVE))) -+ return NULL; -+ -+ if (dname) { -+ VIR_FREE(aclDef->name); -+ aclDef->name = g_strdup(dname); -+ } -+ -+ if (ensureACL(sconn, aclDef) < 0) { -+ return NULL; -+ } -+ } -+ - if (!(def = virDomainDefParseString(dom_xml, driver->xmlopt, - qemuCaps, - VIR_DOMAIN_DEF_PARSE_INACTIVE))) -@@ -4899,6 +4919,7 @@ qemuMigrationSrcRun(virQEMUDriver *driver, - if (!(persistDef = qemuMigrationAnyPrepareDef(driver, - priv->qemuCaps, - persist_xml, -+ NULL, NULL, - NULL, NULL))) - goto error; - } else { -diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h -index 4b7ef9688..1fca93edd 100644 ---- a/src/qemu/qemu_migration.h -+++ b/src/qemu/qemu_migration.h -@@ -133,7 +133,9 @@ qemuMigrationAnyPrepareDef(virQEMUDriver *driver, - virQEMUCaps *qemuCaps, - const char *dom_xml, - const char *dname, -- char **origname); -+ char **origname, -+ virConnectPtr sconn, -+ int (*ensureACL)(virConnectPtr, virDomainDef *)); - - int - qemuMigrationDstPrepareTunnel(virQEMUDriver *driver, -diff --git a/src/qemu/qemu_saveimage.c b/src/qemu/qemu_saveimage.c -index 69617e07e..d9d53e33a 100644 ---- a/src/qemu/qemu_saveimage.c -+++ b/src/qemu/qemu_saveimage.c -@@ -249,6 +249,90 @@ qemuSaveImageGetCompressionCommand(virQEMUSaveFormat format) - } - - -+static int -+qemuSaveImageReadHeader(int fd, virQEMUSaveData **ret_data) -+{ -+ g_autoptr(virQEMUSaveData) data = NULL; -+ virQEMUSaveHeader *header; -+ size_t xml_len; -+ size_t cookie_len; -+ -+ data = g_new0(virQEMUSaveData, 1); -+ header = &data->header; -+ if (saferead(fd, header, sizeof(*header)) != sizeof(*header)) { -+ virReportError(VIR_ERR_OPERATION_FAILED, -+ "%s", _("failed to read qemu header")); -+ return -1; -+ } -+ -+ if (memcmp(header->magic, QEMU_SAVE_MAGIC, sizeof(header->magic)) != 0) { -+ if (memcmp(header->magic, QEMU_SAVE_PARTIAL, sizeof(header->magic)) == 0) { -+ virReportError(VIR_ERR_OPERATION_FAILED, "%s", -+ _("save image is incomplete")); -+ return -1; -+ } -+ -+ virReportError(VIR_ERR_OPERATION_FAILED, "%s", -+ _("image magic is incorrect")); -+ return -1; -+ } -+ -+ if (header->version > QEMU_SAVE_VERSION) { -+ /* convert endianness and try again */ -+ qemuSaveImageBswapHeader(header); -+ } -+ -+ if (header->version > QEMU_SAVE_VERSION) { -+ virReportError(VIR_ERR_OPERATION_FAILED, -+ _("image version is not supported (%1$d > %2$d)"), -+ header->version, QEMU_SAVE_VERSION); -+ return -1; -+ } -+ -+ if (header->format >= QEMU_SAVE_FORMAT_LAST) { -+ virReportError(VIR_ERR_OPERATION_FAILED, -+ _("unsupported save image format: %1$d"), header->format); -+ return -1; -+ } -+ -+ if (header->data_len <= 0) { -+ virReportError(VIR_ERR_OPERATION_FAILED, -+ _("invalid header data length: %1$d"), header->data_len); -+ return -1; -+ } -+ -+ if (header->cookieOffset) -+ xml_len = header->cookieOffset; -+ else -+ xml_len = header->data_len; -+ -+ cookie_len = header->data_len - xml_len; -+ -+ data->xml = g_new0(char, xml_len); -+ -+ if (saferead(fd, data->xml, xml_len) != xml_len) { -+ virReportError(VIR_ERR_OPERATION_FAILED, -+ "%s", _("failed to read domain XML")); -+ return -1; -+ } -+ -+ if (cookie_len > 0) { -+ data->cookie = g_new0(char, cookie_len); -+ -+ if (saferead(fd, data->cookie, cookie_len) != cookie_len) { -+ virReportError(VIR_ERR_OPERATION_FAILED, "%s", -+ _("failed to read cookie")); -+ return -1; -+ } -+ } -+ -+ if (ret_data) -+ *ret_data = g_steal_pointer(&data); -+ -+ return 0; -+} -+ -+ - /** - * qemuSaveImageDecompressionStart: - * @data: data from memory state file -@@ -522,41 +606,116 @@ qemuSaveImageGetCompressionProgram(const char *imageFormat, - - - /** -- * qemuSaveImageOpen: -+ * qemuSaveImageIsCorrupt: -+ * @driver: qemu driver data -+ * @path: path of the save image -+ * -+ * Returns true if the save image file identified by @path does not exist or -+ * has a corrupt header. Returns false otherwise. -+ */ -+ -+bool -+qemuSaveImageIsCorrupt(virQEMUDriver *driver, const char *path) -+{ -+ g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); -+ VIR_AUTOCLOSE fd = -1; -+ virQEMUSaveHeader header; -+ -+ if ((fd = qemuDomainOpenFile(cfg, NULL, path, O_RDONLY, NULL)) < 0) -+ return true; -+ -+ if (saferead(fd, &header, sizeof(header)) != sizeof(header)) -+ return true; -+ -+ if (memcmp(header.magic, QEMU_SAVE_MAGIC, sizeof(header.magic)) != 0 || -+ memcmp(header.magic, QEMU_SAVE_PARTIAL, sizeof(header.magic)) == 0) -+ return true; -+ -+ return false; -+} -+ -+ -+/** -+ * qemuSaveImageGetMetadata: - * @driver: qemu driver data - * @qemuCaps: pointer to qemuCaps if the domain is running or NULL - * @path: path of the save image -+ * @ensureACL: ACL callback to check against the definition or NULL -+ * @conn: parameter for the @ensureACL callback - * @ret_def: returns domain definition created from the XML stored in the image - * @ret_data: returns structure filled with data from the image header -+ * -+ * Open the save image file, read libvirt's save image metadata, optionally -+ * check ACLs before parsing the whole domain definition and populate the -+ * @ret_def and @ret_data structures. Returns 0 on success and -1 on failure. -+ */ -+int -+qemuSaveImageGetMetadata(virQEMUDriver *driver, -+ virQEMUCaps *qemuCaps, -+ const char *path, -+ int (*ensureACL)(virConnectPtr, virDomainDef *), -+ virConnectPtr conn, -+ virDomainDef **ret_def, -+ virQEMUSaveData **ret_data) -+{ -+ g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); -+ VIR_AUTOCLOSE fd = -1; -+ virQEMUSaveData *data; -+ g_autoptr(virDomainDef) def = NULL; -+ unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE | -+ VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE; -+ int rc; -+ -+ if ((fd = qemuDomainOpenFile(cfg, NULL, path, O_RDONLY, NULL)) < 0) -+ return -1; -+ -+ if ((rc = qemuSaveImageReadHeader(fd, ret_data)) < 0) -+ return rc; -+ -+ data = *ret_data; -+ -+ if (ensureACL) { -+ /* Parse only the IDs for ACL checks */ -+ g_autoptr(virDomainDef) aclDef = virDomainDefIDsParseString(data->xml, -+ driver->xmlopt, -+ parse_flags); -+ -+ if (!aclDef || ensureACL(conn, aclDef) < 0) -+ return -1; -+ } -+ -+ /* Create a domain from this XML */ -+ if (!(def = virDomainDefParseString(data->xml, driver->xmlopt, qemuCaps, -+ parse_flags))) -+ return -1; -+ -+ *ret_def = g_steal_pointer(&def); -+ -+ return 0; -+} -+ -+ -+/** -+ * qemuSaveImageOpen: -+ * @driver: qemu driver data -+ * @path: path of the save image - * @bypass_cache: bypass cache when opening the file - * @wrapperFd: returns the file wrapper structure - * @open_write: open the file for writing (for updates) -- * @unlink_corrupt: remove the image file if it is corrupted - * -- * Returns the opened fd of the save image file and fills the appropriate fields -- * on success. On error returns -1 on most failures, -3 if corrupt image was -- * unlinked (no error raised). -+ * Returns the opened fd of the save image file on success, -1 on failure. - */ - int - qemuSaveImageOpen(virQEMUDriver *driver, -- virQEMUCaps *qemuCaps, - const char *path, -- virDomainDef **ret_def, -- virQEMUSaveData **ret_data, - bool bypass_cache, - virFileWrapperFd **wrapperFd, -- bool open_write, -- bool unlink_corrupt) -+ bool open_write) - { - g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); - VIR_AUTOCLOSE fd = -1; - int ret = -1; -- g_autoptr(virQEMUSaveData) data = NULL; -- virQEMUSaveHeader *header; -- g_autoptr(virDomainDef) def = NULL; - int oflags = open_write ? O_RDWR : O_RDONLY; -- size_t xml_len; -- size_t cookie_len; - - if (bypass_cache) { - int directFlag = virFileDirectFdFlag(); -@@ -576,100 +735,10 @@ qemuSaveImageOpen(virQEMUDriver *driver, - VIR_FILE_WRAPPER_BYPASS_CACHE))) - return -1; - -- data = g_new0(virQEMUSaveData, 1); -- -- header = &data->header; -- if (saferead(fd, header, sizeof(*header)) != sizeof(*header)) { -- if (unlink_corrupt) { -- if (unlink(path) < 0) { -- virReportSystemError(errno, -- _("cannot remove corrupt file: %1$s"), -- path); -- return -1; -- } else { -- return -3; -- } -- } -- -- virReportError(VIR_ERR_OPERATION_FAILED, -- "%s", _("failed to read qemu header")); -+ /* Read the header to position the file pointer for QEMU. Unfortunately we -+ * can't use lseek with virFileWrapperFD. */ -+ if (qemuSaveImageReadHeader(fd, NULL) < 0) - return -1; -- } -- -- if (memcmp(header->magic, QEMU_SAVE_MAGIC, sizeof(header->magic)) != 0) { -- if (memcmp(header->magic, QEMU_SAVE_PARTIAL, sizeof(header->magic)) == 0) { -- if (unlink_corrupt) { -- if (unlink(path) < 0) { -- virReportSystemError(errno, -- _("cannot remove corrupt file: %1$s"), -- path); -- return -1; -- } else { -- return -3; -- } -- } -- -- virReportError(VIR_ERR_OPERATION_FAILED, "%s", -- _("save image is incomplete")); -- return -1; -- } -- -- virReportError(VIR_ERR_OPERATION_FAILED, "%s", -- _("image magic is incorrect")); -- return -1; -- } -- -- if (header->version > QEMU_SAVE_VERSION) { -- /* convert endianness and try again */ -- qemuSaveImageBswapHeader(header); -- } -- -- if (header->version > QEMU_SAVE_VERSION) { -- virReportError(VIR_ERR_OPERATION_FAILED, -- _("image version is not supported (%1$d > %2$d)"), -- header->version, QEMU_SAVE_VERSION); -- return -1; -- } -- -- if (header->data_len <= 0) { -- virReportError(VIR_ERR_OPERATION_FAILED, -- _("invalid header data length: %1$d"), header->data_len); -- return -1; -- } -- -- if (header->cookieOffset) -- xml_len = header->cookieOffset; -- else -- xml_len = header->data_len; -- -- cookie_len = header->data_len - xml_len; -- -- data->xml = g_new0(char, xml_len); -- -- if (saferead(fd, data->xml, xml_len) != xml_len) { -- virReportError(VIR_ERR_OPERATION_FAILED, -- "%s", _("failed to read domain XML")); -- return -1; -- } -- -- if (cookie_len > 0) { -- data->cookie = g_new0(char, cookie_len); -- -- if (saferead(fd, data->cookie, cookie_len) != cookie_len) { -- virReportError(VIR_ERR_OPERATION_FAILED, "%s", -- _("failed to read cookie")); -- return -1; -- } -- } -- -- /* Create a domain from this XML */ -- if (!(def = virDomainDefParseString(data->xml, driver->xmlopt, qemuCaps, -- VIR_DOMAIN_DEF_PARSE_INACTIVE | -- VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE))) -- return -1; -- -- *ret_def = g_steal_pointer(&def); -- *ret_data = g_steal_pointer(&data); - - ret = fd; - fd = -1; -diff --git a/src/qemu/qemu_saveimage.h b/src/qemu/qemu_saveimage.h -index 0e58dd14b..2527042c4 100644 ---- a/src/qemu/qemu_saveimage.h -+++ b/src/qemu/qemu_saveimage.h -@@ -69,17 +69,28 @@ qemuSaveImageStartVM(virConnectPtr conn, - virDomainAsyncJob asyncJob) - ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5) ATTRIBUTE_NONNULL(6); - -+bool -+qemuSaveImageIsCorrupt(virQEMUDriver *driver, -+ const char *path) -+ ATTRIBUTE_NONNULL(2); -+ -+int -+qemuSaveImageGetMetadata(virQEMUDriver *driver, -+ virQEMUCaps *qemuCaps, -+ const char *path, -+ int (*ensureACL)(virConnectPtr, virDomainDef *), -+ virConnectPtr conn, -+ virDomainDef **ret_def, -+ virQEMUSaveData **ret_data) -+ ATTRIBUTE_NONNULL(6) ATTRIBUTE_NONNULL(7); -+ - int - qemuSaveImageOpen(virQEMUDriver *driver, -- virQEMUCaps *qemuCaps, - const char *path, -- virDomainDef **ret_def, -- virQEMUSaveData **ret_data, - bool bypass_cache, - virFileWrapperFd **wrapperFd, -- bool open_write, -- bool unlink_corrupt) -- ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4); -+ bool open_write) -+ ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4); - - int - qemuSaveImageGetCompressionProgram(const char *imageFormat, -diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c -index 18b2e478f..98d822898 100644 ---- a/src/qemu/qemu_snapshot.c -+++ b/src/qemu/qemu_snapshot.c -@@ -2377,11 +2377,12 @@ qemuSnapshotRevertExternalPrepare(virDomainObj *vm, - g_autoptr(virDomainDef) savedef = NULL; - - memdata->path = snapdef->memorysnapshotfile; -- memdata->fd = qemuSaveImageOpen(driver, NULL, memdata->path, -- &savedef, &memdata->data, -- false, NULL, -- false, false); -+ if (qemuSaveImageGetMetadata(driver, NULL, memdata->path, NULL, NULL, -+ &savedef, &memdata->data) < 0) -+ return -1; - -+ memdata->fd = qemuSaveImageOpen(driver, memdata->path, -+ false, NULL, false); - if (memdata->fd < 0) - return -1; - -diff --git a/src/vz/vz_driver.c b/src/vz/vz_driver.c -index 4edea4bf1..8596e02c4 100644 ---- a/src/vz/vz_driver.c -+++ b/src/vz/vz_driver.c -@@ -796,6 +796,15 @@ vzDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flags) - if (flags & VIR_DOMAIN_DEFINE_VALIDATE) - parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA; - -+ /* Avoid parsing the whole domain definition for ACL checks */ -+ if (!(def = virDomainDefIDsParseString(xml, driver->xmlopt, parse_flags))) -+ return NULL; -+ -+ if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0) -+ return NULL; -+ -+ g_clear_pointer(&def, virDomainDefFree); -+ - if ((def = virDomainDefParseString(xml, driver->xmlopt, - NULL, parse_flags)) == NULL) - goto cleanup; -@@ -803,9 +812,6 @@ vzDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flags) - if (virXMLCheckIllegalChars("name", def->name, "\n") < 0) - goto cleanup; - -- if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0) -- goto cleanup; -- - dom = virDomainObjListFindByUUID(driver->domains, def->uuid); - if (dom == NULL) { - virResetLastError(); -@@ -2973,9 +2979,9 @@ vzDomainMigratePrepare3Params(virConnectPtr conn, - | VZ_MIGRATION_COOKIE_DOMAIN_NAME) < 0) - return -1; - -- if (!(def = virDomainDefParseString(dom_xml, driver->xmlopt, -- NULL, -- VIR_DOMAIN_DEF_PARSE_INACTIVE))) -+ /* Avoid parsing the whole domain definition for ACL checks */ -+ if (!(def = virDomainDefIDsParseString(dom_xml, driver->xmlopt, -+ VIR_DOMAIN_DEF_PARSE_INACTIVE))) - return -1; - - if (dname) { diff --git a/SPECS/libvirt/libvirt-qemu-Properly-propagate-migration-state-to-TPM-cleanup-code.patch b/SPECS/libvirt/libvirt-qemu-Properly-propagate-migration-state-to-TPM-cleanup-code.patch deleted file mode 100644 index 1060783e1f9..00000000000 --- a/SPECS/libvirt/libvirt-qemu-Properly-propagate-migration-state-to-TPM-cleanup-code.patch +++ /dev/null @@ -1,135 +0,0 @@ -From b6e803fc90bb9d49345adca4f38856ce97fde9f8 Mon Sep 17 00:00:00 2001 -Message-ID: -From: Jiri Denemark -Date: Wed, 9 Apr 2025 15:35:20 +0200 -Subject: [PATCH] qemu: Properly propagate migration state to TPM cleanup code -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -When migrating a domain with TPM state on a shared disk, we need to skip -TPM cleanup on both ends. So far the code only handled successful -migration and skipped the cleanup on the source host. But if the -migration failed for some reason, the cleanup would be incorrectly -called on the destination host removing the TPM files even though the -domain was still running on the source host. - -https://issues.redhat.com/browse/RHEL-82411 - -Signed-off-by: Jiri Denemark -Reviewed-by: Ján Tomko -(cherry picked from commit 97ed7f22b089c5fdd9ee02cffc6854f6e021ab2b) - -https://issues.redhat.com/browse/RHEL-86800 -Signed-off-by: Jiri Denemark ---- - src/qemu/qemu_driver.c | 7 +++++-- - src/qemu/qemu_migration.c | 6 +++--- - src/qemu/qemu_process.c | 8 ++------ - 3 files changed, 10 insertions(+), 11 deletions(-) - -diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c -index f8f3d2c725..4c6eff9286 100644 ---- a/src/qemu/qemu_driver.c -+++ b/src/qemu/qemu_driver.c -@@ -3853,6 +3853,7 @@ processMonitorEOFEvent(virQEMUDriver *driver, - const char *auditReason = "shutdown"; - unsigned int stopFlags = 0; - virObjectEvent *event = NULL; -+ bool migration; - - if (vm->def->id != domid) { - VIR_DEBUG("Domain %s was restarted, ignoring EOF", -@@ -3863,6 +3864,8 @@ processMonitorEOFEvent(virQEMUDriver *driver, - if (qemuProcessBeginStopJob(vm, VIR_JOB_DESTROY, true) < 0) - return; - -+ migration = vm->job->asyncJob == VIR_ASYNC_JOB_MIGRATION_IN; -+ - if (!virDomainObjIsActive(vm)) { - VIR_DEBUG("Domain %p '%s' is not active, ignoring EOF", - vm, vm->def->name); -@@ -3877,7 +3880,7 @@ processMonitorEOFEvent(virQEMUDriver *driver, - auditReason = "failed"; - } - -- if (vm->job->asyncJob == VIR_ASYNC_JOB_MIGRATION_IN) { -+ if (migration) { - stopFlags |= VIR_QEMU_PROCESS_STOP_MIGRATED; - qemuMigrationDstErrorSave(driver, vm->def->name, - qemuMonitorLastError(priv->mon)); -@@ -3890,7 +3893,7 @@ processMonitorEOFEvent(virQEMUDriver *driver, - virObjectEventStateQueue(driver->domainEventState, event); - - endjob: -- qemuDomainRemoveInactive(driver, vm, 0, false); -+ qemuDomainRemoveInactive(driver, vm, 0, migration); - qemuProcessEndStopJob(vm); - } - -diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c -index 62da892254..5cb7642315 100644 ---- a/src/qemu/qemu_migration.c -+++ b/src/qemu/qemu_migration.c -@@ -3592,7 +3592,7 @@ qemuMigrationDstPrepareFresh(virQEMUDriver *driver, - * and there is no 'goto cleanup;' in the middle of those */ - VIR_FREE(priv->origname); - virDomainObjRemoveTransientDef(vm); -- qemuDomainRemoveInactive(driver, vm, 0, false); -+ qemuDomainRemoveInactive(driver, vm, 0, true); - } - virDomainObjEndAPI(&vm); - virErrorRestore(&origErr); -@@ -6963,7 +6963,7 @@ qemuMigrationDstFinishActive(virQEMUDriver *driver, - } - - if (!qemuDomainObjIsActive(vm)) -- qemuDomainRemoveInactive(driver, vm, VIR_DOMAIN_UNDEFINE_TPM, false); -+ qemuDomainRemoveInactive(driver, vm, VIR_DOMAIN_UNDEFINE_TPM, true); - - virErrorRestore(&orig_err); - return NULL; -@@ -7099,7 +7099,7 @@ qemuMigrationProcessUnattended(virQEMUDriver *driver, - qemuMigrationJobFinish(vm); - - if (!virDomainObjIsActive(vm)) -- qemuDomainRemoveInactive(driver, vm, 0, false); -+ qemuDomainRemoveInactive(driver, vm, 0, true); - } - - -diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c -index fac5678439..ad7e99750f 100644 ---- a/src/qemu/qemu_process.c -+++ b/src/qemu/qemu_process.c -@@ -8731,7 +8731,6 @@ void qemuProcessStop(virQEMUDriver *driver, - size_t i; - g_autofree char *timestamp = NULL; - g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); -- bool outgoingMigration; - - VIR_DEBUG("Shutting down vm=%p name=%s id=%d pid=%lld, " - "reason=%s, asyncJob=%s, flags=0x%x", -@@ -8807,10 +8806,7 @@ void qemuProcessStop(virQEMUDriver *driver, - - qemuDomainCleanupRun(driver, vm); - -- outgoingMigration = (flags & VIR_QEMU_PROCESS_STOP_MIGRATED) && -- (asyncJob == VIR_ASYNC_JOB_MIGRATION_OUT); -- -- qemuExtDevicesStop(driver, vm, outgoingMigration); -+ qemuExtDevicesStop(driver, vm, !!(flags & VIR_QEMU_PROCESS_STOP_MIGRATED)); - - qemuDBusStop(driver, vm); - -@@ -9070,7 +9066,7 @@ qemuProcessAutoDestroy(virDomainObj *dom, - VIR_DOMAIN_EVENT_STOPPED, - VIR_DOMAIN_EVENT_STOPPED_DESTROYED); - -- qemuDomainRemoveInactive(driver, dom, 0, false); -+ qemuDomainRemoveInactive(driver, dom, 0, !!(stopFlags & VIR_QEMU_PROCESS_STOP_MIGRATED)); - - qemuProcessEndStopJob(dom); - --- -2.49.0 diff --git a/SPECS/libvirt/libvirt-qemu-Rename-outgoingMigration-parameter-in-various-TPM-functions.patch b/SPECS/libvirt/libvirt-qemu-Rename-outgoingMigration-parameter-in-various-TPM-functions.patch deleted file mode 100644 index ed7eb10fc14..00000000000 --- a/SPECS/libvirt/libvirt-qemu-Rename-outgoingMigration-parameter-in-various-TPM-functions.patch +++ /dev/null @@ -1,230 +0,0 @@ -From c28859cbaeac298adbe957956cf8442c9a6b7264 Mon Sep 17 00:00:00 2001 -Message-ID: -From: Jiri Denemark -Date: Tue, 11 Mar 2025 10:05:28 +0100 -Subject: [PATCH] qemu: Rename outgoingMigration parameter in various TPM - functions -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The parameter is used to skip TPM state cleanup on outgoing migration -with shared storage. But we also need to skip the cleanup after a failed -incoming migration. Let's call the parameter "migration" to reflect its -usage on both sides of migration. - -Signed-off-by: Jiri Denemark -Reviewed-by: Ján Tomko -(cherry picked from commit a5e4ca6f02dc8250f84163a0d19b69300affde43) - -https://issues.redhat.com/browse/RHEL-86800 -Signed-off-by: Jiri Denemark ---- - src/qemu/qemu_domain.c | 8 ++++---- - src/qemu/qemu_domain.h | 2 +- - src/qemu/qemu_extdevice.c | 8 ++++---- - src/qemu/qemu_extdevice.h | 4 ++-- - src/qemu/qemu_tpm.c | 19 +++++++++---------- - src/qemu/qemu_tpm.h | 4 ++-- - 6 files changed, 22 insertions(+), 23 deletions(-) - -diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c -index 1ccaff90d9..89e1b50366 100644 ---- a/src/qemu/qemu_domain.c -+++ b/src/qemu/qemu_domain.c -@@ -5749,7 +5749,7 @@ static void - qemuDomainRemoveInactiveCommon(virQEMUDriver *driver, - virDomainObj *vm, - virDomainUndefineFlagsValues flags, -- bool outgoingMigration) -+ bool migration) - { - g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); - g_autofree char *snapDir = NULL; -@@ -5775,7 +5775,7 @@ qemuDomainRemoveInactiveCommon(virQEMUDriver *driver, - if (rmdir(chkDir) < 0 && errno != ENOENT) - VIR_WARN("unable to remove checkpoint directory %s", chkDir); - } -- qemuExtDevicesCleanupHost(driver, vm->def, flags, outgoingMigration); -+ qemuExtDevicesCleanupHost(driver, vm->def, flags, migration); - } - - -@@ -5788,14 +5788,14 @@ void - qemuDomainRemoveInactive(virQEMUDriver *driver, - virDomainObj *vm, - virDomainUndefineFlagsValues flags, -- bool outgoingMigration) -+ bool migration) - { - if (vm->persistent) { - /* Short-circuit, we don't want to remove a persistent domain */ - return; - } - -- qemuDomainRemoveInactiveCommon(driver, vm, flags, outgoingMigration); -+ qemuDomainRemoveInactiveCommon(driver, vm, flags, migration); - - virDomainObjListRemove(driver->domains, vm); - } -diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h -index e810f79599..6246988491 100644 ---- a/src/qemu/qemu_domain.h -+++ b/src/qemu/qemu_domain.h -@@ -689,7 +689,7 @@ int qemuDomainMomentDiscardAll(void *payload, - void qemuDomainRemoveInactive(virQEMUDriver *driver, - virDomainObj *vm, - virDomainUndefineFlagsValues flags, -- bool outgoingMigration); -+ bool migration); - - void - qemuDomainRemoveInactiveLocked(virQEMUDriver *driver, -diff --git a/src/qemu/qemu_extdevice.c b/src/qemu/qemu_extdevice.c -index 2384bab7a6..7451e0fa03 100644 ---- a/src/qemu/qemu_extdevice.c -+++ b/src/qemu/qemu_extdevice.c -@@ -154,7 +154,7 @@ void - qemuExtDevicesCleanupHost(virQEMUDriver *driver, - virDomainDef *def, - virDomainUndefineFlagsValues flags, -- bool outgoingMigration) -+ bool migration) - { - size_t i; - -@@ -165,7 +165,7 @@ qemuExtDevicesCleanupHost(virQEMUDriver *driver, - virDomainTPMDef *tpm = def->tpms[i]; - - if (tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) -- qemuExtTPMCleanupHost(driver, tpm, flags, outgoingMigration); -+ qemuExtTPMCleanupHost(driver, tpm, flags, migration); - } - } - -@@ -266,7 +266,7 @@ qemuExtDevicesStart(virQEMUDriver *driver, - void - qemuExtDevicesStop(virQEMUDriver *driver, - virDomainObj *vm, -- bool outgoingMigration) -+ bool migration) - { - virDomainDef *def = vm->def; - size_t i; -@@ -283,7 +283,7 @@ qemuExtDevicesStop(virQEMUDriver *driver, - - for (i = 0; i < def->ntpms; i++) { - if (def->tpms[i]->type == VIR_DOMAIN_TPM_TYPE_EMULATOR) -- qemuExtTPMStop(driver, vm, outgoingMigration); -+ qemuExtTPMStop(driver, vm, migration); - } - - for (i = 0; i < def->nnets; i++) { -diff --git a/src/qemu/qemu_extdevice.h b/src/qemu/qemu_extdevice.h -index d4ac9f395c..36f7fb77a8 100644 ---- a/src/qemu/qemu_extdevice.h -+++ b/src/qemu/qemu_extdevice.h -@@ -48,7 +48,7 @@ int qemuExtDevicesPrepareHost(virQEMUDriver *driver, - void qemuExtDevicesCleanupHost(virQEMUDriver *driver, - virDomainDef *def, - virDomainUndefineFlagsValues flags, -- bool outgoingMigration) -+ bool migration) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); - - int qemuExtDevicesStart(virQEMUDriver *driver, -@@ -59,7 +59,7 @@ int qemuExtDevicesStart(virQEMUDriver *driver, - - void qemuExtDevicesStop(virQEMUDriver *driver, - virDomainObj *vm, -- bool outgoingMigration) -+ bool migration) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); - - bool qemuExtDevicesHasDevice(virDomainDef *def); -diff --git a/src/qemu/qemu_tpm.c b/src/qemu/qemu_tpm.c -index f5e0184e54..f910a26286 100644 ---- a/src/qemu/qemu_tpm.c -+++ b/src/qemu/qemu_tpm.c -@@ -907,7 +907,8 @@ qemuTPMEmulatorInitPaths(virDomainTPMDef *tpm, - * @driver: QEMU driver - * @tpm: TPM definition - * @flags: flags indicating whether to keep or remove TPM persistent state -- * @outgoingMigration: whether cleanup is due to an outgoing migration -+ * @migration: whether cleanup is due to a successful outgoing or failed -+ * incoming migration - * - * Clean up persistent storage for the swtpm. - */ -@@ -915,14 +916,12 @@ static void - qemuTPMEmulatorCleanupHost(virQEMUDriver *driver, - virDomainTPMDef *tpm, - virDomainUndefineFlagsValues flags, -- bool outgoingMigration) -+ bool migration) - { - g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); - -- /* Never remove the state in case of outgoing migration with shared -- * storage. -- */ -- if (outgoingMigration && -+ /* Never remove the state in case of migration with shared storage. */ -+ if (migration && - virFileIsSharedFS(tpm->data.emulator.source_path, cfg->sharedFilesystems) == 1) - return; - -@@ -1293,9 +1292,9 @@ void - qemuExtTPMCleanupHost(virQEMUDriver *driver, - virDomainTPMDef *tpm, - virDomainUndefineFlagsValues flags, -- bool outgoingMigration) -+ bool migration) - { -- qemuTPMEmulatorCleanupHost(driver, tpm, flags, outgoingMigration); -+ qemuTPMEmulatorCleanupHost(driver, tpm, flags, migration); - } - - -@@ -1319,7 +1318,7 @@ qemuExtTPMStart(virQEMUDriver *driver, - void - qemuExtTPMStop(virQEMUDriver *driver, - virDomainObj *vm, -- bool outgoingMigration) -+ bool migration) - { - g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); - g_autofree char *shortName = virDomainDefGetShortName(vm->def); -@@ -1329,7 +1328,7 @@ qemuExtTPMStop(virQEMUDriver *driver, - return; - - qemuTPMEmulatorStop(cfg->swtpmStateDir, shortName); -- if (outgoingMigration && qemuTPMHasSharedStorage(driver, vm->def)) -+ if (migration && qemuTPMHasSharedStorage(driver, vm->def)) - restoreTPMStateLabel = false; - - if (qemuSecurityRestoreTPMLabels(driver, vm, restoreTPMStateLabel, false) < 0) -diff --git a/src/qemu/qemu_tpm.h b/src/qemu/qemu_tpm.h -index 7096060a2a..37813087cf 100644 ---- a/src/qemu/qemu_tpm.h -+++ b/src/qemu/qemu_tpm.h -@@ -38,7 +38,7 @@ int qemuExtTPMPrepareHost(virQEMUDriver *driver, - void qemuExtTPMCleanupHost(virQEMUDriver *driver, - virDomainTPMDef *tpm, - virDomainUndefineFlagsValues flags, -- bool outgoingMigration) -+ bool migration) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); - - int qemuExtTPMStart(virQEMUDriver *driver, -@@ -52,7 +52,7 @@ int qemuExtTPMStart(virQEMUDriver *driver, - - void qemuExtTPMStop(virQEMUDriver *driver, - virDomainObj *vm, -- bool outgoingMigration) -+ bool migration) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); - - int qemuExtTPMSetupCgroup(virQEMUDriver *driver, --- -2.49.0 diff --git a/SPECS/libvirt/libvirt-qemu-tpm-do-not-update-profile-name-for-transient-domains.patch b/SPECS/libvirt/libvirt-qemu-tpm-do-not-update-profile-name-for-transient-domains.patch deleted file mode 100644 index d483c22c04f..00000000000 --- a/SPECS/libvirt/libvirt-qemu-tpm-do-not-update-profile-name-for-transient-domains.patch +++ /dev/null @@ -1,73 +0,0 @@ -From c184ba489a432d5748c3de3ff5719ccd8194c1e5 Mon Sep 17 00:00:00 2001 -Message-ID: -From: =?UTF-8?q?J=C3=A1n=20Tomko?= -Date: Tue, 3 Dec 2024 12:00:08 +0100 -Subject: [PATCH] qemu: tpm: do not update profile name for transient domains -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -If we do not have a persistent definition, there's no point in -looking for it since we cannot store it. - -Also skip the update if the tpm device(s) in the persistent -definition are different. - -This fixes the crash when starting a transient domain. - -https://issues.redhat.com/browse/RHEL-69774 -https://gitlab.com/libvirt/libvirt/-/issues/715 - -Fixes: d79542eec669eb9c449bb8228179e7a87e768017 -Signed-off-by: Ján Tomko -Reviewed-by: Jiri Denemark -Reviewed-by: Stefan Berger -(cherry picked from commit 81da7a2c2a2d490cddaaa77d3e3b36e210b38bd7) - -https://issues.redhat.com/browse/RHEL-71072 - -Signed-off-by: Ján Tomko ---- - src/qemu/qemu_extdevice.c | 13 ++++++++++++- - src/qemu/qemu_tpm.c | 2 +- - 2 files changed, 13 insertions(+), 2 deletions(-) - -diff --git a/src/qemu/qemu_extdevice.c b/src/qemu/qemu_extdevice.c -index a6f31f9773..954cb323a4 100644 ---- a/src/qemu/qemu_extdevice.c -+++ b/src/qemu/qemu_extdevice.c -@@ -190,7 +190,18 @@ qemuExtDevicesStart(virQEMUDriver *driver, - - for (i = 0; i < def->ntpms; i++) { - virDomainTPMDef *tpm = def->tpms[i]; -- virDomainTPMDef *persistentTPMDef = persistentDef->tpms[i]; -+ virDomainTPMDef *persistentTPMDef = NULL; -+ -+ if (persistentDef) { -+ /* do not try to update the profile in the persistent definition -+ * if the device does not match */ -+ if (persistentDef->ntpms == def->ntpms) -+ persistentTPMDef = persistentDef->tpms[i]; -+ if (persistentTPMDef && -+ (persistentTPMDef->type != tpm->type || -+ persistentTPMDef->model != tpm->model)) -+ persistentTPMDef = NULL; -+ } - - if (tpm->type == VIR_DOMAIN_TPM_TYPE_EMULATOR && - qemuExtTPMStart(driver, vm, tpm, persistentTPMDef, -diff --git a/src/qemu/qemu_tpm.c b/src/qemu/qemu_tpm.c -index f223dcb9ae..f5e0184e54 100644 ---- a/src/qemu/qemu_tpm.c -+++ b/src/qemu/qemu_tpm.c -@@ -773,7 +773,7 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDef *tpm, - incomingMigration) < 0) - goto error; - -- if (run_setup && !incomingMigration && -+ if (run_setup && !incomingMigration && persistentTPMDef && - qemuTPMEmulatorUpdateProfileName(&tpm->data.emulator, persistentTPMDef, - cfg, saveDef) < 0) - goto error; --- -2.47.1 diff --git a/SPECS/libvirt/libvirt.signatures.json b/SPECS/libvirt/libvirt.signatures.json index b1d26ea20dc..898b772da93 100644 --- a/SPECS/libvirt/libvirt.signatures.json +++ b/SPECS/libvirt/libvirt.signatures.json @@ -1,5 +1,5 @@ { "Signatures": { - "libvirt-10.10.0.tar.xz": "e1bd7bd31b7c0d0ae073dec050bb5b0232b3e4adebdc58ea82fe8b366c765796" + "libvirt-11.9.0.tar.xz": "104f70ee591e72989d4f8c6caa79ed9dacd5dc84efdb0125b848afe544ad0c2d" } } diff --git a/SPECS/libvirt/libvirt.spec b/SPECS/libvirt/libvirt.spec index b702c68e755..1a6beb1edcb 100644 --- a/SPECS/libvirt/libvirt.spec +++ b/SPECS/libvirt/libvirt.spec @@ -11,12 +11,14 @@ %define arches_zfs %{arches_x86} %{power64} %{arm} %define arches_numactl %{arches_x86} %{power64} aarch64 s390x %define arches_numad %{arches_x86} %{power64} aarch64 +%define arches_ch x86_64 aarch64 # The hypervisor drivers that run in libvirtd %define with_qemu 0%{!?_without_qemu:1} %define with_lxc 0%{!?_without_lxc:1} %define with_libxl 0%{!?_without_libxl:1} %define with_vbox 0%{!?_without_vbox:1} +%define with_ch 0 %ifarch %{arches_qemu_kvm} %define with_qemu_kvm %{with_qemu} @@ -56,6 +58,7 @@ # Other optional features %define with_numactl 0%{!?_without_numactl:1} +%define with_userfaultfd_sysctl 1 # A few optional bits off by default, we enable later %define with_fuse 0 @@ -95,6 +98,7 @@ %define with_libxl 0 %define with_hyperv 0 %define with_lxc 0 +%define with_ch 0 %define with_netcf 0 @@ -141,6 +145,9 @@ %define with_modular_daemons 0 +# Preserve the iptables-first behavior used by previous Azure Linux releases. +%define firewall_backend_priority iptables,nftables + # Force QEMU to run as non-root %define qemu_user qemu %define qemu_group qemu @@ -184,8 +191,8 @@ Summary: Library providing a simple virtualization API Name: libvirt -Version: 10.10.0 -Release: 2%{?dist} +Version: 11.9.0 +Release: 1%{?dist} License: GPL-2.0-or-later AND LGPL-2.1-only AND LGPL-2.1-or-later AND OFL-1.1 Vendor: Microsoft Corporation Distribution: Azure Linux @@ -197,10 +204,6 @@ URL: https://libvirt.org/ Source: https://download.libvirt.org/%{?mainturl}libvirt-%{version}.tar.xz Patch0: libvirt-conf.patch Patch1: CVE-2025-13193.patch -Patch2: CVE-2025-12748.patch -Patch3: libvirt-qemu-tpm-do-not-update-profile-name-for-transient-domains.patch -Patch4: libvirt-qemu-Rename-outgoingMigration-parameter-in-various-TPM-functions.patch -Patch5: libvirt-qemu-Properly-propagate-migration-state-to-TPM-cleanup-code.patch Requires: libvirt-daemon = %{version}-%{release} Requires: libvirt-daemon-config-network = %{version}-%{release} @@ -253,7 +256,7 @@ BuildRequires: gcc %if %{with_libxl} BuildRequires: xen-devel %endif -BuildRequires: glib2-devel >= 2.56 +BuildRequires: glib2-devel >= 2.66 BuildRequires: libxml2-devel BuildRequires: readline-devel BuildRequires: bash-completion >= 2.0 @@ -275,12 +278,7 @@ BuildRequires: libnl3-devel BuildRequires: libselinux-devel BuildRequires: iptables BuildRequires: ebtables -# For modprobe -BuildRequires: kmod BuildRequires: cyrus-sasl-devel -BuildRequires: polkit >= 0.112 -# For mount/umount in FS driver -BuildRequires: util-linux %if %{with_qemu} # For managing ACLs BuildRequires: libacl-devel @@ -291,10 +289,6 @@ BuildRequires: qemu-img %if %{with_nbdkit} BuildRequires: libnbd-devel %endif -# For LVM drivers -BuildRequires: lvm2 -# For pool type=iscsi -BuildRequires: iscsi-initiator-utils %if %{with_storage_iscsi_direct} # For pool type=iscsi-direct BuildRequires: libiscsi-devel @@ -334,13 +328,8 @@ BuildRequires: libwsman-devel >= 2.6.3 BuildRequires: audit-libs-devel # we need /usr/sbin/dtrace BuildRequires: systemtap-sdt-devel -# For mount/umount in FS driver -BuildRequires: util-linux # For showmount in FS driver (netfs discovery) BuildRequires: nfs-utils - %if %{with_numad} -BuildRequires: numad - %endif %if %{with_wireshark} # was disabled before ... stay disabled? BuildRequires: wireshark-devel @@ -381,6 +370,8 @@ Requires: libvirt-daemon-lock = %{version}-%{release} Requires: libvirt-daemon-plugin-lockd = %{version}-%{release} Requires: libvirt-daemon-log = %{version}-%{release} Requires: libvirt-daemon-proxy = %{version}-%{release} +# For modprobe and rmmod +Requires: kmod %description daemon Server side daemon required to manage the virtualization capabilities @@ -433,6 +424,7 @@ resources %package daemon-plugin-lockd Summary: lockd client plugin for virtlockd Requires: libvirt-libs = %{version}-%{release} +Requires: libvirt-daemon-common = %{version}-%{release} Requires: libvirt-daemon-lock = %{version}-%{release} %description daemon-plugin-lockd @@ -553,6 +545,9 @@ Requires: qemu-img Obsoletes: libvirt-daemon-driver-storage-rbd < 5.2.0 %endif Obsoletes: libvirt-daemon-driver-storage-sheepdog < 8.8.0 + %if !%{with_storage_zfs} +Obsoletes: libvirt-daemon-driver-storage-zfs < 11.4.0 + %endif %description daemon-driver-storage-core The storage driver plugin for the libvirtd daemon, providing @@ -1015,9 +1010,15 @@ Libvirt plugin for NSS for translating domain names into IP addresses. %endif %if %{with_esx} - %define arg_esx -Ddriver_esx=enabled -Dcurl=enabled + %define arg_esx -Ddriver_esx=enabled +%else + %define arg_esx -Ddriver_esx=disabled +%endif + +%if %{with_esx} || %{with_ch} + %define arg_curl -Dcurl=enabled %else - %define arg_esx -Ddriver_esx=disabled -Dcurl=disabled + %define arg_curl -Dcurl=disabled %endif %if %{with_hyperv} @@ -1032,6 +1033,12 @@ Libvirt plugin for NSS for translating domain names into IP addresses. %define arg_vmware -Ddriver_vmware=disabled %endif +%if %{with_ch} + %define arg_ch -Ddriver_ch=enabled +%else + %define arg_ch -Ddriver_ch=disabled +%endif + %if %{with_storage_rbd} %define arg_storage_rbd -Dstorage_rbd=enabled %else @@ -1128,6 +1135,12 @@ Libvirt plugin for NSS for translating domain names into IP addresses. %define arg_remote_mode -Dremote_default_mode=legacy %endif +%if %{with_userfaultfd_sysctl} + %define arg_userfaultfd_sysctl -Duserfaultfd_sysctl=enabled +%else + %define arg_userfaultfd_sysctl -Duserfaultfd_sysctl=disabled +%endif + %define when %(date +"%%F-%%T") %define where %(hostname) %define who %{?packager}%{!?packager:Unknown} @@ -1143,6 +1156,8 @@ export SOURCE_DATE_EPOCH=$(stat --printf='%Y' %{_specdir}/libvirt.spec) %meson \ -Drunstatedir=%{_rundir} \ -Dinitconfdir=%{_sysconfdir}/sysconfig \ + -Dunitdir=%{_unitdir} \ + -Dsysusersdir=%{_sysusersdir} \ %{?arg_qemu} \ %{?arg_openvz} \ %{?arg_lxc} \ @@ -1154,11 +1169,12 @@ export SOURCE_DATE_EPOCH=$(stat --printf='%Y' %{_specdir}/libvirt.spec) -Ddriver_remote=enabled \ -Ddriver_test=enabled \ %{?arg_esx} \ + %{?arg_curl} \ %{?arg_hyperv} \ %{?arg_vmware} \ + %{?arg_ch} \ -Ddriver_vz=disabled \ -Ddriver_bhyve=disabled \ - -Ddriver_ch=disabled \ %{?arg_remote_mode} \ -Ddriver_interface=enabled \ -Ddriver_network=enabled \ @@ -1206,9 +1222,13 @@ export SOURCE_DATE_EPOCH=$(stat --printf='%Y' %{_specdir}/libvirt.spec) -Dqemu_moddir=%{qemu_moddir} \ -Dqemu_datadir=%{qemu_datadir} \ -Dtls_priority=%{tls_priority} \ + -Dsysctl_config=enabled \ + %{?arg_userfaultfd_sysctl} \ + -Dssh_proxy=enabled \ %{?enable_werror} \ -Dexpensive_tests=enabled \ -Dinit_script=systemd \ + -Dfirewall_backend_priority=%{firewall_backend_priority} \ -Ddocs=enabled \ -Dtests=enabled \ -Drpath=disabled \ @@ -1272,6 +1292,10 @@ rm -rf $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d/libvirtd.libxl rm -f $RPM_BUILD_ROOT%{_datadir}/augeas/lenses/libvirtd_libxl.aug rm -f $RPM_BUILD_ROOT%{_datadir}/augeas/lenses/tests/test_libvirtd_libxl.aug %endif + %if ! %{with_ch} +rm -f $RPM_BUILD_ROOT%{_datadir}/augeas/lenses/libvirtd_ch.aug +rm -f $RPM_BUILD_ROOT%{_datadir}/augeas/lenses/tests/test_libvirtd_ch.aug + %endif # Copied into libvirt-docs subpackage eventually mv $RPM_BUILD_ROOT%{_datadir}/doc/libvirt libvirt-docs @@ -1727,7 +1751,9 @@ exit 0 %config(noreplace) %{_sysconfdir}/libvirt/libvirtd.conf %config(noreplace) %{_prefix}/lib/sysctl.d/60-libvirtd.conf %config(noreplace) %{_sysconfdir}/logrotate.d/libvirtd +%dir %{_datadir}/augeas/lenses %{_datadir}/augeas/lenses/libvirtd.aug +%dir %{_datadir}/augeas/lenses/tests %{_datadir}/augeas/lenses/tests/test_libvirtd.aug %attr(0755, root, root) %{_sbindir}/libvirtd %{_mandir}/man8/libvirtd.8* @@ -1748,9 +1774,11 @@ exit 0 %dir %attr(0755, root, root) %{_libdir}/libvirt/connection-driver/ %dir %attr(0755, root, root) %{_libdir}/libvirt/storage-backend/ %dir %attr(0755, root, root) %{_libdir}/libvirt/storage-file/ +%dir %attr(0755, root, root) %{_libdir}/libvirt/lock-driver/ %{_datadir}/polkit-1/actions/org.libvirt.unix.policy %{_datadir}/polkit-1/actions/org.libvirt.api.policy %{_datadir}/polkit-1/rules.d/50-libvirt.rules +%{_sysusersdir}/libvirt.conf %dir %attr(0700, root, root) %{_localstatedir}/log/libvirt/ %attr(0755, root, root) %{_libexecdir}/libvirt_iohelper %attr(0755, root, root) %{_bindir}/virt-ssh-helper @@ -1781,7 +1809,6 @@ exit 0 %{_mandir}/man8/virtlockd.8* %files daemon-plugin-lockd -%dir %attr(0755, root, root) %{_libdir}/libvirt/lock-driver/ %attr(0755, root, root) %{_libdir}/libvirt/lock-driver/lockd.so %files daemon-log @@ -1920,7 +1947,6 @@ exit 0 %ghost %dir %{_rundir}/libvirt/storage/ %{_libdir}/libvirt/connection-driver/libvirt_driver_storage.so %{_libdir}/libvirt/storage-backend/libvirt_storage_backend_fs.so -%{_libdir}/libvirt/storage-file/libvirt_storage_file_fs.so %{_mandir}/man8/virtstoraged.8* %files daemon-driver-storage-disk @@ -1962,10 +1988,12 @@ exit 0 %if %{with_qemu} %files daemon-driver-qemu %config(noreplace) %{_sysconfdir}/libvirt/virtqemud.conf + %if %{with_userfaultfd_sysctl} %config(noreplace) %{_prefix}/lib/sysctl.d/60-qemu-postcopy-migration.conf + %endif %{_datadir}/augeas/lenses/virtqemud.aug %{_datadir}/augeas/lenses/tests/test_virtqemud.aug -%{_prefix}/lib/sysusers.d/libvirt-qemu.conf +%{_sysusersdir}/libvirt-qemu.conf %{_unitdir}/virtqemud.service %{_unitdir}/virtqemud.socket %{_unitdir}/virtqemud-ro.socket @@ -1977,11 +2005,11 @@ exit 0 %config(noreplace) %{_sysconfdir}/libvirt/qemu.conf %config(noreplace) %{_sysconfdir}/libvirt/qemu-lockd.conf %config(noreplace) %{_sysconfdir}/logrotate.d/libvirtd.qemu -%ghost %dir %{_rundir}/libvirt/qemu/ -%ghost %dir %{_rundir}/libvirt/qemu/dbus/ -%ghost %dir %{_rundir}/libvirt/qemu/passt/ -%ghost %dir %{_rundir}/libvirt/qemu/slirp/ -%ghost %dir %{_rundir}/libvirt/qemu/swtpm/ +%ghost %dir %attr(0755, %{qemu_user}, %{qemu_group}) %{_rundir}/libvirt/qemu/ +%ghost %dir %attr(0770, %{qemu_user}, %{qemu_group}) %{_rundir}/libvirt/qemu/dbus/ +%ghost %dir %attr(0755, %{qemu_user}, %{qemu_group}) %{_rundir}/libvirt/qemu/passt/ +%ghost %dir %attr(0755, %{qemu_user}, %{qemu_group}) %{_rundir}/libvirt/qemu/slirp/ +%ghost %dir %attr(0770, %{qemu_user}, %{qemu_group}) %{_rundir}/libvirt/qemu/swtpm/ %dir %attr(0751, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/ %dir %attr(0751, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/checkpoint/ %dir %attr(0751, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/dump/ @@ -2197,6 +2225,10 @@ exit 0 %endif %changelog +* Wed Aug 05 2026 GitHub Copilot - 11.9.0-1 +- Upgrade to 11.9.0. +- Remove patches fixed or superseded upstream. + * Tue Mar 24 2026 Harshit Gupta - 10.10.0-2 - Add patches from https://gitlab.com/redhat/centos-stream/rpms/libvirt to fix TPM handling in QEMU migrations. @@ -2216,12 +2248,12 @@ exit 0 * Fri Nov 21 2025 Azure Linux Security Servicing Account - 10.0.0-6 - Patch for CVE-2025-13193 -* Thu May 15 2025 Aninda Pradhan - 10.0.0-5 -- Fixes CVE-2024-4418 with an upstream patch - * Fri May 23 2025 Aninda Pradhan - 10.0.0-4 - Fix for CVE-2024-1441 and CVE-2024-2494 +* Thu May 15 2025 Aninda Pradhan - 10.0.0-5 +- Fixes CVE-2024-4418 with an upstream patch + * Thu May 30 2024 Sharath Srikanth Chellappa - 10.0.0-3 - Add patch to libvirt.conf to work with kubevirt. diff --git a/SPECS/qemu/0002-Disable-failing-tests-on-azl.patch b/SPECS/qemu/0002-Disable-failing-tests-on-azl.patch index b6dedfa6e72..a2cb35b1b04 100644 --- a/SPECS/qemu/0002-Disable-failing-tests-on-azl.patch +++ b/SPECS/qemu/0002-Disable-failing-tests-on-azl.patch @@ -3,73 +3,82 @@ From: Kanika Nema Date: Thu, 4 Apr 2024 14:33:33 +0000 Subject: [PATCH] Disable tests that fail during azl rpmbuild check -1. Disable post-copy eventfd based tests as they hang -2. Disable TLS-PSK test as they fail (curve is unsupported error, -possibly because psktool doesn't work on azl). +1. Disable post-copy eventfd based tests as they hang. +2. Disable TLS-PSK tests because the required curve is unsupported in Azure + Linux builds. Signed-off-by: Kanika Nema --- - tests/qtest/migration-test.c | 28 +++++++++++++++++++++++++++- - 1 file changed, 27 insertions(+), 1 deletion(-) + tests/qtest/migration/framework.c | 2 ++ + tests/qtest/migration/tls-tests.c | 12 ++++++++++++ + 2 files changed, 14 insertions(+) ---- a/b/tests/qtest/migration-test.c 2026-02-06 23:49:13.929537847 +0000 -+++ b/tests/qtest/migration-test.c 2026-02-06 23:49:36.409520951 +0000 -@@ -3808,6 +3808,8 @@ - } +diff --git a/tests/qtest/migration/framework.c b/tests/qtest/migration/framework.c +index 4d43e65..b8d50c0 100644 +--- a/tests/qtest/migration/framework.c ++++ b/tests/qtest/migration/framework.c +@@ -1028,6 +1028,8 @@ MigrationTestEnv *migration_get_env(void) - has_uffd = ufd_version_check(); + env->has_dirty_ring = kvm_dirty_ring_supported(); + env->has_uffd = ufd_version_check(&env->uffd_feature_thread_id); + /* Unblock azl qemu tests, eventfd may not be working properly */ -+ has_uffd = 0; - arch = qtest_get_arch(); - is_x86 = !strcmp(arch, "i386") || !strcmp(arch, "x86_64"); ++ env->has_uffd = false; + env->arch = qtest_get_arch(); + env->is_x86 = !strcmp(env->arch, "i386") || !strcmp(env->arch, "x86_64"); -@@ -3896,8 +3898,14 @@ - #endif +diff --git a/tests/qtest/migration/tls-tests.c b/tests/qtest/migration/tls-tests.c +index 136a0a8..2d5af2e 100644 +--- a/tests/qtest/migration/tls-tests.c ++++ b/tests/qtest/migration/tls-tests.c +@@ -785,8 +785,14 @@ static void test_multifd_tcp_tls_x509_reject_anon_client(void) - #ifdef CONFIG_GNUTLS + static void migration_test_add_tls_smoke(MigrationTestEnv *env) + { +/* -+ * TLSPSK doesn't work in azl builds and fails with this error: ++ * TLS PSK tests fail on azl builds with this error: + * "qemu-system-x86_64: TLS handshake failed: The curve is unsupported" + */ ++#if 0 + migration_test_add("/migration/precopy/tcp/tls/psk/match", + test_precopy_tcp_tls_psk_match); ++#endif + } + + void migration_test_add_tls(MigrationTestEnv *env) +@@ -799,8 +805,10 @@ void migration_test_add_tls(MigrationTestEnv *env) + return; + } + +#if 0 migration_test_add("/migration/precopy/unix/tls/psk", test_precopy_unix_tls_psk); +#endif - if (has_uffd) { + if (env->has_uffd) { /* -@@ -3928,10 +3936,16 @@ - test_precopy_tcp_switchover_ack); - - #ifdef CONFIG_GNUTLS -+/* -+ * TLS PSK tests fail on azl rpmbuilds with error: -+ * "qemu-system-x86_64: TLS handshake failed: The curve is unsupported" -+ */ +@@ -829,8 +837,10 @@ void migration_test_add_tls(MigrationTestEnv *env) + test_precopy_unix_tls_x509_override_host); + #endif /* CONFIG_TASN1 */ + +#if 0 - migration_test_add("/migration/precopy/tcp/tls/psk/match", - test_precopy_tcp_tls_psk_match); migration_test_add("/migration/precopy/tcp/tls/psk/mismatch", test_precopy_tcp_tls_psk_mismatch); +#endif #ifdef CONFIG_TASN1 migration_test_add("/migration/precopy/tcp/tls/x509/default-host", test_precopy_tcp_tls_x509_default_host); -@@ -4005,10 +4019,15 @@ - test_multifd_tcp_uadk); - #endif - #ifdef CONFIG_GNUTLS -+/* -+ * TLS PSK tests fail on azl rpmbuilds -+ */ +@@ -848,10 +858,12 @@ void migration_test_add_tls(MigrationTestEnv *env) + test_precopy_tcp_tls_x509_reject_anon_client); + #endif /* CONFIG_TASN1 */ + +#if 0 migration_test_add("/migration/multifd/tcp/tls/psk/match", test_multifd_tcp_tls_psk_match); migration_test_add("/migration/multifd/tcp/tls/psk/mismatch", test_multifd_tcp_tls_psk_mismatch); +#endif - #ifdef CONFIG_TASN1 - migration_test_add("/migration/multifd/tcp/tls/x509/default-host", - test_multifd_tcp_tls_x509_default_host); + if (env->has_uffd) { + migration_test_add("/migration/multifd+postcopy/tcp/tls/psk/match", + test_multifd_postcopy_tcp_tls_psk_match); -- 2.25.1 diff --git a/SPECS/qemu/CVE-2026-3842.patch b/SPECS/qemu/CVE-2026-3842.patch index 5f098e6b04c..d3749a70fdd 100644 --- a/SPECS/qemu/CVE-2026-3842.patch +++ b/SPECS/qemu/CVE-2026-3842.patch @@ -14,10 +14,11 @@ diff --git a/hw/hyperv/syndbg.c b/hw/hyperv/syndbg.c index 065e12fb1..9fdec1146 100644 --- a/hw/hyperv/syndbg.c +++ b/hw/hyperv/syndbg.c -@@ -189,7 +189,7 @@ static uint16_t handle_recv_msg(HvSynDbg *syndbg, uint64_t outgpa, +@@ -192,8 +192,8 @@ static uint16_t handle_recv_msg(HvSynDbg *syndbg, uint64_t outgpa, { uint16_t ret; - uint8_t data_buf[TARGET_PAGE_SIZE - UDP_PKT_HEADER_SIZE]; + g_assert(MSG_BUFSZ >= qemu_target_page_size()); + QEMU_UNINITIALIZED uint8_t data_buf[MSG_BUFSZ]; - hwaddr out_len; + hwaddr out_len, out_requested_len; void *out_data; diff --git a/SPECS/qemu/README.tests b/SPECS/qemu/README.tests index 9932773c9e6..693ba523521 100644 --- a/SPECS/qemu/README.tests +++ b/SPECS/qemu/README.tests @@ -1,39 +1,28 @@ -qemu-kvm-tests README -===================== +qemu-tests README +================= -The qemu-kvm-tests rpm contains tests that can be used to verify the -functionality of the installed qemu-kvm package +The qemu-tests RPM contains qemu-iotests that can be used to verify the +functionality of the installed QEMU package. When installed, the files from this rpm will be arranged in the following -directory structure +directory structure: tests-src/ ├── README +├── python +│ └── qemu ├── scripts -│   ├── qemu.py -│   └── qmp +│ └── qmp └── tests - ├── acceptance ├── Makefile.include └── qemu-iotests -The tests/ directory within the tests-src/ directory is setup to remain a copy -of a subset of the tests/ directory from the QEMU source tree +The tests directory contains a subset of the QEMU source test tree. The Python +QEMU modules and QMP scripts are included because qemu-iotests uses them. -The avocado_qemu tests and qemu-iotests, along with files required for the -execution of the avocado_qemu tests (scripts/qemu.py and scripts/qmp/) will be -installed in a new location - /usr/lib64/qemu-kvm/tests-src/ +QEMU 10 replaced the old avocado_qemu test tree with the functional test +framework. Functional tests are not installed by this RPM. -avocado_qemu tests: -The avocado_qemu tests can be executed by running the following avocado command: -avocado run -p qemu_bin=/usr/libexec/qemu-kvm /usr/lib64/qemu-kvm/tests/acceptance/ -Avocado needs to be installed separately using either pip or from source as -Avocado is not being packaged for RHEL-8. - -qemu-iotests: -symlinks to corresponding binaries need to be created for QEMU_PROG, -QEMU_IO_PROG, QEMU_IMG_PROG, and QEMU_NBD_PROG before the iotests can be -executed. - -The primary purpose of this package is to make these tests available to be -executed as gating tests for the virt module in the RHEL-8 OSCI environment. +Before running qemu-iotests, set QEMU_PROG, QEMU_IO_PROG, QEMU_IMG_PROG, and +QEMU_NBD_PROG to the corresponding installed QEMU binaries, or create the +symlinks expected by the test suite. diff --git a/SPECS/qemu/UPGRADE-10.1.0.md b/SPECS/qemu/UPGRADE-10.1.0.md new file mode 100644 index 00000000000..fb5e1d2953a --- /dev/null +++ b/SPECS/qemu/UPGRADE-10.1.0.md @@ -0,0 +1,465 @@ +# QEMU 10.1.0 Upgrade Rationale + +This document explains the changes made while upgrading the Azure Linux 3.0 +QEMU package from 9.1.0 to 10.1.0. It records why each structural, macro, +configure, package, and patch-stack change was made so that a future upgrade +does not need to rediscover the same decisions. + +## Reference hierarchy + +The upgrade used three references, with different authority: + +1. The existing Azure Linux 3.0 `qemu.spec` remained authoritative for Azure + Linux product policy, dependency availability, package identity, and local + features. +2. The Azure Linux 4.0 QEMU 10.1.4 spec was the primary reference for upstream + QEMU 10 package topology, removed targets, new modules, configure options, + and 32-bit host handling. +3. The CentOS Stream 9 `qemu-kvm` 10.1.0-22 spec was used to understand + downstream fixes and patch history. Its RHEL-specific package identity, + Epoch, machine types, compiler policy, and single-target package model were + not copied. + +This ordering matters. Azure Linux 4.0 is close enough to show how QEMU 10 is +packaged in Azure Linux, but Azure Linux 3.0 does not have every dependency or +the same release policy. The result therefore ports QEMU 10 structure without +turning the Azure Linux 3.0 package into either the Azure Linux 4.0 package or +the CentOS package. + +## Version and source metadata + +### Version and release + +`Version` changed from `9.1.0` to `10.1.0`, and `Release` restarted at +`1%{?dist}`. Restarting the release is standard when the upstream version +changes. The package remains named `qemu`, and no `Epoch` was imported from +CentOS or Azure Linux 4.0 because Azure Linux 3.0 did not previously need one. +Adding an Epoch without a version-ordering requirement would permanently +change RPM comparison semantics. + +### Source signature and component governance manifest + +`qemu.signatures.json` now names `qemu-10.1.0.tar.xz` and records SHA-256: + +```text +e0517349b50ca73ebec2fa85b06050d5c463ca65c738833bd8fc1f15f180be51 +``` + +`cgmanifest.json` now identifies QEMU 10.1.0 and its matching download URL. +These changes keep source verification and component governance metadata in +sync with `Source0`; updating only the spec would leave the build or compliance +metadata referring to QEMU 9.1.0. + +## Azure Linux policy retained + +The following controls were intentionally kept because they express Azure +Linux 3.0 policy rather than an upstream-version detail: + +- `Name: qemu`, `Vendor: Microsoft Corporation`, and + `Distribution: Azure Linux`. +- `%bcond_without check`, including the existing test-package behavior. +- `%global azl_no_ui 1`, which keeps the Azure Linux build headless. +- `%global __strip /bin/true`, preserving the existing debug-information and + packaging workflow. +- Existing Azure firmware locations and `%global ipxe_version 1.21.1`. +- `have_opengl`, `have_ui`, `have_spice`, `have_dbus_display`, and `have_jack` + remain disabled for Azure Linux. +- `have_liburing` and NFS block support remain enabled, while RBD and Gluster + block support remain disabled according to repository dependency policy. +- Static user-mode emulators remain enabled. +- `vhostuser-backend(fs)` remains the virtiofs provider relationship. + +These settings were not replaced by their CentOS or Azure Linux 4.0 +counterparts because doing so would change product behavior beyond the QEMU +version upgrade. + +## Macro changes + +### Added `have_64bit` + +```spec +%global have_64bit 1 +%ifarch %{ix86} +%global have_64bit 0 +%endif +``` + +QEMU 10 no longer builds 64-bit emulators on a 32-bit x86 host. The macro was +added from the Azure Linux 4.0 QEMU spec so one condition controls every part +of the RPM model affected by that upstream change: + +- metapackage `Requires`; +- dynamic user-mode emulator binaries and SystemTap files; +- static user-mode subpackages, binaries, SystemTap files, and binfmt rules; +- system emulator packages, binaries, firmware, man pages, and SystemTap + files; and +- cleanup of generated 64-bit binfmt and firmware files during `%install`. + +The guarded targets include AArch64, Alpha, HPPA, LoongArch64, S390x, and the +64-bit members of the MIPS, PPC, RISC-V, SPARC, and x86 target families. +Matching `Obsoletes` were added on hosts without 64-bit target support so an +upgrade can remove packages that QEMU 10 can no longer produce. Guarding only +the binaries would be insufficient: RPM would still create dangling +dependencies or `%files` entries for missing outputs. + +The existing `system-x86` subpackage remains scoped to `x86_64`. This differs +slightly from the Azure Linux 4.0 layout but preserves the Azure Linux 3.0 +subpackage declaration policy. + +### Added `requires_device_uefi_vars` + +QEMU 10 builds `hw-uefi-vars.so` as a separate loadable module. The new macro: + +```spec +%define requires_device_uefi_vars Requires: %{name}-device-uefi-vars = %{evr} +``` + +was added to `requires_all_modules`, and the matching +`qemu-device-uefi-vars` subpackage owns the module. This follows the Azure +Linux 4.0 QEMU 10 layout and preserves the existing convention that system +emulator metapackages depend on all loadable device modules they may need. + +### Neutralized generic audio dependency macros + +The generic audio dependency macros for ALSA, OSS, PulseAudio, PipeWire, SDL, +JACK, and D-Bus now expand to `%{nil}`. The old `pa_drv`, `sdl_drv`, and +`jack_drv` list-fragment macros were removed because the final audio driver +list is deliberately empty. + +The macro names were retained rather than deleting every reference from +`requires_all_modules`. This keeps the module dependency composition uniform +and makes the disabled policy explicit. It also avoids introducing a second +Azure-specific version of the module aggregation macro. + +This matches the headless audio policy seen in the Azure Linux 4.0 QEMU spec. +The conditional SPICE audio module remains governed by `have_spice`; it is not +part of the removed generic host-audio backend set. + +### Added CRIS obsoletes + +QEMU 10 removed CRIS system and user emulation. The package no longer declares +CRIS dependencies, subpackages, scriptlets, file lists, binaries, tapsets, or +binfmt rules. Obsoletes were added for: + +- `qemu-system-cris`; +- `qemu-system-cris-core`; and +- `qemu-user-static-cris`. + +The obsoletes are necessary because simply deleting the package declarations +would leave old CRIS RPMs installed after an upgrade. This removal and upgrade +handling are also present in the Azure Linux 4.0 QEMU spec. + +## Configure changes + +### Updated `disable_everything` + +`disable_everything` is the baseline used before selected features are enabled +for each build. Keeping it complete prevents Meson `auto` detection from +silently changing the package when the buildroot gains a new dependency. + +The following QEMU 10 options were added to the disabled baseline: + +- `--disable-asan` +- `--disable-debug-remap` +- `--disable-igvm` +- `--disable-libcbor` +- `--disable-passt` +- `--disable-pvg` +- `--disable-qpl` +- `--disable-rust` +- `--disable-strict-rust-lints` +- `--disable-uadk` +- `--disable-ubsan` +- `--disable-valgrind` + +These switches exist in the QEMU 10 configuration surface but are not selected +for Azure Linux 3.0. In particular, the repository does not provide all of the +dependencies needed for IGVM, libcbor, passt, QPL, UADK, and the newer Rust +path. Explicit disables make the build reproducible and match the conservative +feature baseline used by the Azure Linux 4.0 spec where applicable. + +The following obsolete aggregate or CPU-feature switches were removed: + +- `--disable-avx2` +- `--disable-avx512bw` +- `--disable-sanitizers` + +QEMU 10 no longer exposes these old configure switches in this form. Sanitizer +selection is represented by individual ASAN, UBSAN, and related options, while +the old AVX configure toggles are no longer accepted. Leaving obsolete options +would make configure fail instead of disabling a feature. + +### Disabled host audio and SDL explicitly + +The main build now passes: + +```text +--disable-alsa +--disable-jack +--disable-oss +--disable-pa +--disable-pipewire +--audio-drv-list= +--disable-sdl +--disable-sdl-image +``` + +The prior spec enabled some of these backends and then packaged a module for +each one. Azure Linux builds QEMU as a headless virtualization component, and +the Azure Linux 4.0 QEMU spec no longer carries these generic audio packages. +Explicitly disabling both the feature and the driver list prevents module files +from being generated accidentally and keeps the configure result aligned with +the RPM package graph. + +### Removed obsolete enables + +`--enable-avx2` and `--enable-avx512bw` were removed for the same reason as +their disabled counterparts: QEMU 10 no longer accepts those configure +switches. + +`--enable-virtfs-proxy-helper` was removed because QEMU 10 no longer exposes a +separate configure option for that helper. QEMU removed the 9p proxy backend +and `virtfs-proxy-helper` in 9.2 because the backend was slow, unmaintained, and +required a root helper without delivering the intended security benefit. +`--enable-virtfs` remains, so supported local 9p functionality is still enabled +without passing an invalid legacy switch. + +## Package and file-layout changes + +### Removed generic audio subpackages + +The following package declarations and `%files` sections were removed: + +- `qemu-audio-alsa` +- `qemu-audio-dbus` +- `qemu-audio-oss` +- `qemu-audio-pa` +- `qemu-audio-pipewire` +- `qemu-audio-sdl` +- `qemu-audio-jack` + +This is the package-side counterpart to disabling the backends at configure +time. Retaining empty package declarations would create packages with no +payload, while retaining file lists would fail when the disabled modules are +not built. + +### Added `qemu-device-uefi-vars` + +The new package owns: + +```text +%{_libdir}/qemu/hw-uefi-vars.so +``` + +Splitting the module follows the existing one-module-per-subpackage pattern and +the Azure Linux 4.0 QEMU 10 spec. Placing it in `qemu-common` instead would make +the common package architecture-specific and would bypass the module +dependency macros. + +### Removed CRIS package surfaces + +All CRIS system and static-user declarations, scriptlets, and file entries were +removed because no corresponding QEMU 10 output exists. This includes the CRIS +emulator binaries, SystemTap probes, man page, and static binfmt integration. + +### Guarded 64-bit package surfaces + +Every 64-bit file list is guarded by `have_64bit`, including 64-bit members +inside mixed target packages such as `qemu-user-static-mips` and +`qemu-system-riscv`. The `%install` cleanup removes 64-bit binfmt files that +`qemu-binfmt-conf.sh` can generate independently of the selected target list, +plus firmware files owned only by guarded packages. This avoids both unpackaged +files and references to files not built on i686. + +### Removed stale Avocado test packaging + +QEMU 10 removed the `tests/avocado` source and build directories when its +acceptance tests moved to the newer `tests/functional` framework. The old +`%install` code attempted to copy `qemu_kvm_build/tests/avocado/*`, which made +the RPM build fail because that path no longer exists. + +The Avocado directory creation and copy were removed, matching the Azure Linux +4.0 QEMU 10 spec. The tests subpackage continues to stage qemu-iotests and the +Python/QMP helpers they use. Functional tests were not added to the RPM payload +as part of this fix because the Azure Linux 4.0 package runs selected functional +tests during `%check` but does not install the functional test source tree. + +### Removed `virtfs-proxy-helper` file entries + +The `%files common` list no longer claims +`%{_libexecdir}/virtfs-proxy-helper` or its man page. QEMU removed both the +proxy backend and helper in 9.2, so QEMU 10.1 cannot install these files. The +Azure Linux 4.0 QEMU 10 spec likewise has no helper or man-page entry. + +This is the package-side counterpart to removing +`--enable-virtfs-proxy-helper`. Keeping the stale `%files` entries allowed +compilation and installation to finish but caused RPM file processing to fail +with `File not found`. Supported 9p local backends and the separate virtiofs +path are unaffected. + +### Removed loadable TCG accelerator entries + +The QEMU 9 spec claimed `accel-tcg-i386.so` and `accel-tcg-x86_64.so` in the +`qemu-system-x86-core` package and removed those files on non-x86 builds. QEMU +10.1 no longer installs per-target TCG accelerator modules; TCG support is +linked into the corresponding `qemu-system-*` binaries. The only accelerator +module produced by this build is `accel-qtest-*.so`, which remains owned by the +tests package. + +Both stale `%files` entries and their obsolete `%install` cleanup commands were +removed, matching the Azure Linux 4.0 QEMU 10 spec. Keeping the `%files` entries +caused RPM processing to fail after the x86 emulator binaries had been built +successfully. + +### Reconciled QEMU 10 firmware paths + +The firmware `%files` entries and target cleanup were compared with the actual +QEMU 10.1 Meson install log and the Azure Linux 4.0 QEMU spec. This identified +several related layout changes: + +- Petalogix, Bamboo, and Canyonlands device trees moved under + `%{_datadir}/qemu/dtb/`. +- `ast27x0_bootrom.bin` and `npcm8xx_bootrom.bin` are new ARM firmware payloads + and are owned by `qemu-system-arm` alongside `npcm7xx_bootrom.bin`. +- `pnv-pnor.bin` is a POWER firmware payload. It is owned by `qemu-system-ppc` + when PPC support is enabled and removed during `%install` when PPC support is + disabled. +- `s390-netboot.img` is no longer installed by QEMU 10.1, so its stale + `qemu-system-s390x` file entry was removed. `s390-ccw.img` remains packaged. + +Updating both ownership and cleanup is necessary. For example, changing only +the PPC `%files` paths would still leave moved DTBs and `pnv-pnor.bin` as +unpackaged files in the default Azure Linux build, where PPC support is +disabled. + +## Patch-stack decisions + +Patch compatibility was checked against the exact pristine +`qemu-10.1.0.tar.xz` source. A patch was removed only after one of these stronger +conditions was established: + +- reverse application showed the exact change was already upstream; or +- QEMU 10.1 contained the complete behavior or a generalized replacement, not + merely similar-looking code. + +Failure to apply by itself was not treated as proof that a patch was obsolete. + +### Patches removed because the exact fixes are upstream + +| Patch | Reason for removal | +| --- | --- | +| `kvm-migration-Ensure-vmstate_save-sets-errp.patch` | The `vmstate_save()` error propagation fix is already in pristine QEMU 10.1. | +| `kvm-net-Fix-announce_self.patch` | The `announce_self` networking fix is already in pristine QEMU 10.1. | +| `kvm-block-Allow-inactivating-already-inactive-nodes.patch` | QEMU 10.1 already makes repeated node inactivation safe. | +| `kvm-block-Don-t-attach-inactive-child-to-active-node.patch` | The active-parent/inactive-child protection is already upstream. | +| `kvm-block-Fix-crash-on-block_resize-on-inactive-node.patch` | The inactive-node resize crash fix is already upstream. | +| `kvm-nbd-server-Support-inactive-nodes.patch` | NBD export handling for inactive nodes is already upstream. | +| `kvm-migration-Fix-UAF-for-incoming-migration-on-Migratio.patch` | The incoming migration use-after-free fix is already upstream. | + +Keeping any of these patches would duplicate upstream code and increase the +chance of conflicts or accidentally reverting a later upstream refinement. + +### Late block activation series removed as integrated upstream + +The following downstream series introduced late block activation and inactive +block-node management. QEMU 10.1 already contains the complete resulting +surface, including `migration_get_target_runstate()`, +`migration/block-active.c`, `bdrv_activate()`/`bdrv_inactivate()`, the +`blockdev-set-active` QMP command, inactive-node creation, active-state +reporting, and the `allow-inactive` block export option. + +| Patch | QEMU 10.1 behavior that supersedes it | +| --- | --- | +| `kvm-migration-Add-helper-to-get-target-runstate.patch` | `migration_get_target_runstate()` is present and used by incoming migration. | +| `kvm-qmp-cont-Only-activate-disks-if-migration-completed.patch` | Disk activation is coordinated through the upstream migration block-active state. | +| `kvm-migration-block-Make-late-block-active-the-default.patch` | Late activation is part of the upstream incoming migration flow. | +| `kvm-migration-block-Apply-late-block-active-behavior-to-.patch` | The behavior covered by the series is integrated into the upstream migration paths. | +| `kvm-migration-block-Fix-possible-race-with-block_inactiv.patch` | Upstream block-active handling contains the serialized activation/inactivation flow. | +| `kvm-migration-block-Rewrite-disk-activation.patch` | QEMU 10.1 has the rewritten activation implementation in `migration/block-active.c`. | +| `kvm-block-Add-active-field-to-BlockDeviceInfo.patch` | QEMU 10.1 exposes block-node active state through its block QAPI. | +| `kvm-block-Inactivate-external-snapshot-overlays-when-nec.patch` | External overlay inactivation is included in the upstream block graph handling. | +| `kvm-migration-block-active-Remove-global-active-flag.patch` | The upstream implementation uses per-node activation rather than the old global flag. | +| `kvm-block-Add-option-to-create-inactive-nodes.patch` | QEMU 10.1 supports creating inactive block nodes. | +| `kvm-block-Add-blockdev-set-active-QMP-command.patch` | `blockdev-set-active` is defined in QEMU 10.1 QAPI. | +| `kvm-block-Support-inactive-nodes-in-blk_insert_bs.patch` | Upstream block insertion supports the inactive-node model. | +| `kvm-block-export-Don-t-ignore-image-activation-error-in-.patch` | The upstream export path calls `bdrv_activate()` and propagates errors. | +| `kvm-block-export-Add-option-to-allow-export-of-inactive-.patch` | The `allow-inactive` export option is present in QEMU 10.1 QAPI and implementation. | + +Removing this series as a unit is important. Its patches depend on each other; +retaining only fragments would mix old downstream interfaces with the final +upstream design. + +### Virtio queue-loading patch removed as superseded + +`kvm-virtio-net-Add-queues-before-loading-them.patch` added a +`pre_load_queues` callback so virtio-net queues existed before migration state +was loaded. QEMU 10.1 contains a generalized version: + +- the callback receives the migrated queue count as `uint32_t n`; +- `virtio_load()` invokes it after validating the count and before loading + queue state; and +- virtio-net resizes its queues through that callback. + +The old patch was therefore removed instead of rebased. Reapplying it would +replace the newer callback contract with an older, less capable version. + +### Patches retained because they still apply and remain needed + +- `0001-pc-bios-optionrom-Fix-pvh.img-ld-build-failure-on-fe.patch` still + applies and preserves the existing linker compatibility fix. +- `CVE-2021-20255.patch`, `CVE-2025-11234.patch`, `CVE-2025-12464.patch`, + `CVE-2024-8354.patch`, `CVE-2025-14876.patch`, `CVE-2026-3195.patch`, + `CVE-2026-48914.patch`, and `CVE-2026-3196.patch` still apply to QEMU 10.1 + and continue to provide Azure Linux security servicing fixes. +- `kvm-block-Drain-nodes-before-inactivating-them.patch` still applies and is + not present in pristine QEMU 10.1, so it remains in the stack. + +### Azure migration-test patch rebased + +`0002-Disable-failing-tests-on-azl.patch` previously modified the monolithic +`tests/qtest/migration-test.c`. QEMU 10 split those tests into the migration +test framework, so the patch now targets: + +- `tests/qtest/migration/framework.c`, where it forces `env->has_uffd` false to + skip userfaultfd/postcopy paths that hang in the Azure Linux RPM build + environment; and +- `tests/qtest/migration/tls-tests.c`, where it disables only TLS-PSK test + registrations that fail with `The curve is unsupported`. + +TLS X.509 registrations were deliberately left enabled. The purpose of the +patch is to preserve known Azure Linux exclusions, not to disable all TLS +coverage. + +### CVE-2026-3842 patch rebased + +The Hyper-V synthetic debugger fix still applies logically, but QEMU 10.1 +changed the receive buffer from a page-sized array to `MSG_BUFSZ` and added an +assertion. The patch context was updated for that layout while retaining the +security behavior: + +- remember the requested mapping length; +- reject a null or short `cpu_physical_memory_map()` result; +- copy only the mapped length; and +- unmap only when a mapping was returned. + +This is a context rebase, not a change to the intended CVE fix. + +## Validation performed + +The upgrade was checked with the following focused validations: + +- `rpmspec --define 'azl 1' --target x86_64 --parse`; +- `rpmspec --define 'azl 1' --target i686 --parse`, including checks that + guarded 64-bit Requires and file lists are absent; +- a clean `rpmbuild --nodeps -bp` against QEMU 10.1.0, which applies the entire + remaining patch stack successfully; +- direct `git apply --check` of both rebased patches against pristine QEMU + 10.1.0; +- SHA-256 verification of the source archive; +- JSON parsing of `qemu.signatures.json` and `cgmanifest.json`; and +- `git diff --check`. + +A full binary RPM build was not part of this rebase validation. The next +highest-value check is a repository-native QEMU build to reconcile generated +file lists and exercise the QEMU test suite with the Azure Linux buildroot +dependencies. diff --git a/SPECS/qemu/kvm-block-Add-active-field-to-BlockDeviceInfo.patch b/SPECS/qemu/kvm-block-Add-active-field-to-BlockDeviceInfo.patch deleted file mode 100644 index 42ce35bbce7..00000000000 --- a/SPECS/qemu/kvm-block-Add-active-field-to-BlockDeviceInfo.patch +++ /dev/null @@ -1,317 +0,0 @@ -From 454a498569318365a16ed65bd2110daef5bb3fc3 Mon Sep 17 00:00:00 2001 -From: Kevin Wolf -Date: Tue, 4 Feb 2025 22:13:52 +0100 -Subject: [PATCH 08/23] block: Add 'active' field to BlockDeviceInfo - -RH-Author: Kevin Wolf -RH-MergeRequest: 339: QMP command for block device reactivation after migration -RH-Jira: RHEL-54296 RHEL-78397 -RH-Acked-by: Eric Blake -RH-Acked-by: Stefan Hajnoczi -RH-Commit: [7/22] 6309d1a9ac2a7a21013cfe71dc40474cbdc89464 (kmwolf/centos-qemu-kvm) - -This allows querying from QMP (and also HMP) whether an image is -currently active or inactive (in the sense of BDRV_O_INACTIVE). - -Signed-off-by: Kevin Wolf -Acked-by: Fabiano Rosas -Reviewed-by: Eric Blake -Reviewed-by: Stefan Hajnoczi -Message-ID: <20250204211407.381505-2-kwolf@redhat.com> -Signed-off-by: Kevin Wolf -(cherry picked from commit aec81049c2daa8a97b89e59f03733b21ae0f8c2d) -Signed-off-by: Kevin Wolf ---- - block.c | 4 ++++ - block/monitor/block-hmp-cmds.c | 5 +++-- - block/qapi.c | 1 + - include/block/block-global-state.h | 3 +++ - qapi/block-core.json | 6 +++++- - tests/qemu-iotests/184.out | 2 ++ - tests/qemu-iotests/191.out | 16 ++++++++++++++++ - tests/qemu-iotests/273.out | 5 +++++ - 8 files changed, 39 insertions(+), 3 deletions(-) - -diff --git a/block.c b/block.c -index c317de9eaa..c94d78eefd 100644 ---- a/block.c -+++ b/block.c -@@ -6824,6 +6824,10 @@ void bdrv_init_with_whitelist(void) - bdrv_init(); - } - -+bool bdrv_is_inactive(BlockDriverState *bs) { -+ return bs->open_flags & BDRV_O_INACTIVE; -+} -+ - int bdrv_activate(BlockDriverState *bs, Error **errp) - { - BdrvChild *child, *parent; -diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c -index bdf2eb50b6..cc832549e1 100644 ---- a/block/monitor/block-hmp-cmds.c -+++ b/block/monitor/block-hmp-cmds.c -@@ -630,11 +630,12 @@ static void print_block_info(Monitor *mon, BlockInfo *info, - } - - if (inserted) { -- monitor_printf(mon, ": %s (%s%s%s)\n", -+ monitor_printf(mon, ": %s (%s%s%s%s)\n", - inserted->file, - inserted->drv, - inserted->ro ? ", read-only" : "", -- inserted->encrypted ? ", encrypted" : ""); -+ inserted->encrypted ? ", encrypted" : "", -+ inserted->active ? "" : ", inactive"); - } else { - monitor_printf(mon, ": [not inserted]\n"); - } -diff --git a/block/qapi.c b/block/qapi.c -index 2b5793f1d9..709170e63d 100644 ---- a/block/qapi.c -+++ b/block/qapi.c -@@ -63,6 +63,7 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk, - info->file = g_strdup(bs->filename); - info->ro = bdrv_is_read_only(bs); - info->drv = g_strdup(bs->drv->format_name); -+ info->active = !bdrv_is_inactive(bs); - info->encrypted = bs->encrypted; - - info->cache = g_new(BlockdevCacheInfo, 1); -diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h -index bd7cecd1cf..a826bf5f78 100644 ---- a/include/block/block-global-state.h -+++ b/include/block/block-global-state.h -@@ -175,6 +175,9 @@ BlockDriverState * GRAPH_RDLOCK - check_to_replace_node(BlockDriverState *parent_bs, const char *node_name, - Error **errp); - -+ -+bool GRAPH_RDLOCK bdrv_is_inactive(BlockDriverState *bs); -+ - int no_coroutine_fn GRAPH_RDLOCK - bdrv_activate(BlockDriverState *bs, Error **errp); - -diff --git a/qapi/block-core.json b/qapi/block-core.json -index aa40d44f1d..92af032744 100644 ---- a/qapi/block-core.json -+++ b/qapi/block-core.json -@@ -486,6 +486,10 @@ - # @backing_file_depth: number of files in the backing file chain - # (since: 1.2) - # -+# @active: true if the backend is active; typical cases for inactive backends -+# are on the migration source instance after migration completes and on the -+# destination before it completes. (since: 10.0) -+# - # @encrypted: true if the backing device is encrypted - # - # @detect_zeroes: detect and optimize zero writes (Since 2.1) -@@ -556,7 +560,7 @@ - { 'struct': 'BlockDeviceInfo', - 'data': { 'file': 'str', '*node-name': 'str', 'ro': 'bool', 'drv': 'str', - '*backing_file': 'str', 'backing_file_depth': 'int', -- 'encrypted': 'bool', -+ 'active': 'bool', 'encrypted': 'bool', - 'detect_zeroes': 'BlockdevDetectZeroesOptions', - 'bps': 'int', 'bps_rd': 'int', 'bps_wr': 'int', - 'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int', -diff --git a/tests/qemu-iotests/184.out b/tests/qemu-iotests/184.out -index e8f631f853..52692b6b3b 100644 ---- a/tests/qemu-iotests/184.out -+++ b/tests/qemu-iotests/184.out -@@ -26,6 +26,7 @@ Testing: - { - "iops_rd": 0, - "detect_zeroes": "off", -+ "active": true, - "image": { - "backing-image": { - "virtual-size": 1073741824, -@@ -59,6 +60,7 @@ Testing: - { - "iops_rd": 0, - "detect_zeroes": "off", -+ "active": true, - "image": { - "virtual-size": 1073741824, - "filename": "null-co://", -diff --git a/tests/qemu-iotests/191.out b/tests/qemu-iotests/191.out -index c3309e4bc6..2a72ca7106 100644 ---- a/tests/qemu-iotests/191.out -+++ b/tests/qemu-iotests/191.out -@@ -114,6 +114,7 @@ wrote 65536/65536 bytes at offset 1048576 - { - "iops_rd": 0, - "detect_zeroes": "off", -+ "active": true, - "image": { - "backing-image": { - "virtual-size": 67108864, -@@ -155,6 +156,7 @@ wrote 65536/65536 bytes at offset 1048576 - { - "iops_rd": 0, - "detect_zeroes": "off", -+ "active": true, - "image": { - "virtual-size": 197120, - "filename": "TEST_DIR/t.IMGFMT.ovl2", -@@ -183,6 +185,7 @@ wrote 65536/65536 bytes at offset 1048576 - { - "iops_rd": 0, - "detect_zeroes": "off", -+ "active": true, - "image": { - "backing-image": { - "virtual-size": 67108864, -@@ -224,6 +227,7 @@ wrote 65536/65536 bytes at offset 1048576 - { - "iops_rd": 0, - "detect_zeroes": "off", -+ "active": true, - "image": { - "virtual-size": 197120, - "filename": "TEST_DIR/t.IMGFMT", -@@ -252,6 +256,7 @@ wrote 65536/65536 bytes at offset 1048576 - { - "iops_rd": 0, - "detect_zeroes": "off", -+ "active": true, - "image": { - "backing-image": { - "virtual-size": 67108864, -@@ -293,6 +298,7 @@ wrote 65536/65536 bytes at offset 1048576 - { - "iops_rd": 0, - "detect_zeroes": "off", -+ "active": true, - "image": { - "virtual-size": 393216, - "filename": "TEST_DIR/t.IMGFMT.mid", -@@ -321,6 +327,7 @@ wrote 65536/65536 bytes at offset 1048576 - { - "iops_rd": 0, - "detect_zeroes": "off", -+ "active": true, - "image": { - "virtual-size": 67108864, - "filename": "TEST_DIR/t.IMGFMT.base", -@@ -350,6 +357,7 @@ wrote 65536/65536 bytes at offset 1048576 - { - "iops_rd": 0, - "detect_zeroes": "off", -+ "active": true, - "image": { - "virtual-size": 393216, - "filename": "TEST_DIR/t.IMGFMT.base", -@@ -521,6 +529,7 @@ wrote 65536/65536 bytes at offset 1048576 - { - "iops_rd": 0, - "detect_zeroes": "off", -+ "active": true, - "image": { - "backing-image": { - "virtual-size": 67108864, -@@ -562,6 +571,7 @@ wrote 65536/65536 bytes at offset 1048576 - { - "iops_rd": 0, - "detect_zeroes": "off", -+ "active": true, - "image": { - "virtual-size": 197120, - "filename": "TEST_DIR/t.IMGFMT.ovl2", -@@ -590,6 +600,7 @@ wrote 65536/65536 bytes at offset 1048576 - { - "iops_rd": 0, - "detect_zeroes": "off", -+ "active": true, - "image": { - "backing-image": { - "backing-image": { -@@ -642,6 +653,7 @@ wrote 65536/65536 bytes at offset 1048576 - { - "iops_rd": 0, - "detect_zeroes": "off", -+ "active": true, - "image": { - "virtual-size": 197120, - "filename": "TEST_DIR/t.IMGFMT.ovl3", -@@ -670,6 +682,7 @@ wrote 65536/65536 bytes at offset 1048576 - { - "iops_rd": 0, - "detect_zeroes": "off", -+ "active": true, - "image": { - "virtual-size": 67108864, - "filename": "TEST_DIR/t.IMGFMT.base", -@@ -699,6 +712,7 @@ wrote 65536/65536 bytes at offset 1048576 - { - "iops_rd": 0, - "detect_zeroes": "off", -+ "active": true, - "image": { - "virtual-size": 393216, - "filename": "TEST_DIR/t.IMGFMT.base", -@@ -727,6 +741,7 @@ wrote 65536/65536 bytes at offset 1048576 - { - "iops_rd": 0, - "detect_zeroes": "off", -+ "active": true, - "image": { - "backing-image": { - "virtual-size": 67108864, -@@ -768,6 +783,7 @@ wrote 65536/65536 bytes at offset 1048576 - { - "iops_rd": 0, - "detect_zeroes": "off", -+ "active": true, - "image": { - "virtual-size": 197120, - "filename": "TEST_DIR/t.IMGFMT", -diff --git a/tests/qemu-iotests/273.out b/tests/qemu-iotests/273.out -index 71843f02de..c19753c685 100644 ---- a/tests/qemu-iotests/273.out -+++ b/tests/qemu-iotests/273.out -@@ -23,6 +23,7 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev - { - "iops_rd": 0, - "detect_zeroes": "off", -+ "active": true, - "image": { - "backing-image": { - "backing-image": { -@@ -74,6 +75,7 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev - { - "iops_rd": 0, - "detect_zeroes": "off", -+ "active": true, - "image": { - "virtual-size": 197120, - "filename": "TEST_DIR/t.IMGFMT", -@@ -102,6 +104,7 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev - { - "iops_rd": 0, - "detect_zeroes": "off", -+ "active": true, - "image": { - "backing-image": { - "virtual-size": 197120, -@@ -142,6 +145,7 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev - { - "iops_rd": 0, - "detect_zeroes": "off", -+ "active": true, - "image": { - "virtual-size": 197120, - "filename": "TEST_DIR/t.IMGFMT.mid", -@@ -170,6 +174,7 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev - { - "iops_rd": 0, - "detect_zeroes": "off", -+ "active": true, - "image": { - "virtual-size": 197120, - "filename": "TEST_DIR/t.IMGFMT.base", --- -2.48.1 - diff --git a/SPECS/qemu/kvm-block-Add-blockdev-set-active-QMP-command.patch b/SPECS/qemu/kvm-block-Add-blockdev-set-active-QMP-command.patch deleted file mode 100644 index 1c0b59a00cb..00000000000 --- a/SPECS/qemu/kvm-block-Add-blockdev-set-active-QMP-command.patch +++ /dev/null @@ -1,187 +0,0 @@ -From c6c40cc92fbb91d704d3739bb78bfd936f111625 Mon Sep 17 00:00:00 2001 -From: Kevin Wolf -Date: Tue, 4 Feb 2025 22:13:59 +0100 -Subject: [PATCH 15/23] block: Add blockdev-set-active QMP command - -RH-Author: Kevin Wolf -RH-MergeRequest: 339: QMP command for block device reactivation after migration -RH-Jira: RHEL-54296 RHEL-78397 -RH-Acked-by: Eric Blake -RH-Acked-by: Stefan Hajnoczi -RH-Commit: [14/22] e494fb6df6c363b6266e5fb7d09c31b3e7694f04 (kmwolf/centos-qemu-kvm) - -The system emulator tries to automatically activate and inactivate block -nodes at the right point during migration. However, there are still -cases where it's necessary that the user can do this manually. - -Images are only activated on the destination VM of a migration when the -VM is actually resumed. If the VM was paused, this doesn't happen -automatically. The user may want to perform some operation on a block -device (e.g. taking a snapshot or starting a block job) without also -resuming the VM yet. This is an example where a manual command is -necessary. - -Another example is VM migration when the image files are opened by an -external qemu-storage-daemon instance on each side. In this case, the -process that needs to hand over the images isn't even part of the -migration and can't know when the migration completes. Management tools -need a way to explicitly inactivate images on the source and activate -them on the destination. - -This adds a new blockdev-set-active QMP command that lets the user -change the status of individual nodes (this is necessary in -qemu-storage-daemon because it could be serving multiple VMs and only -one of them migrates at a time). For convenience, operating on all -devices (like QEMU does automatically during migration) is offered as an -option, too, and can be used in the context of single VM. - -Signed-off-by: Kevin Wolf -Acked-by: Fabiano Rosas -Reviewed-by: Eric Blake -Reviewed-by: Stefan Hajnoczi -Message-ID: <20250204211407.381505-9-kwolf@redhat.com> -Signed-off-by: Kevin Wolf -(cherry picked from commit 8cd37207f8a90c5f995283ecf95f1cb5f7518a77) -Signed-off-by: Kevin Wolf ---- - block.c | 21 ++++++++++++++++++++ - blockdev.c | 32 ++++++++++++++++++++++++++++++ - include/block/block-global-state.h | 3 +++ - qapi/block-core.json | 32 ++++++++++++++++++++++++++++++ - 4 files changed, 88 insertions(+) - -diff --git a/block.c b/block.c -index fd2ac177ef..2140a5d3b7 100644 ---- a/block.c -+++ b/block.c -@@ -7052,6 +7052,27 @@ bdrv_inactivate_recurse(BlockDriverState *bs, bool top_level) - return 0; - } - -+int bdrv_inactivate(BlockDriverState *bs, Error **errp) -+{ -+ int ret; -+ -+ GLOBAL_STATE_CODE(); -+ GRAPH_RDLOCK_GUARD_MAINLOOP(); -+ -+ if (bdrv_has_bds_parent(bs, true)) { -+ error_setg(errp, "Node has active parent node"); -+ return -EPERM; -+ } -+ -+ ret = bdrv_inactivate_recurse(bs, true); -+ if (ret < 0) { -+ error_setg_errno(errp, -ret, "Failed to inactivate node"); -+ return ret; -+ } -+ -+ return 0; -+} -+ - int bdrv_inactivate_all(void) - { - BlockDriverState *bs = NULL; -diff --git a/blockdev.c b/blockdev.c -index 81430122df..70046b6690 100644 ---- a/blockdev.c -+++ b/blockdev.c -@@ -3468,6 +3468,38 @@ void qmp_blockdev_del(const char *node_name, Error **errp) - bdrv_unref(bs); - } - -+void qmp_blockdev_set_active(const char *node_name, bool active, Error **errp) -+{ -+ int ret; -+ -+ GLOBAL_STATE_CODE(); -+ GRAPH_RDLOCK_GUARD_MAINLOOP(); -+ -+ if (!node_name) { -+ if (active) { -+ bdrv_activate_all(errp); -+ } else { -+ ret = bdrv_inactivate_all(); -+ if (ret < 0) { -+ error_setg_errno(errp, -ret, "Failed to inactivate all nodes"); -+ } -+ } -+ } else { -+ BlockDriverState *bs = bdrv_find_node(node_name); -+ if (!bs) { -+ error_setg(errp, "Failed to find node with node-name='%s'", -+ node_name); -+ return; -+ } -+ -+ if (active) { -+ bdrv_activate(bs, errp); -+ } else { -+ bdrv_inactivate(bs, errp); -+ } -+ } -+} -+ - static BdrvChild * GRAPH_RDLOCK - bdrv_find_child(BlockDriverState *parent_bs, const char *child_name) - { -diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h -index a826bf5f78..9be34b3c99 100644 ---- a/include/block/block-global-state.h -+++ b/include/block/block-global-state.h -@@ -184,6 +184,9 @@ bdrv_activate(BlockDriverState *bs, Error **errp); - int coroutine_fn no_co_wrapper_bdrv_rdlock - bdrv_co_activate(BlockDriverState *bs, Error **errp); - -+int no_coroutine_fn -+bdrv_inactivate(BlockDriverState *bs, Error **errp); -+ - void bdrv_activate_all(Error **errp); - int bdrv_inactivate_all(void); - -diff --git a/qapi/block-core.json b/qapi/block-core.json -index 6ec603aa6f..c1af3d1f7d 100644 ---- a/qapi/block-core.json -+++ b/qapi/block-core.json -@@ -4930,6 +4930,38 @@ - { 'command': 'blockdev-del', 'data': { 'node-name': 'str' }, - 'allow-preconfig': true } - -+## -+# @blockdev-set-active: -+# -+# Activate or inactivate a block device. Use this to manage the handover of -+# block devices on migration with qemu-storage-daemon. -+# -+# Activating a node automatically activates all of its child nodes first. -+# Inactivating a node automatically inactivates any of its child nodes that are -+# not in use by a still active node. -+# -+# @node-name: Name of the graph node to activate or inactivate. By default, all -+# nodes are affected by the operation. -+# -+# @active: true if the nodes should be active when the command returns success, -+# false if they should be inactive. -+# -+# Since: 10.0 -+# -+# .. qmp-example:: -+# -+# -> { "execute": "blockdev-set-active", -+# "arguments": { -+# "node-name": "node0", -+# "active": false -+# } -+# } -+# <- { "return": {} } -+## -+{ 'command': 'blockdev-set-active', -+ 'data': { '*node-name': 'str', 'active': 'bool' }, -+ 'allow-preconfig': true } -+ - ## - # @BlockdevCreateOptionsFile: - # --- -2.48.1 - diff --git a/SPECS/qemu/kvm-block-Add-option-to-create-inactive-nodes.patch b/SPECS/qemu/kvm-block-Add-option-to-create-inactive-nodes.patch deleted file mode 100644 index 8502b88c418..00000000000 --- a/SPECS/qemu/kvm-block-Add-option-to-create-inactive-nodes.patch +++ /dev/null @@ -1,102 +0,0 @@ -From d44250363b08e627e06a9afe288d02a3d995afc0 Mon Sep 17 00:00:00 2001 -From: Kevin Wolf -Date: Tue, 4 Feb 2025 22:13:58 +0100 -Subject: [PATCH 14/23] block: Add option to create inactive nodes - -RH-Author: Kevin Wolf -RH-MergeRequest: 339: QMP command for block device reactivation after migration -RH-Jira: RHEL-54296 RHEL-78397 -RH-Acked-by: Eric Blake -RH-Acked-by: Stefan Hajnoczi -RH-Commit: [13/22] 45b01b9c09d5f12715e4977cab6140d2cac90714 (kmwolf/centos-qemu-kvm) - -In QEMU, nodes are automatically created inactive while expecting an -incoming migration (i.e. RUN_STATE_INMIGRATE). In qemu-storage-daemon, -the notion of runstates doesn't exist. It also wouldn't necessarily make -sense to introduce it because a single daemon can serve multiple VMs -that can be in different states. - -Therefore, allow the user to explicitly open images as inactive with a -new option. The default is as before: Nodes are usually active, except -when created during RUN_STATE_INMIGRATE. - -Signed-off-by: Kevin Wolf -Acked-by: Fabiano Rosas -Reviewed-by: Eric Blake -Reviewed-by: Stefan Hajnoczi -Message-ID: <20250204211407.381505-8-kwolf@redhat.com> -Signed-off-by: Kevin Wolf -(cherry picked from commit faecd16fe5c65a25b5b55b5edbe4322cec5a9d96) -Signed-off-by: Kevin Wolf ---- - block.c | 9 +++++++++ - include/block/block-common.h | 1 + - qapi/block-core.json | 6 ++++++ - 3 files changed, 16 insertions(+) - -diff --git a/block.c b/block.c -index bedd54deaa..fd2ac177ef 100644 ---- a/block.c -+++ b/block.c -@@ -1573,6 +1573,10 @@ static void update_flags_from_options(int *flags, QemuOpts *opts) - if (qemu_opt_get_bool_del(opts, BDRV_OPT_AUTO_READ_ONLY, false)) { - *flags |= BDRV_O_AUTO_RDONLY; - } -+ -+ if (!qemu_opt_get_bool_del(opts, BDRV_OPT_ACTIVE, true)) { -+ *flags |= BDRV_O_INACTIVE; -+ } - } - - static void update_options_from_flags(QDict *options, int flags) -@@ -1799,6 +1803,11 @@ QemuOptsList bdrv_runtime_opts = { - .type = QEMU_OPT_BOOL, - .help = "Ignore flush requests", - }, -+ { -+ .name = BDRV_OPT_ACTIVE, -+ .type = QEMU_OPT_BOOL, -+ .help = "Node is activated", -+ }, - { - .name = BDRV_OPT_READ_ONLY, - .type = QEMU_OPT_BOOL, -diff --git a/include/block/block-common.h b/include/block/block-common.h -index 338fe5ff7a..7030669f04 100644 ---- a/include/block/block-common.h -+++ b/include/block/block-common.h -@@ -257,6 +257,7 @@ typedef enum { - #define BDRV_OPT_AUTO_READ_ONLY "auto-read-only" - #define BDRV_OPT_DISCARD "discard" - #define BDRV_OPT_FORCE_SHARE "force-share" -+#define BDRV_OPT_ACTIVE "active" - - - #define BDRV_SECTOR_BITS 9 -diff --git a/qapi/block-core.json b/qapi/block-core.json -index 92af032744..6ec603aa6f 100644 ---- a/qapi/block-core.json -+++ b/qapi/block-core.json -@@ -4668,6 +4668,11 @@ - # - # @cache: cache-related options - # -+# @active: whether the block node should be activated (default: true). -+# Having inactive block nodes is useful primarily for migration because it -+# allows opening an image on the destination while the source is still -+# holding locks for it. (Since 10.0) -+# - # @read-only: whether the block device should be read-only (default: - # false). Note that some block drivers support only read-only - # access, either generally or in certain configurations. In this -@@ -4694,6 +4699,7 @@ - '*node-name': 'str', - '*discard': 'BlockdevDiscardOptions', - '*cache': 'BlockdevCacheOptions', -+ '*active': 'bool', - '*read-only': 'bool', - '*auto-read-only': 'bool', - '*force-share': 'bool', --- -2.48.1 - diff --git a/SPECS/qemu/kvm-block-Allow-inactivating-already-inactive-nodes.patch b/SPECS/qemu/kvm-block-Allow-inactivating-already-inactive-nodes.patch deleted file mode 100644 index 7001529a19e..00000000000 --- a/SPECS/qemu/kvm-block-Allow-inactivating-already-inactive-nodes.patch +++ /dev/null @@ -1,80 +0,0 @@ -From f7f73025679c5d001256d87bc47566d1db4e98c7 Mon Sep 17 00:00:00 2001 -From: Kevin Wolf -Date: Tue, 4 Feb 2025 22:13:53 +0100 -Subject: [PATCH 09/23] block: Allow inactivating already inactive nodes - -RH-Author: Kevin Wolf -RH-MergeRequest: 339: QMP command for block device reactivation after migration -RH-Jira: RHEL-54296 RHEL-78397 -RH-Acked-by: Eric Blake -RH-Acked-by: Stefan Hajnoczi -RH-Commit: [8/22] 781a749ae61e038b5b562407b01d53a1bfba598c (kmwolf/centos-qemu-kvm) - -What we wanted to catch with the assertion is cases where the recursion -finds that a child was inactive before its parent. This should never -happen. But if the user tries to inactivate an image that is already -inactive, that's harmless and we don't want to fail the assertion. - -Signed-off-by: Kevin Wolf -Acked-by: Fabiano Rosas -Reviewed-by: Eric Blake -Reviewed-by: Stefan Hajnoczi -Message-ID: <20250204211407.381505-3-kwolf@redhat.com> -Signed-off-by: Kevin Wolf -(cherry picked from commit a6490ec9d56b9e95a13918813585a3a9891710bc) -Signed-off-by: Kevin Wolf ---- - block.c | 16 ++++++++++++---- - 1 file changed, 12 insertions(+), 4 deletions(-) - -diff --git a/block.c b/block.c -index c94d78eefd..a2aa454312 100644 ---- a/block.c -+++ b/block.c -@@ -6959,7 +6959,8 @@ bdrv_has_bds_parent(BlockDriverState *bs, bool only_active) - return false; - } - --static int GRAPH_RDLOCK bdrv_inactivate_recurse(BlockDriverState *bs) -+static int GRAPH_RDLOCK -+bdrv_inactivate_recurse(BlockDriverState *bs, bool top_level) - { - BdrvChild *child, *parent; - int ret; -@@ -6977,7 +6978,14 @@ static int GRAPH_RDLOCK bdrv_inactivate_recurse(BlockDriverState *bs) - return 0; - } - -- assert(!(bs->open_flags & BDRV_O_INACTIVE)); -+ /* -+ * Inactivating an already inactive node on user request is harmless, but if -+ * a child is already inactive before its parent, that's bad. -+ */ -+ if (bs->open_flags & BDRV_O_INACTIVE) { -+ assert(top_level); -+ return 0; -+ } - - /* Inactivate this node */ - if (bs->drv->bdrv_inactivate) { -@@ -7014,7 +7022,7 @@ static int GRAPH_RDLOCK bdrv_inactivate_recurse(BlockDriverState *bs) - - /* Recursively inactivate children */ - QLIST_FOREACH(child, &bs->children, next) { -- ret = bdrv_inactivate_recurse(child->bs); -+ ret = bdrv_inactivate_recurse(child->bs, false); - if (ret < 0) { - return ret; - } -@@ -7039,7 +7047,7 @@ int bdrv_inactivate_all(void) - if (bdrv_has_bds_parent(bs, false)) { - continue; - } -- ret = bdrv_inactivate_recurse(bs); -+ ret = bdrv_inactivate_recurse(bs, true); - if (ret < 0) { - bdrv_next_cleanup(&it); - break; --- -2.48.1 - diff --git a/SPECS/qemu/kvm-block-Don-t-attach-inactive-child-to-active-node.patch b/SPECS/qemu/kvm-block-Don-t-attach-inactive-child-to-active-node.patch deleted file mode 100644 index f2a9219a22d..00000000000 --- a/SPECS/qemu/kvm-block-Don-t-attach-inactive-child-to-active-node.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0f0968badaa11f4ac56f8ee93cbe11f9a6d5fc95 Mon Sep 17 00:00:00 2001 -From: Kevin Wolf -Date: Tue, 4 Feb 2025 22:13:56 +0100 -Subject: [PATCH 12/23] block: Don't attach inactive child to active node - -RH-Author: Kevin Wolf -RH-MergeRequest: 339: QMP command for block device reactivation after migration -RH-Jira: RHEL-54296 RHEL-78397 -RH-Acked-by: Eric Blake -RH-Acked-by: Stefan Hajnoczi -RH-Commit: [11/22] 1ca560728b97bd1d5f7498a7e5d23e2d8bb0808d (kmwolf/centos-qemu-kvm) - -An active node makes unrestricted use of its children and would possibly -run into assertion failures when it operates on an inactive child node. - -Signed-off-by: Kevin Wolf -Acked-by: Fabiano Rosas -Reviewed-by: Eric Blake -Reviewed-by: Stefan Hajnoczi -Message-ID: <20250204211407.381505-6-kwolf@redhat.com> -Signed-off-by: Kevin Wolf -(cherry picked from commit 9b81361aedcc47905de5e91f68221de89c6f5467) -Signed-off-by: Kevin Wolf ---- - block.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/block.c b/block.c -index a2aa454312..41e72e6965 100644 ---- a/block.c -+++ b/block.c -@@ -3183,6 +3183,11 @@ bdrv_attach_child_noperm(BlockDriverState *parent_bs, - child_bs->node_name, child_name, parent_bs->node_name); - return NULL; - } -+ if (bdrv_is_inactive(child_bs) && !bdrv_is_inactive(parent_bs)) { -+ error_setg(errp, "Inactive '%s' can't be a %s child of active '%s'", -+ child_bs->node_name, child_name, parent_bs->node_name); -+ return NULL; -+ } - - bdrv_get_cumulative_perm(parent_bs, &perm, &shared_perm); - bdrv_child_perm(parent_bs, child_bs, NULL, child_role, NULL, --- -2.48.1 - diff --git a/SPECS/qemu/kvm-block-Fix-crash-on-block_resize-on-inactive-node.patch b/SPECS/qemu/kvm-block-Fix-crash-on-block_resize-on-inactive-node.patch deleted file mode 100644 index 63d37e6420c..00000000000 --- a/SPECS/qemu/kvm-block-Fix-crash-on-block_resize-on-inactive-node.patch +++ /dev/null @@ -1,68 +0,0 @@ -From eed2b4b40553cae162407b375f18c935f5025c53 Mon Sep 17 00:00:00 2001 -From: Kevin Wolf -Date: Tue, 4 Feb 2025 22:13:57 +0100 -Subject: [PATCH 13/23] block: Fix crash on block_resize on inactive node - -RH-Author: Kevin Wolf -RH-MergeRequest: 339: QMP command for block device reactivation after migration -RH-Jira: RHEL-54296 RHEL-78397 -RH-Acked-by: Eric Blake -RH-Acked-by: Stefan Hajnoczi -RH-Commit: [12/22] e352c665f68a865859cc62fe1ed6e4044407b8e3 (kmwolf/centos-qemu-kvm) - -In order for block_resize to fail gracefully on an inactive node instead -of crashing with an assertion failure in bdrv_co_write_req_prepare() -(called from bdrv_co_truncate()), we need to check for inactive nodes -also when they are attached as a root node and make sure that -BLK_PERM_RESIZE isn't among the permissions allowed for inactive nodes. -To this effect, don't enumerate the permissions that are incompatible -with inactive nodes any more, but allow only BLK_PERM_CONSISTENT_READ -for them. - -Signed-off-by: Kevin Wolf -Acked-by: Fabiano Rosas -Reviewed-by: Eric Blake -Reviewed-by: Stefan Hajnoczi -Message-ID: <20250204211407.381505-7-kwolf@redhat.com> -Signed-off-by: Kevin Wolf -(cherry picked from commit 8c2c72a33581987af8d8c484d03af3cd69b9e10a) -Signed-off-by: Kevin Wolf ---- - block.c | 7 +++++++ - block/block-backend.c | 2 +- - 2 files changed, 8 insertions(+), 1 deletion(-) - -diff --git a/block.c b/block.c -index 41e72e6965..bedd54deaa 100644 ---- a/block.c -+++ b/block.c -@@ -3077,6 +3077,13 @@ bdrv_attach_child_common(BlockDriverState *child_bs, - assert(child_class->get_parent_desc); - GLOBAL_STATE_CODE(); - -+ if (bdrv_is_inactive(child_bs) && (perm & ~BLK_PERM_CONSISTENT_READ)) { -+ g_autofree char *perm_names = bdrv_perm_names(perm); -+ error_setg(errp, "Permission '%s' unavailable on inactive node", -+ perm_names); -+ return NULL; -+ } -+ - new_child = g_new(BdrvChild, 1); - *new_child = (BdrvChild) { - .bs = NULL, -diff --git a/block/block-backend.c b/block/block-backend.c -index db6f9b92a3..356db1b703 100644 ---- a/block/block-backend.c -+++ b/block/block-backend.c -@@ -253,7 +253,7 @@ static bool blk_can_inactivate(BlockBackend *blk) - * guest. For block job BBs that satisfy this, we can just allow - * it. This is the case for mirror job source, which is required - * by libvirt non-shared block migration. */ -- if (!(blk->perm & (BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED))) { -+ if (!(blk->perm & ~BLK_PERM_CONSISTENT_READ)) { - return true; - } - --- -2.48.1 - diff --git a/SPECS/qemu/kvm-block-Inactivate-external-snapshot-overlays-when-nec.patch b/SPECS/qemu/kvm-block-Inactivate-external-snapshot-overlays-when-nec.patch deleted file mode 100644 index 3c38d0645ac..00000000000 --- a/SPECS/qemu/kvm-block-Inactivate-external-snapshot-overlays-when-nec.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 6f4a7e3489a104137f60e034157cf687e4c3158f Mon Sep 17 00:00:00 2001 -From: Kevin Wolf -Date: Tue, 4 Feb 2025 22:13:54 +0100 -Subject: [PATCH 10/23] block: Inactivate external snapshot overlays when - necessary - -RH-Author: Kevin Wolf -RH-MergeRequest: 339: QMP command for block device reactivation after migration -RH-Jira: RHEL-54296 RHEL-78397 -RH-Acked-by: Eric Blake -RH-Acked-by: Stefan Hajnoczi -RH-Commit: [9/22] 59b39138f0da734d497f3a58d458992abc348978 (kmwolf/centos-qemu-kvm) - -Putting an active block node on top of an inactive one is strictly -speaking an invalid configuration and the next patch will turn it into a -hard error. - -However, taking a snapshot while disk images are inactive after -completing migration has an important use case: After migrating to a -file, taking an external snapshot is what is needed to take a full VM -snapshot. - -In order for this to keep working after the later patches, change -creating a snapshot such that it automatically inactivates an overlay -that is added on top of an already inactive node. - -Signed-off-by: Kevin Wolf -Acked-by: Fabiano Rosas -Reviewed-by: Eric Blake -Reviewed-by: Stefan Hajnoczi -Message-ID: <20250204211407.381505-4-kwolf@redhat.com> -Signed-off-by: Kevin Wolf -(cherry picked from commit e80210ffb24c4e47650344ba77ce3ed354af596c) -Signed-off-by: Kevin Wolf ---- - blockdev.c | 16 ++++++++++++++++ - 1 file changed, 16 insertions(+) - -diff --git a/blockdev.c b/blockdev.c -index 835064ed03..81430122df 100644 ---- a/blockdev.c -+++ b/blockdev.c -@@ -1497,6 +1497,22 @@ static void external_snapshot_action(TransactionAction *action, - return; - } - -+ /* -+ * Older QEMU versions have allowed adding an active parent node to an -+ * inactive child node. This is unsafe in the general case, but there is an -+ * important use case, which is taking a VM snapshot with migration to file -+ * and then adding an external snapshot while the VM is still stopped and -+ * images are inactive. Requiring the user to explicitly create the overlay -+ * as inactive would break compatibility, so just do it automatically here -+ * to keep this working. -+ */ -+ if (bdrv_is_inactive(state->old_bs) && !bdrv_is_inactive(state->new_bs)) { -+ ret = bdrv_inactivate(state->new_bs, errp); -+ if (ret < 0) { -+ return; -+ } -+ } -+ - ret = bdrv_append(state->new_bs, state->old_bs, errp); - if (ret < 0) { - return; --- -2.48.1 - diff --git a/SPECS/qemu/kvm-block-Support-inactive-nodes-in-blk_insert_bs.patch b/SPECS/qemu/kvm-block-Support-inactive-nodes-in-blk_insert_bs.patch deleted file mode 100644 index fbe6fdaa98c..00000000000 --- a/SPECS/qemu/kvm-block-Support-inactive-nodes-in-blk_insert_bs.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 9ab8c39284c0fc2d9d685706b2d788ab02930a08 Mon Sep 17 00:00:00 2001 -From: Kevin Wolf -Date: Tue, 4 Feb 2025 22:14:00 +0100 -Subject: [PATCH 16/23] block: Support inactive nodes in blk_insert_bs() - -RH-Author: Kevin Wolf -RH-MergeRequest: 339: QMP command for block device reactivation after migration -RH-Jira: RHEL-54296 RHEL-78397 -RH-Acked-by: Eric Blake -RH-Acked-by: Stefan Hajnoczi -RH-Commit: [15/22] 17405266afeddc47f73828816d0b8c1ab5ece462 (kmwolf/centos-qemu-kvm) - -Device models have a relatively complex way to set up their block -backends, in which blk_attach_dev() sets blk->disable_perm = true. -We want to support inactive images in exports, too, so that -qemu-storage-daemon can be used with migration. Because they don't use -blk_attach_dev(), they need another way to set this flag. The most -convenient is to do this automatically when an inactive node is attached -to a BlockBackend that can be inactivated. - -Signed-off-by: Kevin Wolf -Acked-by: Fabiano Rosas -Reviewed-by: Eric Blake -Reviewed-by: Stefan Hajnoczi -Message-ID: <20250204211407.381505-10-kwolf@redhat.com> -Signed-off-by: Kevin Wolf -(cherry picked from commit c1c5c7cc4ef6c45ca769c640566fd40d2cb7d5c1) -Signed-off-by: Kevin Wolf ---- - block/block-backend.c | 14 ++++++++++++-- - 1 file changed, 12 insertions(+), 2 deletions(-) - -diff --git a/block/block-backend.c b/block/block-backend.c -index 356db1b703..4a5a1c1f6a 100644 ---- a/block/block-backend.c -+++ b/block/block-backend.c -@@ -909,14 +909,24 @@ void blk_remove_bs(BlockBackend *blk) - int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp) - { - ThrottleGroupMember *tgm = &blk->public.throttle_group_member; -+ uint64_t perm, shared_perm; - - GLOBAL_STATE_CODE(); - bdrv_ref(bs); - bdrv_graph_wrlock(); -+ -+ if ((bs->open_flags & BDRV_O_INACTIVE) && blk_can_inactivate(blk)) { -+ blk->disable_perm = true; -+ perm = 0; -+ shared_perm = BLK_PERM_ALL; -+ } else { -+ perm = blk->perm; -+ shared_perm = blk->shared_perm; -+ } -+ - blk->root = bdrv_root_attach_child(bs, "root", &child_root, - BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, -- blk->perm, blk->shared_perm, -- blk, errp); -+ perm, shared_perm, blk, errp); - bdrv_graph_wrunlock(); - if (blk->root == NULL) { - return -EPERM; --- -2.48.1 - diff --git a/SPECS/qemu/kvm-block-export-Add-option-to-allow-export-of-inactive-.patch b/SPECS/qemu/kvm-block-export-Add-option-to-allow-export-of-inactive-.patch deleted file mode 100644 index e3db67a80b7..00000000000 --- a/SPECS/qemu/kvm-block-export-Add-option-to-allow-export-of-inactive-.patch +++ /dev/null @@ -1,135 +0,0 @@ -From 22de4ba6cec94a38cd56156d9114f06dc4d2a5a5 Mon Sep 17 00:00:00 2001 -From: Kevin Wolf -Date: Tue, 4 Feb 2025 22:14:03 +0100 -Subject: [PATCH 19/23] block/export: Add option to allow export of inactive - nodes - -RH-Author: Kevin Wolf -RH-MergeRequest: 339: QMP command for block device reactivation after migration -RH-Jira: RHEL-54296 RHEL-78397 -RH-Acked-by: Eric Blake -RH-Acked-by: Stefan Hajnoczi -RH-Commit: [18/22] 985eadb03f27d046b89ffeef1fb36ef2e4579552 (kmwolf/centos-qemu-kvm) - -Add an option in BlockExportOptions to allow creating an export on an -inactive node without activating the node. This mode needs to be -explicitly supported by the export type (so that it doesn't perform any -operations that are forbidden for inactive nodes), so this patch alone -doesn't allow this option to be successfully used yet. - -Signed-off-by: Kevin Wolf -Acked-by: Fabiano Rosas -Reviewed-by: Eric Blake -Reviewed-by: Stefan Hajnoczi -Message-ID: <20250204211407.381505-13-kwolf@redhat.com> -Signed-off-by: Kevin Wolf -(cherry picked from commit 1600ef01ab1296ca8230daa6bc41ba983751f646) -Signed-off-by: Kevin Wolf ---- - block/export/export.c | 31 +++++++++++++++++++++---------- - include/block/export.h | 3 +++ - qapi/block-export.json | 10 +++++++++- - 3 files changed, 33 insertions(+), 11 deletions(-) - -diff --git a/block/export/export.c b/block/export/export.c -index 23a86efcdb..71af65b3e5 100644 ---- a/block/export/export.c -+++ b/block/export/export.c -@@ -75,6 +75,7 @@ static const BlockExportDriver *blk_exp_find_driver(BlockExportType type) - BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp) - { - bool fixed_iothread = export->has_fixed_iothread && export->fixed_iothread; -+ bool allow_inactive = export->has_allow_inactive && export->allow_inactive; - const BlockExportDriver *drv; - BlockExport *exp = NULL; - BlockDriverState *bs; -@@ -138,17 +139,24 @@ BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp) - } - } - -- /* -- * Block exports are used for non-shared storage migration. Make sure -- * that BDRV_O_INACTIVE is cleared and the image is ready for write -- * access since the export could be available before migration handover. -- * ctx was acquired in the caller. -- */ - bdrv_graph_rdlock_main_loop(); -- ret = bdrv_activate(bs, errp); -- if (ret < 0) { -- bdrv_graph_rdunlock_main_loop(); -- goto fail; -+ if (allow_inactive) { -+ if (!drv->supports_inactive) { -+ error_setg(errp, "Export type does not support inactive exports"); -+ bdrv_graph_rdunlock_main_loop(); -+ goto fail; -+ } -+ } else { -+ /* -+ * Block exports are used for non-shared storage migration. Make sure -+ * that BDRV_O_INACTIVE is cleared and the image is ready for write -+ * access since the export could be available before migration handover. -+ */ -+ ret = bdrv_activate(bs, errp); -+ if (ret < 0) { -+ bdrv_graph_rdunlock_main_loop(); -+ goto fail; -+ } - } - bdrv_graph_rdunlock_main_loop(); - -@@ -162,6 +170,9 @@ BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp) - if (!fixed_iothread) { - blk_set_allow_aio_context_change(blk, true); - } -+ if (allow_inactive) { -+ blk_set_force_allow_inactivate(blk); -+ } - - ret = blk_insert_bs(blk, bs, errp); - if (ret < 0) { -diff --git a/include/block/export.h b/include/block/export.h -index f2fe0f8078..4bd9531d4d 100644 ---- a/include/block/export.h -+++ b/include/block/export.h -@@ -29,6 +29,9 @@ typedef struct BlockExportDriver { - */ - size_t instance_size; - -+ /* True if the export type supports running on an inactive node */ -+ bool supports_inactive; -+ - /* Creates and starts a new block export */ - int (*create)(BlockExport *, BlockExportOptions *, Error **); - -diff --git a/qapi/block-export.json b/qapi/block-export.json -index ce33fe378d..117b05d13c 100644 ---- a/qapi/block-export.json -+++ b/qapi/block-export.json -@@ -372,6 +372,13 @@ - # cannot be moved to the iothread. The default is false. - # (since: 5.2) - # -+# @allow-inactive: If true, the export allows the exported node to be inactive. -+# If it is created for an inactive block node, the node remains inactive. If -+# the export type doesn't support running on an inactive node, an error is -+# returned. If false, inactive block nodes are automatically activated before -+# creating the export and trying to inactivate them later fails. -+# (since: 10.0; default: false) -+# - # Since: 4.2 - ## - { 'union': 'BlockExportOptions', -@@ -381,7 +388,8 @@ - '*iothread': 'str', - 'node-name': 'str', - '*writable': 'bool', -- '*writethrough': 'bool' }, -+ '*writethrough': 'bool', -+ '*allow-inactive': 'bool' }, - 'discriminator': 'type', - 'data': { - 'nbd': 'BlockExportOptionsNbd', --- -2.48.1 - diff --git a/SPECS/qemu/kvm-block-export-Don-t-ignore-image-activation-error-in-.patch b/SPECS/qemu/kvm-block-export-Don-t-ignore-image-activation-error-in-.patch deleted file mode 100644 index 217851f869d..00000000000 --- a/SPECS/qemu/kvm-block-export-Don-t-ignore-image-activation-error-in-.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0cced76da63a886e6aaaa96a2c40620db27cb8cc Mon Sep 17 00:00:00 2001 -From: Kevin Wolf -Date: Tue, 4 Feb 2025 22:14:01 +0100 -Subject: [PATCH 17/23] block/export: Don't ignore image activation error in - blk_exp_add() - -RH-Author: Kevin Wolf -RH-MergeRequest: 339: QMP command for block device reactivation after migration -RH-Jira: RHEL-54296 RHEL-78397 -RH-Acked-by: Eric Blake -RH-Acked-by: Stefan Hajnoczi -RH-Commit: [16/22] 86e791a19948c88a3512bb7ba3bd3ed0f03a2a18 (kmwolf/centos-qemu-kvm) - -Currently, block exports can't handle inactive images correctly. -Incoming write requests would run into assertion failures. Make sure -that we return an error when creating an export can't activate the -image. - -Signed-off-by: Kevin Wolf -Acked-by: Fabiano Rosas -Reviewed-by: Eric Blake -Reviewed-by: Stefan Hajnoczi -Message-ID: <20250204211407.381505-11-kwolf@redhat.com> -Signed-off-by: Kevin Wolf -(cherry picked from commit 69f28176ca0af850db23a1c6364f0c8525b20801) -Signed-off-by: Kevin Wolf ---- - block/export/export.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/block/export/export.c b/block/export/export.c -index 6d51ae8ed7..23a86efcdb 100644 ---- a/block/export/export.c -+++ b/block/export/export.c -@@ -145,7 +145,11 @@ BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp) - * ctx was acquired in the caller. - */ - bdrv_graph_rdlock_main_loop(); -- bdrv_activate(bs, NULL); -+ ret = bdrv_activate(bs, errp); -+ if (ret < 0) { -+ bdrv_graph_rdunlock_main_loop(); -+ goto fail; -+ } - bdrv_graph_rdunlock_main_loop(); - - perm = BLK_PERM_CONSISTENT_READ; --- -2.48.1 - diff --git a/SPECS/qemu/kvm-migration-Add-helper-to-get-target-runstate.patch b/SPECS/qemu/kvm-migration-Add-helper-to-get-target-runstate.patch deleted file mode 100644 index 7c58ada8e17..00000000000 --- a/SPECS/qemu/kvm-migration-Add-helper-to-get-target-runstate.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 21e971c2d7a8aee5cb95b7714c15374331add796 Mon Sep 17 00:00:00 2001 -From: Peter Xu -Date: Fri, 6 Dec 2024 18:08:33 -0500 -Subject: [PATCH 02/23] migration: Add helper to get target runstate - -RH-Author: Kevin Wolf -RH-MergeRequest: 339: QMP command for block device reactivation after migration -RH-Jira: RHEL-54296 RHEL-78397 -RH-Acked-by: Eric Blake -RH-Acked-by: Stefan Hajnoczi -RH-Commit: [1/22] d1b2ee0d6a878e71ad04ace9fd82d8aab2d5217b (kmwolf/centos-qemu-kvm) - -In 99% cases, after QEMU migrates to dest host, it tries to detect the -target VM runstate using global_state_get_runstate(). - -There's one outlier so far which is Xen that won't send global state. -That's the major reason why global_state_received() check was always there -together with global_state_get_runstate(). - -However it's utterly confusing why global_state_received() has anything to -do with "let's start VM or not". - -Provide a helper to explain it, then we have an unified entry for getting -the target dest QEMU runstate after migration. - -Suggested-by: Fabiano Rosas -Signed-off-by: Peter Xu -Message-Id: <20241206230838.1111496-2-peterx@redhat.com> -Signed-off-by: Fabiano Rosas -(cherry picked from commit 7815f69867da92335055d4b5248430b0f122ce4e) -Signed-off-by: Kevin Wolf ---- - migration/migration.c | 21 +++++++++++++++++---- - 1 file changed, 17 insertions(+), 4 deletions(-) - -diff --git a/migration/migration.c b/migration/migration.c -index 3dea06d577..c7a9e2e026 100644 ---- a/migration/migration.c -+++ b/migration/migration.c -@@ -135,6 +135,21 @@ static bool migration_needs_multiple_sockets(void) - return migrate_multifd() || migrate_postcopy_preempt(); - } - -+static RunState migration_get_target_runstate(void) -+{ -+ /* -+ * When the global state is not migrated, it means we don't know the -+ * runstate of the src QEMU. We don't have much choice but assuming -+ * the VM is running. NOTE: this is pretty rare case, so far only Xen -+ * uses it. -+ */ -+ if (!global_state_received()) { -+ return RUN_STATE_RUNNING; -+ } -+ -+ return global_state_get_runstate(); -+} -+ - static bool transport_supports_multi_channels(MigrationAddress *addr) - { - if (addr->transport == MIGRATION_ADDRESS_TYPE_SOCKET) { -@@ -727,8 +742,7 @@ static void process_incoming_migration_bh(void *opaque) - * unless we really are starting the VM. - */ - if (!migrate_late_block_activate() || -- (autostart && (!global_state_received() || -- runstate_is_live(global_state_get_runstate())))) { -+ (autostart && runstate_is_live(migration_get_target_runstate()))) { - /* Make sure all file formats throw away their mutable metadata. - * If we get an error here, just don't restart the VM yet. */ - bdrv_activate_all(&local_err); -@@ -751,8 +765,7 @@ static void process_incoming_migration_bh(void *opaque) - - dirty_bitmap_mig_before_vm_start(); - -- if (!global_state_received() || -- runstate_is_live(global_state_get_runstate())) { -+ if (runstate_is_live(migration_get_target_runstate())) { - if (autostart) { - vm_start(); - } else { --- -2.48.1 - diff --git a/SPECS/qemu/kvm-migration-Ensure-vmstate_save-sets-errp.patch b/SPECS/qemu/kvm-migration-Ensure-vmstate_save-sets-errp.patch deleted file mode 100644 index 6493c3e98d6..00000000000 --- a/SPECS/qemu/kvm-migration-Ensure-vmstate_save-sets-errp.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 91f67a47a3fd31be578988d7ac11bb814314ec5a Mon Sep 17 00:00:00 2001 -From: Hanna Czenczek -Date: Tue, 15 Oct 2024 19:04:37 +0200 -Subject: [PATCH] migration: Ensure vmstate_save() sets errp - -RH-Author: Hanna Czenczek -RH-MergeRequest: 295: migration: Ensure vmstate_save() sets errp -RH-Jira: RHEL-67844 -RH-Acked-by: Stefano Garzarella -RH-Acked-by: Jon Maloy -RH-Commit: [1/1] df65f254fa6bf241b1fd4f4d2101f137d2a6e44b (hreitz/qemu-kvm-c-9-s) - -migration/savevm.c contains some calls to vmstate_save() that are -followed by migrate_set_error() if the integer return value indicates an -error. migrate_set_error() requires that the `Error *` object passed to -it is set. Therefore, vmstate_save() is assumed to always set *errp on -error. - -Right now, that assumption is not met: vmstate_save_state_v() (called -internally by vmstate_save()) will not set *errp if -vmstate_subsection_save() or vmsd->post_save() fail. Fix that by adding -an *errp parameter to vmstate_subsection_save(), and by generating a -generic error in case post_save() fails (as is already done for -pre_save()). - -Without this patch, qemu will crash after vmstate_subsection_save() or -post_save() have failed inside of a vmstate_save() call (unless -migrate_set_error() then happen to discard the new error because -s->error is already set). This happens e.g. when receiving the state -from a virtio-fs back-end (virtiofsd) fails. - -Signed-off-by: Hanna Czenczek -Link: https://lore.kernel.org/r/20241015170437.310358-1-hreitz@redhat.com -Signed-off-by: Peter Xu -(cherry picked from commit 37dfcba1a04989830c706f9cbc00450e5d3a7447) -Signed-off-by: Hanna Czenczek ---- - migration/vmstate.c | 13 ++++++++----- - 1 file changed, 8 insertions(+), 5 deletions(-) - -diff --git a/migration/vmstate.c b/migration/vmstate.c -index ef26f26ccd..d19b42630a 100644 ---- a/migration/vmstate.c -+++ b/migration/vmstate.c -@@ -22,7 +22,8 @@ - #include "trace.h" - - static int vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd, -- void *opaque, JSONWriter *vmdesc); -+ void *opaque, JSONWriter *vmdesc, -+ Error **errp); - static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd, - void *opaque); - -@@ -440,12 +441,13 @@ int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd, - json_writer_end_array(vmdesc); - } - -- ret = vmstate_subsection_save(f, vmsd, opaque, vmdesc); -+ ret = vmstate_subsection_save(f, vmsd, opaque, vmdesc, errp); - - if (vmsd->post_save) { - int ps_ret = vmsd->post_save(opaque); -- if (!ret) { -+ if (!ret && ps_ret) { - ret = ps_ret; -+ error_setg(errp, "post-save failed: %s", vmsd->name); - } - } - return ret; -@@ -517,7 +519,8 @@ static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd, - } - - static int vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd, -- void *opaque, JSONWriter *vmdesc) -+ void *opaque, JSONWriter *vmdesc, -+ Error **errp) - { - const VMStateDescription * const *sub = vmsd->subsections; - bool vmdesc_has_subsections = false; -@@ -545,7 +548,7 @@ static int vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd, - qemu_put_byte(f, len); - qemu_put_buffer(f, (uint8_t *)vmsdsub->name, len); - qemu_put_be32(f, vmsdsub->version_id); -- ret = vmstate_save_state(f, vmsdsub, opaque, vmdesc); -+ ret = vmstate_save_state_with_err(f, vmsdsub, opaque, vmdesc, errp); - if (ret) { - return ret; - } --- -2.45.1 - diff --git a/SPECS/qemu/kvm-migration-Fix-UAF-for-incoming-migration-on-Migratio.patch b/SPECS/qemu/kvm-migration-Fix-UAF-for-incoming-migration-on-Migratio.patch deleted file mode 100644 index d9d12bf95a4..00000000000 --- a/SPECS/qemu/kvm-migration-Fix-UAF-for-incoming-migration-on-Migratio.patch +++ /dev/null @@ -1,180 +0,0 @@ -From 5d7d7a2ec6301f4d0b0dbea4fbdcab4e41a9cf07 Mon Sep 17 00:00:00 2001 -From: Peter Xu -Date: Thu, 20 Feb 2025 08:24:59 -0500 -Subject: [PATCH 7/9] migration: Fix UAF for incoming migration on - MigrationState - -RH-Author: Peter Xu -RH-MergeRequest: 344: migration: Fix UAF for incoming migration on MigrationState -RH-Jira: RHEL-69775 -RH-Acked-by: Juraj Marcin -RH-Acked-by: Jon Maloy -RH-Commit: [1/1] 106e2b4c1c461202c912b5e3ea7e586c4ab05d8c (peterx/qemu-kvm) - -On the incoming migration side, QEMU uses a coroutine to load all the VM -states. Inside, it may reference MigrationState on global states like -migration capabilities, parameters, error state, shared mutexes and more. - -However there's nothing yet to make sure MigrationState won't get -destroyed (e.g. after migration_shutdown()). Meanwhile there's also no API -available to remove the incoming coroutine in migration_shutdown(), -avoiding it to access the freed elements. - -There's a bug report showing this can happen and crash dest QEMU when -migration is cancelled on source. - -When it happens, the dest main thread is trying to cleanup everything: - - #0 qemu_aio_coroutine_enter - #1 aio_dispatch_handler - #2 aio_poll - #3 monitor_cleanup - #4 qemu_cleanup - #5 qemu_default_main - -Then it found the migration incoming coroutine, schedule it (even after -migration_shutdown()), causing crash: - - #0 __pthread_kill_implementation - #1 __pthread_kill_internal - #2 __GI_raise - #3 __GI_abort - #4 __assert_fail_base - #5 __assert_fail - #6 qemu_mutex_lock_impl - #7 qemu_lockable_mutex_lock - #8 qemu_lockable_lock - #9 qemu_lockable_auto_lock - #10 migrate_set_error - #11 process_incoming_migration_co - #12 coroutine_trampoline - -To fix it, take a refcount after an incoming setup is properly done when -qmp_migrate_incoming() succeeded the 1st time. As it's during a QMP -handler which needs BQL, it means the main loop is still alive (without -going into cleanups, which also needs BQL). - -Releasing the refcount now only until the incoming migration coroutine -finished or failed. Hence the refcount is valid for both (1) setup phase -of incoming ports, mostly IO watches (e.g. qio_channel_add_watch_full()), -and (2) the incoming coroutine itself (process_incoming_migration_co()). - -Note that we can't unref in migration_incoming_state_destroy(), because -both qmp_xen_load_devices_state() and load_snapshot() will use it without -an incoming migration. Those hold BQL so they're not prone to this issue. - -PS: I suspect nobody uses Xen's command at all, as it didn't register yank, -hence AFAIU the command should crash on master when trying to unregister -yank in migration_incoming_state_destroy().. but that's another story. - -Also note that in some incoming failure cases we may not always unref the -MigrationState refcount, which is a trade-off to keep things simple. We -could make it accurate, but it can be an overkill. Some examples: - - - Unlike most of the rest protocols, socket_start_incoming_migration() - may create net listener after incoming port setup sucessfully. - It means we can't unref in migration_channel_process_incoming() as a - generic path because socket protocol might keep using MigrationState. - - - For either socket or file, multiple IO watches might be created, it - means logically each IO watch needs to take one refcount for - MigrationState so as to be 100% accurate on ownership of refcount taken. - -In general, we at least need per-protocol handling to make it accurate, -which can be an overkill if we know incoming failed after all. Add a short -comment to explain that when taking the refcount in qmp_migrate_incoming(). - -Bugzilla: https://issues.redhat.com/browse/RHEL-69775 -Tested-by: Yan Fu -Signed-off-by: Peter Xu -Reviewed-by: Fabiano Rosas -Message-ID: <20250220132459.512610-1-peterx@redhat.com> -Signed-off-by: Fabiano Rosas -(cherry picked from commit d657a14de5d597bbfe7b54e4c4f0646f440e98ad) -Signed-off-by: Peter Xu ---- - migration/migration.c | 40 ++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 38 insertions(+), 2 deletions(-) - -diff --git a/migration/migration.c b/migration/migration.c -index 999d4cac54..aabdc45c16 100644 ---- a/migration/migration.c -+++ b/migration/migration.c -@@ -115,6 +115,27 @@ static void migration_downtime_start(MigrationState *s) - s->downtime_start = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); - } - -+/* -+ * This is unfortunate: incoming migration actually needs the outgoing -+ * migration state (MigrationState) to be there too, e.g. to query -+ * capabilities, parameters, using locks, setup errors, etc. -+ * -+ * NOTE: when calling this, making sure current_migration exists and not -+ * been freed yet! Otherwise trying to access the refcount is already -+ * an use-after-free itself.. -+ * -+ * TODO: Move shared part of incoming / outgoing out into separate object. -+ * Then this is not needed. -+ */ -+static void migrate_incoming_ref_outgoing_state(void) -+{ -+ object_ref(migrate_get_current()); -+} -+static void migrate_incoming_unref_outgoing_state(void) -+{ -+ object_unref(migrate_get_current()); -+} -+ - static void migration_downtime_end(MigrationState *s) - { - int64_t now = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); -@@ -821,7 +842,7 @@ process_incoming_migration_co(void *opaque) - * postcopy thread. - */ - trace_process_incoming_migration_co_postcopy_end_main(); -- return; -+ goto out; - } - /* Else if something went wrong then just fall out of the normal exit */ - } -@@ -837,7 +858,8 @@ process_incoming_migration_co(void *opaque) - } - - migration_bh_schedule(process_incoming_migration_bh, mis); -- return; -+ goto out; -+ - fail: - migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE, - MIGRATION_STATUS_FAILED); -@@ -854,6 +876,9 @@ fail: - - exit(EXIT_FAILURE); - } -+out: -+ /* Pairs with the refcount taken in qmp_migrate_incoming() */ -+ migrate_incoming_unref_outgoing_state(); - } - - /** -@@ -1875,6 +1900,17 @@ void qmp_migrate_incoming(const char *uri, bool has_channels, - return; - } - -+ /* -+ * Making sure MigrationState is available until incoming migration -+ * completes. -+ * -+ * NOTE: QEMU _might_ leak this refcount in some failure paths, but -+ * that's OK. This is the minimum change we need to at least making -+ * sure success case is clean on the refcount. We can try harder to -+ * make it accurate for any kind of failures, but it might be an -+ * overkill and doesn't bring us much benefit. -+ */ -+ migrate_incoming_ref_outgoing_state(); - once = false; - } - --- -2.48.1 - diff --git a/SPECS/qemu/kvm-migration-block-Apply-late-block-active-behavior-to-.patch b/SPECS/qemu/kvm-migration-block-Apply-late-block-active-behavior-to-.patch deleted file mode 100644 index f052aa34807..00000000000 --- a/SPECS/qemu/kvm-migration-block-Apply-late-block-active-behavior-to-.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 149fdbbe765e0153a533d5bed653e7de16f8ad9b Mon Sep 17 00:00:00 2001 -From: Peter Xu -Date: Fri, 6 Dec 2024 18:08:36 -0500 -Subject: [PATCH 05/23] migration/block: Apply late-block-active behavior to - postcopy - -RH-Author: Kevin Wolf -RH-MergeRequest: 339: QMP command for block device reactivation after migration -RH-Jira: RHEL-54296 RHEL-78397 -RH-Acked-by: Eric Blake -RH-Acked-by: Stefan Hajnoczi -RH-Commit: [4/22] 1ba47fc6bb9e3b244f75b2f29a89b9fd4014deea (kmwolf/centos-qemu-kvm) - -Postcopy never cared about late-block-active. However there's no mention -in the capability that it doesn't apply to postcopy. - -Considering that we _assumed_ late activation is always good, do that too -for postcopy unconditionally, just like precopy. After this patch, we -should have unified the behavior across all. - -Signed-off-by: Peter Xu -Reviewed-by: Fabiano Rosas -Message-Id: <20241206230838.1111496-5-peterx@redhat.com> -Signed-off-by: Fabiano Rosas -(cherry picked from commit 61f2b489987c51159c53101a072c6aa901b50506) -Signed-off-by: Kevin Wolf ---- - migration/savevm.c | 25 ++++++++++++------------- - 1 file changed, 12 insertions(+), 13 deletions(-) - -diff --git a/migration/savevm.c b/migration/savevm.c -index 6bb404b9c8..a0c4befdc1 100644 ---- a/migration/savevm.c -+++ b/migration/savevm.c -@@ -2156,22 +2156,21 @@ static void loadvm_postcopy_handle_run_bh(void *opaque) - - trace_vmstate_downtime_checkpoint("dst-postcopy-bh-announced"); - -- /* Make sure all file formats throw away their mutable metadata. -- * If we get an error here, just don't restart the VM yet. */ -- bdrv_activate_all(&local_err); -- if (local_err) { -- error_report_err(local_err); -- local_err = NULL; -- autostart = false; -- } -- -- trace_vmstate_downtime_checkpoint("dst-postcopy-bh-cache-invalidated"); -- - dirty_bitmap_mig_before_vm_start(); - - if (autostart) { -- /* Hold onto your hats, starting the CPU */ -- vm_start(); -+ /* -+ * Make sure all file formats throw away their mutable metadata. -+ * If we get an error here, just don't restart the VM yet. -+ */ -+ bdrv_activate_all(&local_err); -+ trace_vmstate_downtime_checkpoint("dst-postcopy-bh-cache-invalidated"); -+ if (local_err) { -+ error_report_err(local_err); -+ local_err = NULL; -+ } else { -+ vm_start(); -+ } - } else { - /* leave it paused and let management decide when to start the CPU */ - runstate_set(RUN_STATE_PAUSED); --- -2.48.1 - diff --git a/SPECS/qemu/kvm-migration-block-Fix-possible-race-with-block_inactiv.patch b/SPECS/qemu/kvm-migration-block-Fix-possible-race-with-block_inactiv.patch deleted file mode 100644 index f0a36d47485..00000000000 --- a/SPECS/qemu/kvm-migration-block-Fix-possible-race-with-block_inactiv.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 703a2b932f8b6e06f4a1c0cdfdf7f4cf030a6e38 Mon Sep 17 00:00:00 2001 -From: Peter Xu -Date: Fri, 6 Dec 2024 18:08:37 -0500 -Subject: [PATCH 06/23] migration/block: Fix possible race with block_inactive - -RH-Author: Kevin Wolf -RH-MergeRequest: 339: QMP command for block device reactivation after migration -RH-Jira: RHEL-54296 RHEL-78397 -RH-Acked-by: Eric Blake -RH-Acked-by: Stefan Hajnoczi -RH-Commit: [5/22] 6300de6a4a19d4648e5a5503ef8cec557fe8e666 (kmwolf/centos-qemu-kvm) - -Src QEMU sets block_inactive=true very early before the invalidation takes -place. It means if something wrong happened during setting the flag but -before reaching qemu_savevm_state_complete_precopy_non_iterable() where it -did the invalidation work, it'll make block_inactive flag inconsistent. - -For example, think about when qemu_savevm_state_complete_precopy_iterable() -can fail: it will have block_inactive set to true even if all block drives -are active. - -Fix that by only update the flag after the invalidation is done. - -No Fixes for any commit, because it's not an issue if bdrv_activate_all() -is re-entrant upon all-active disks - false positive block_inactive can -bring nothing more than "trying to active the blocks but they're already -active". However let's still do it right to avoid the inconsistent flag -v.s. reality. - -Signed-off-by: Peter Xu -Reviewed-by: Fabiano Rosas -Message-Id: <20241206230838.1111496-6-peterx@redhat.com> -Signed-off-by: Fabiano Rosas -(cherry picked from commit 8c97c5a476d146b35b2873ef73df601216a494d9) -Signed-off-by: Kevin Wolf ---- - migration/migration.c | 9 +++------ - migration/savevm.c | 2 ++ - 2 files changed, 5 insertions(+), 6 deletions(-) - -diff --git a/migration/migration.c b/migration/migration.c -index 8a262e01ff..784b7e9b90 100644 ---- a/migration/migration.c -+++ b/migration/migration.c -@@ -2779,14 +2779,11 @@ static int migration_completion_precopy(MigrationState *s, - goto out_unlock; - } - -- /* -- * Inactivate disks except in COLO, and track that we have done so in order -- * to remember to reactivate them if migration fails or is cancelled. -- */ -- s->block_inactive = !migrate_colo(); - migration_rate_set(RATE_LIMIT_DISABLED); -+ -+ /* Inactivate disks except in COLO */ - ret = qemu_savevm_state_complete_precopy(s->to_dst_file, false, -- s->block_inactive); -+ !migrate_colo()); - out_unlock: - bql_unlock(); - return ret; -diff --git a/migration/savevm.c b/migration/savevm.c -index a0c4befdc1..b88dadd904 100644 ---- a/migration/savevm.c -+++ b/migration/savevm.c -@@ -1577,6 +1577,8 @@ int qemu_savevm_state_complete_precopy_non_iterable(QEMUFile *f, - qemu_file_set_error(f, ret); - return ret; - } -+ /* Remember that we did this */ -+ s->block_inactive = true; - } - if (!in_postcopy) { - /* Postcopy stream will still be going */ --- -2.48.1 - diff --git a/SPECS/qemu/kvm-migration-block-Make-late-block-active-the-default.patch b/SPECS/qemu/kvm-migration-block-Make-late-block-active-the-default.patch deleted file mode 100644 index 93134981ad8..00000000000 --- a/SPECS/qemu/kvm-migration-block-Make-late-block-active-the-default.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 5a3017fbfb1081fc0a074ee53e1ad7ba8489c8c1 Mon Sep 17 00:00:00 2001 -From: Peter Xu -Date: Fri, 6 Dec 2024 18:08:35 -0500 -Subject: [PATCH 04/23] migration/block: Make late-block-active the default - -RH-Author: Kevin Wolf -RH-MergeRequest: 339: QMP command for block device reactivation after migration -RH-Jira: RHEL-54296 RHEL-78397 -RH-Acked-by: Eric Blake -RH-Acked-by: Stefan Hajnoczi -RH-Commit: [3/22] 74d95ded9153bf0969ede7d7d2708e9452d7cd11 (kmwolf/centos-qemu-kvm) - -Migration capability 'late-block-active' controls when the block drives -will be activated. If enabled, block drives will only be activated until -VM starts, either src runstate was "live" (RUNNING, or SUSPENDED), or it'll -be postponed until qmp_cont(). - -Let's do this unconditionally. There's no harm to delay activation of -block drives. Meanwhile there's no ABI breakage if dest does it, because -src QEMU has nothing to do with it, so it's no concern on ABI breakage. - -IIUC we could avoid introducing this cap when introducing it before, but -now it's still not too late to just always do it. Cap now prone to -removal, but it'll be for later patches. - -Signed-off-by: Peter Xu -Reviewed-by: Fabiano Rosas -Message-Id: <20241206230838.1111496-4-peterx@redhat.com> -Signed-off-by: Fabiano Rosas -(cherry picked from commit fca9aef1c8d8fc4482cc541638dbfac76dc125d6) -Signed-off-by: Kevin Wolf ---- - migration/migration.c | 38 +++++++++++++++++++------------------- - 1 file changed, 19 insertions(+), 19 deletions(-) - -diff --git a/migration/migration.c b/migration/migration.c -index c7a9e2e026..8a262e01ff 100644 ---- a/migration/migration.c -+++ b/migration/migration.c -@@ -735,24 +735,6 @@ static void process_incoming_migration_bh(void *opaque) - - trace_vmstate_downtime_checkpoint("dst-precopy-bh-enter"); - -- /* If capability late_block_activate is set: -- * Only fire up the block code now if we're going to restart the -- * VM, else 'cont' will do it. -- * This causes file locking to happen; so we don't want it to happen -- * unless we really are starting the VM. -- */ -- if (!migrate_late_block_activate() || -- (autostart && runstate_is_live(migration_get_target_runstate()))) { -- /* Make sure all file formats throw away their mutable metadata. -- * If we get an error here, just don't restart the VM yet. */ -- bdrv_activate_all(&local_err); -- if (local_err) { -- error_report_err(local_err); -- local_err = NULL; -- autostart = false; -- } -- } -- - /* - * This must happen after all error conditions are dealt with and - * we're sure the VM is going to be running on this host. -@@ -767,7 +749,25 @@ static void process_incoming_migration_bh(void *opaque) - - if (runstate_is_live(migration_get_target_runstate())) { - if (autostart) { -- vm_start(); -+ /* -+ * Block activation is always delayed until VM starts, either -+ * here (which means we need to start the dest VM right now..), -+ * or until qmp_cont() later. -+ * -+ * We used to have cap 'late-block-activate' but now we do this -+ * unconditionally, as it has no harm but only benefit. E.g., -+ * it's not part of migration ABI on the time of disk activation. -+ * -+ * Make sure all file formats throw away their mutable -+ * metadata. If error, don't restart the VM yet. -+ */ -+ bdrv_activate_all(&local_err); -+ if (local_err) { -+ error_report_err(local_err); -+ local_err = NULL; -+ } else { -+ vm_start(); -+ } - } else { - runstate_set(RUN_STATE_PAUSED); - } --- -2.48.1 - diff --git a/SPECS/qemu/kvm-migration-block-Rewrite-disk-activation.patch b/SPECS/qemu/kvm-migration-block-Rewrite-disk-activation.patch deleted file mode 100644 index dc8cb1d2f80..00000000000 --- a/SPECS/qemu/kvm-migration-block-Rewrite-disk-activation.patch +++ /dev/null @@ -1,565 +0,0 @@ -From f478efadbb1629028af0e65e8408fe49256b2f17 Mon Sep 17 00:00:00 2001 -From: Peter Xu -Date: Fri, 6 Dec 2024 18:08:38 -0500 -Subject: [PATCH 07/23] migration/block: Rewrite disk activation - -RH-Author: Kevin Wolf -RH-MergeRequest: 339: QMP command for block device reactivation after migration -RH-Jira: RHEL-54296 RHEL-78397 -RH-Acked-by: Eric Blake -RH-Acked-by: Stefan Hajnoczi -RH-Commit: [6/22] cd000f0b00e6f768288f340e1801dd5a236d430c (kmwolf/centos-qemu-kvm) - -This patch proposes a flag to maintain disk activation status globally. It -mostly rewrites disk activation mgmt for QEMU, including COLO and QMP -command xen_save_devices_state. - -Backgrounds -=========== - -We have two problems on disk activations, one resolved, one not. - -Problem 1: disk activation recover (for switchover interruptions) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -When migration is either cancelled or failed during switchover, especially -when after the disks are inactivated, QEMU needs to remember re-activate -the disks again before vm starts. - -It used to be done separately in two paths: one in qmp_migrate_cancel(), -the other one in the failure path of migration_completion(). - -It used to be fixed in different commits, all over the places in QEMU. So -these are the relevant changes I saw, I'm not sure if it's complete list: - - - In 2016, commit fe904ea824 ("migration: regain control of images when - migration fails to complete") - - - In 2017, commit 1d2acc3162 ("migration: re-active images while migration - been canceled after inactive them") - - - In 2023, commit 6dab4c93ec ("migration: Attempt disk reactivation in - more failure scenarios") - -Now since we have a slightly better picture maybe we can unify the -reactivation in a single path. - -One side benefit of doing so is, we can move the disk operation outside QMP -command "migrate_cancel". It's possible that in the future we may want to -make "migrate_cancel" be OOB-compatible, while that requires the command -doesn't need BQL in the first place. This will already do that and make -migrate_cancel command lightweight. - -Problem 2: disk invalidation on top of invalidated disks -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -This is an unresolved bug for current QEMU. Link in "Resolves:" at the -end. It turns out besides the src switchover phase (problem 1 above), QEMU -also needs to remember block activation on destination. - -Consider two continuous migration in a row, where the VM was always paused. -In that scenario, the disks are not activated even until migration -completed in the 1st round. When the 2nd round starts, if QEMU doesn't -know the status of the disks, it needs to try inactivate the disk again. - -Here the issue is the block layer API bdrv_inactivate_all() will crash a -QEMU if invoked on already inactive disks for the 2nd migration. For -detail, see the bug link at the end. - -Implementation -============== - -This patch proposes to maintain disk activation with a global flag, so we -know: - - - If we used to inactivate disks for migration, but migration got - cancelled, or failed, QEMU will know it should reactivate the disks. - - - On incoming side, if the disks are never activated but then another - migration is triggered, QEMU should be able to tell that inactivate is - not needed for the 2nd migration. - -We used to have disk_inactive, but it only solves the 1st issue, not the -2nd. Also, it's done in completely separate paths so it's extremely hard -to follow either how the flag changes, or the duration that the flag is -valid, and when we will reactivate the disks. - -Convert the existing disk_inactive flag into that global flag (also invert -its naming), and maintain the disk activation status for the whole -lifecycle of qemu. That includes the incoming QEMU. - -Put both of the error cases of source migration (failure, cancelled) -together into migration_iteration_finish(), which will be invoked for -either of the scenario. So from that part QEMU should behave the same as -before. However with such global maintenance on disk activation status, we -not only cleanup quite a few temporary paths that we try to maintain the -disk activation status (e.g. in postcopy code), meanwhile it fixes the -crash for problem 2 in one shot. - -For freshly started QEMU, the flag is initialized to TRUE showing that the -QEMU owns the disks by default. - -For incoming migrated QEMU, the flag will be initialized to FALSE once and -for all showing that the dest QEMU doesn't own the disks until switchover. -That is guaranteed by the "once" variable. - -Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2395 -Signed-off-by: Peter Xu -Reviewed-by: Fabiano Rosas -Message-Id: <20241206230838.1111496-7-peterx@redhat.com> -Signed-off-by: Fabiano Rosas -(cherry picked from commit 8597af76153a87068b675d8099063c3ad8695773) -Signed-off-by: Kevin Wolf ---- - include/migration/misc.h | 4 ++ - migration/block-active.c | 94 ++++++++++++++++++++++++++++++++++++++++ - migration/colo.c | 2 +- - migration/meson.build | 1 + - migration/migration.c | 80 ++++++++-------------------------- - migration/migration.h | 5 +-- - migration/savevm.c | 33 ++++++-------- - migration/trace-events | 3 ++ - monitor/qmp-cmds.c | 8 +--- - 9 files changed, 139 insertions(+), 91 deletions(-) - create mode 100644 migration/block-active.c - -diff --git a/include/migration/misc.h b/include/migration/misc.h -index bfadc5613b..35ca8e1194 100644 ---- a/include/migration/misc.h -+++ b/include/migration/misc.h -@@ -111,4 +111,8 @@ bool migration_in_bg_snapshot(void); - /* migration/block-dirty-bitmap.c */ - void dirty_bitmap_mig_init(void); - -+/* Wrapper for block active/inactive operations */ -+bool migration_block_activate(Error **errp); -+bool migration_block_inactivate(void); -+ - #endif -diff --git a/migration/block-active.c b/migration/block-active.c -new file mode 100644 -index 0000000000..d477cf8182 ---- /dev/null -+++ b/migration/block-active.c -@@ -0,0 +1,94 @@ -+/* -+ * Block activation tracking for migration purpose -+ * -+ * SPDX-License-Identifier: GPL-2.0-or-later -+ * -+ * Copyright (C) 2024 Red Hat, Inc. -+ */ -+#include "qemu/osdep.h" -+#include "block/block.h" -+#include "qapi/error.h" -+#include "migration/migration.h" -+#include "qemu/error-report.h" -+#include "trace.h" -+ -+/* -+ * Migration-only cache to remember the block layer activation status. -+ * Protected by BQL. -+ * -+ * We need this because.. -+ * -+ * - Migration can fail after block devices are invalidated (during -+ * switchover phase). When that happens, we need to be able to recover -+ * the block drive status by re-activating them. -+ * -+ * - Currently bdrv_inactivate_all() is not safe to be invoked on top of -+ * invalidated drives (even if bdrv_activate_all() is actually safe to be -+ * called any time!). It means remembering this could help migration to -+ * make sure it won't invalidate twice in a row, crashing QEMU. It can -+ * happen when we migrate a PAUSED VM from host1 to host2, then migrate -+ * again to host3 without starting it. TODO: a cleaner solution is to -+ * allow safe invoke of bdrv_inactivate_all() at anytime, like -+ * bdrv_activate_all(). -+ * -+ * For freshly started QEMU, the flag is initialized to TRUE reflecting the -+ * scenario where QEMU owns block device ownerships. -+ * -+ * For incoming QEMU taking a migration stream, the flag is initialized to -+ * FALSE reflecting that the incoming side doesn't own the block devices, -+ * not until switchover happens. -+ */ -+static bool migration_block_active; -+ -+/* Setup the disk activation status */ -+void migration_block_active_setup(bool active) -+{ -+ migration_block_active = active; -+} -+ -+bool migration_block_activate(Error **errp) -+{ -+ ERRP_GUARD(); -+ -+ assert(bql_locked()); -+ -+ if (migration_block_active) { -+ trace_migration_block_activation("active-skipped"); -+ return true; -+ } -+ -+ trace_migration_block_activation("active"); -+ -+ bdrv_activate_all(errp); -+ if (*errp) { -+ error_report_err(error_copy(*errp)); -+ return false; -+ } -+ -+ migration_block_active = true; -+ return true; -+} -+ -+bool migration_block_inactivate(void) -+{ -+ int ret; -+ -+ assert(bql_locked()); -+ -+ if (!migration_block_active) { -+ trace_migration_block_activation("inactive-skipped"); -+ return true; -+ } -+ -+ trace_migration_block_activation("inactive"); -+ -+ ret = bdrv_inactivate_all(); -+ if (ret) { -+ error_report("%s: bdrv_inactivate_all() failed: %d", -+ __func__, ret); -+ return false; -+ } -+ -+ migration_block_active = false; -+ return true; -+} -diff --git a/migration/colo.c b/migration/colo.c -index 6449490221..ab903f34cb 100644 ---- a/migration/colo.c -+++ b/migration/colo.c -@@ -836,7 +836,7 @@ static void *colo_process_incoming_thread(void *opaque) - - /* Make sure all file formats throw away their mutable metadata */ - bql_lock(); -- bdrv_activate_all(&local_err); -+ migration_block_activate(&local_err); - bql_unlock(); - if (local_err) { - error_report_err(local_err); -diff --git a/migration/meson.build b/migration/meson.build -index 5ce2acb41e..6b79861d3c 100644 ---- a/migration/meson.build -+++ b/migration/meson.build -@@ -11,6 +11,7 @@ migration_files = files( - - system_ss.add(files( - 'block-dirty-bitmap.c', -+ 'block-active.c', - 'channel.c', - 'channel-block.c', - 'dirtyrate.c', -diff --git a/migration/migration.c b/migration/migration.c -index 784b7e9b90..38631d1206 100644 ---- a/migration/migration.c -+++ b/migration/migration.c -@@ -730,7 +730,6 @@ static void qemu_start_incoming_migration(const char *uri, bool has_channels, - - static void process_incoming_migration_bh(void *opaque) - { -- Error *local_err = NULL; - MigrationIncomingState *mis = opaque; - - trace_vmstate_downtime_checkpoint("dst-precopy-bh-enter"); -@@ -761,11 +760,7 @@ static void process_incoming_migration_bh(void *opaque) - * Make sure all file formats throw away their mutable - * metadata. If error, don't restart the VM yet. - */ -- bdrv_activate_all(&local_err); -- if (local_err) { -- error_report_err(local_err); -- local_err = NULL; -- } else { -+ if (migration_block_activate(NULL)) { - vm_start(); - } - } else { -@@ -1562,16 +1557,6 @@ static void migrate_fd_cancel(MigrationState *s) - } - } - } -- if (s->state == MIGRATION_STATUS_CANCELLING && s->block_inactive) { -- Error *local_err = NULL; -- -- bdrv_activate_all(&local_err); -- if (local_err) { -- error_report_err(local_err); -- } else { -- s->block_inactive = false; -- } -- } - } - - void migration_add_notifier_mode(NotifierWithReturn *notify, -@@ -1890,6 +1875,12 @@ void qmp_migrate_incoming(const char *uri, bool has_channels, - return; - } - -+ /* -+ * Newly setup incoming QEMU. Mark the block active state to reflect -+ * that the src currently owns the disks. -+ */ -+ migration_block_active_setup(false); -+ - once = false; - } - -@@ -2542,7 +2533,6 @@ static int postcopy_start(MigrationState *ms, Error **errp) - QIOChannelBuffer *bioc; - QEMUFile *fb; - uint64_t bandwidth = migrate_max_postcopy_bandwidth(); -- bool restart_block = false; - int cur_state = MIGRATION_STATUS_ACTIVE; - - if (migrate_postcopy_preempt()) { -@@ -2578,13 +2568,10 @@ static int postcopy_start(MigrationState *ms, Error **errp) - goto fail; - } - -- ret = bdrv_inactivate_all(); -- if (ret < 0) { -- error_setg_errno(errp, -ret, "%s: Failed in bdrv_inactivate_all()", -- __func__); -+ if (!migration_block_inactivate()) { -+ error_setg(errp, "%s: Failed in bdrv_inactivate_all()", __func__); - goto fail; - } -- restart_block = true; - - /* - * Cause any non-postcopiable, but iterative devices to -@@ -2654,8 +2641,6 @@ static int postcopy_start(MigrationState *ms, Error **errp) - goto fail_closefb; - } - -- restart_block = false; -- - /* Now send that blob */ - if (qemu_savevm_send_packaged(ms->to_dst_file, bioc->data, bioc->usage)) { - error_setg(errp, "%s: Failed to send packaged data", __func__); -@@ -2700,17 +2685,7 @@ fail_closefb: - fail: - migrate_set_state(&ms->state, MIGRATION_STATUS_POSTCOPY_ACTIVE, - MIGRATION_STATUS_FAILED); -- if (restart_block) { -- /* A failure happened early enough that we know the destination hasn't -- * accessed block devices, so we're safe to recover. -- */ -- Error *local_err = NULL; -- -- bdrv_activate_all(&local_err); -- if (local_err) { -- error_report_err(local_err); -- } -- } -+ migration_block_activate(NULL); - migration_call_notifiers(ms, MIG_EVENT_PRECOPY_FAILED, NULL); - bql_unlock(); - return -1; -@@ -2808,31 +2783,6 @@ static void migration_completion_postcopy(MigrationState *s) - trace_migration_completion_postcopy_end_after_complete(); - } - --static void migration_completion_failed(MigrationState *s, -- int current_active_state) --{ -- if (s->block_inactive && (s->state == MIGRATION_STATUS_ACTIVE || -- s->state == MIGRATION_STATUS_DEVICE)) { -- /* -- * If not doing postcopy, vm_start() will be called: let's -- * regain control on images. -- */ -- Error *local_err = NULL; -- -- bql_lock(); -- bdrv_activate_all(&local_err); -- if (local_err) { -- error_report_err(local_err); -- } else { -- s->block_inactive = false; -- } -- bql_unlock(); -- } -- -- migrate_set_state(&s->state, current_active_state, -- MIGRATION_STATUS_FAILED); --} -- - /** - * migration_completion: Used by migration_thread when there's not much left. - * The caller 'breaks' the loop when this returns. -@@ -2886,7 +2836,8 @@ fail: - error_free(local_err); - } - -- migration_completion_failed(s, current_active_state); -+ migrate_set_state(&s->state, current_active_state, -+ MIGRATION_STATUS_FAILED); - } - - /** -@@ -3309,6 +3260,11 @@ static void migration_iteration_finish(MigrationState *s) - case MIGRATION_STATUS_FAILED: - case MIGRATION_STATUS_CANCELLED: - case MIGRATION_STATUS_CANCELLING: -+ /* -+ * Re-activate the block drives if they're inactivated. Note, COLO -+ * shouldn't use block_active at all, so it should be no-op there. -+ */ -+ migration_block_activate(NULL); - if (runstate_is_live(s->vm_old_state)) { - if (!runstate_check(RUN_STATE_SHUTDOWN)) { - vm_start(); -@@ -3869,6 +3825,8 @@ static void migration_instance_init(Object *obj) - ms->state = MIGRATION_STATUS_NONE; - ms->mbps = -1; - ms->pages_per_second = -1; -+ /* Freshly started QEMU owns all the block devices */ -+ migration_block_active_setup(true); - qemu_sem_init(&ms->pause_sem, 0); - qemu_mutex_init(&ms->error_mutex); - -diff --git a/migration/migration.h b/migration/migration.h -index 38aa1402d5..5b17c1344d 100644 ---- a/migration/migration.h -+++ b/migration/migration.h -@@ -356,9 +356,6 @@ struct MigrationState { - /* Flag set once the migration thread is running (and needs joining) */ - bool migration_thread_running; - -- /* Flag set once the migration thread called bdrv_inactivate_all */ -- bool block_inactive; -- - /* Migration is waiting for guest to unplug device */ - QemuSemaphore wait_unplug_sem; - -@@ -537,4 +534,6 @@ int migration_rp_wait(MigrationState *s); - */ - void migration_rp_kick(MigrationState *s); - -+/* migration/block-active.c */ -+void migration_block_active_setup(bool active); - #endif -diff --git a/migration/savevm.c b/migration/savevm.c -index b88dadd904..7f8d177462 100644 ---- a/migration/savevm.c -+++ b/migration/savevm.c -@@ -1566,19 +1566,18 @@ int qemu_savevm_state_complete_precopy_non_iterable(QEMUFile *f, - } - - if (inactivate_disks) { -- /* Inactivate before sending QEMU_VM_EOF so that the -- * bdrv_activate_all() on the other end won't fail. */ -- ret = bdrv_inactivate_all(); -- if (ret) { -- error_setg(&local_err, "%s: bdrv_inactivate_all() failed (%d)", -- __func__, ret); -+ /* -+ * Inactivate before sending QEMU_VM_EOF so that the -+ * bdrv_activate_all() on the other end won't fail. -+ */ -+ if (!migration_block_inactivate()) { -+ error_setg(&local_err, "%s: bdrv_inactivate_all() failed", -+ __func__); - migrate_set_error(ms, local_err); - error_report_err(local_err); -- qemu_file_set_error(f, ret); -+ qemu_file_set_error(f, -EFAULT); - return ret; - } -- /* Remember that we did this */ -- s->block_inactive = true; - } - if (!in_postcopy) { - /* Postcopy stream will still be going */ -@@ -2142,7 +2141,6 @@ static int loadvm_postcopy_handle_listen(MigrationIncomingState *mis) - - static void loadvm_postcopy_handle_run_bh(void *opaque) - { -- Error *local_err = NULL; - MigrationIncomingState *mis = opaque; - - trace_vmstate_downtime_checkpoint("dst-postcopy-bh-enter"); -@@ -2165,12 +2163,11 @@ static void loadvm_postcopy_handle_run_bh(void *opaque) - * Make sure all file formats throw away their mutable metadata. - * If we get an error here, just don't restart the VM yet. - */ -- bdrv_activate_all(&local_err); -+ bool success = migration_block_activate(NULL); -+ - trace_vmstate_downtime_checkpoint("dst-postcopy-bh-cache-invalidated"); -- if (local_err) { -- error_report_err(local_err); -- local_err = NULL; -- } else { -+ -+ if (success) { - vm_start(); - } - } else { -@@ -3214,11 +3211,7 @@ void qmp_xen_save_devices_state(const char *filename, bool has_live, bool live, - * side of the migration take control of the images. - */ - if (live && !saved_vm_running) { -- ret = bdrv_inactivate_all(); -- if (ret) { -- error_setg(errp, "%s: bdrv_inactivate_all() failed (%d)", -- __func__, ret); -- } -+ migration_block_inactivate(); - } - } - -diff --git a/migration/trace-events b/migration/trace-events -index 0b7c3324fb..62141dc2ff 100644 ---- a/migration/trace-events -+++ b/migration/trace-events -@@ -377,3 +377,6 @@ migration_block_progression(unsigned percent) "Completed %u%%" - # page_cache.c - migration_pagecache_init(int64_t max_num_items) "Setting cache buckets to %" PRId64 - migration_pagecache_insert(void) "Error allocating page" -+ -+# block-active.c -+migration_block_activation(const char *name) "%s" -diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c -index 76f21e8af3..6f76d9beaf 100644 ---- a/monitor/qmp-cmds.c -+++ b/monitor/qmp-cmds.c -@@ -31,6 +31,7 @@ - #include "qapi/type-helpers.h" - #include "hw/mem/memory-device.h" - #include "hw/intc/intc.h" -+#include "migration/misc.h" - - NameInfo *qmp_query_name(Error **errp) - { -@@ -103,13 +104,8 @@ void qmp_cont(Error **errp) - * Continuing after completed migration. Images have been - * inactivated to allow the destination to take control. Need to - * get control back now. -- * -- * If there are no inactive block nodes (e.g. because the VM was -- * just paused rather than completing a migration), -- * bdrv_inactivate_all() simply doesn't do anything. - */ -- bdrv_activate_all(&local_err); -- if (local_err) { -+ if (!migration_block_activate(&local_err)) { - error_propagate(errp, local_err); - return; - } --- -2.48.1 - diff --git a/SPECS/qemu/kvm-migration-block-active-Remove-global-active-flag.patch b/SPECS/qemu/kvm-migration-block-active-Remove-global-active-flag.patch deleted file mode 100644 index 7ae57128013..00000000000 --- a/SPECS/qemu/kvm-migration-block-active-Remove-global-active-flag.patch +++ /dev/null @@ -1,158 +0,0 @@ -From a0ebf9fca3b4c6a11c4476c1d1a67fecce7c7e3e Mon Sep 17 00:00:00 2001 -From: Kevin Wolf -Date: Tue, 4 Feb 2025 22:13:55 +0100 -Subject: [PATCH 11/23] migration/block-active: Remove global active flag - -RH-Author: Kevin Wolf -RH-MergeRequest: 339: QMP command for block device reactivation after migration -RH-Jira: RHEL-54296 RHEL-78397 -RH-Acked-by: Eric Blake -RH-Acked-by: Stefan Hajnoczi -RH-Commit: [10/22] 4bdf1da765bde05e2d427fc3ccca10bcc9f1dfbe (kmwolf/centos-qemu-kvm) - -Block devices have an individual active state, a single global flag -can't cover this correctly. This becomes more important as we allow -users to manually manage which nodes are active or inactive. - -Now that it's allowed to call bdrv_inactivate_all() even when some -nodes are already inactive, we can remove the flag and just -unconditionally call bdrv_inactivate_all() and, more importantly, -bdrv_activate_all() before we make use of the nodes. - -Signed-off-by: Kevin Wolf -Acked-by: Fabiano Rosas -Reviewed-by: Eric Blake -Reviewed-by: Stefan Hajnoczi -Message-ID: <20250204211407.381505-5-kwolf@redhat.com> -Signed-off-by: Kevin Wolf -(cherry picked from commit c2a189976e211c9ff782538d5a5ed5e5cffeccd6) -Signed-off-by: Kevin Wolf ---- - migration/block-active.c | 46 ---------------------------------------- - migration/migration.c | 8 ------- - migration/migration.h | 2 -- - 3 files changed, 56 deletions(-) - -diff --git a/migration/block-active.c b/migration/block-active.c -index d477cf8182..40e986aade 100644 ---- a/migration/block-active.c -+++ b/migration/block-active.c -@@ -12,51 +12,12 @@ - #include "qemu/error-report.h" - #include "trace.h" - --/* -- * Migration-only cache to remember the block layer activation status. -- * Protected by BQL. -- * -- * We need this because.. -- * -- * - Migration can fail after block devices are invalidated (during -- * switchover phase). When that happens, we need to be able to recover -- * the block drive status by re-activating them. -- * -- * - Currently bdrv_inactivate_all() is not safe to be invoked on top of -- * invalidated drives (even if bdrv_activate_all() is actually safe to be -- * called any time!). It means remembering this could help migration to -- * make sure it won't invalidate twice in a row, crashing QEMU. It can -- * happen when we migrate a PAUSED VM from host1 to host2, then migrate -- * again to host3 without starting it. TODO: a cleaner solution is to -- * allow safe invoke of bdrv_inactivate_all() at anytime, like -- * bdrv_activate_all(). -- * -- * For freshly started QEMU, the flag is initialized to TRUE reflecting the -- * scenario where QEMU owns block device ownerships. -- * -- * For incoming QEMU taking a migration stream, the flag is initialized to -- * FALSE reflecting that the incoming side doesn't own the block devices, -- * not until switchover happens. -- */ --static bool migration_block_active; -- --/* Setup the disk activation status */ --void migration_block_active_setup(bool active) --{ -- migration_block_active = active; --} -- - bool migration_block_activate(Error **errp) - { - ERRP_GUARD(); - - assert(bql_locked()); - -- if (migration_block_active) { -- trace_migration_block_activation("active-skipped"); -- return true; -- } -- - trace_migration_block_activation("active"); - - bdrv_activate_all(errp); -@@ -65,7 +26,6 @@ bool migration_block_activate(Error **errp) - return false; - } - -- migration_block_active = true; - return true; - } - -@@ -75,11 +35,6 @@ bool migration_block_inactivate(void) - - assert(bql_locked()); - -- if (!migration_block_active) { -- trace_migration_block_activation("inactive-skipped"); -- return true; -- } -- - trace_migration_block_activation("inactive"); - - ret = bdrv_inactivate_all(); -@@ -89,6 +44,5 @@ bool migration_block_inactivate(void) - return false; - } - -- migration_block_active = false; - return true; - } -diff --git a/migration/migration.c b/migration/migration.c -index 38631d1206..999d4cac54 100644 ---- a/migration/migration.c -+++ b/migration/migration.c -@@ -1875,12 +1875,6 @@ void qmp_migrate_incoming(const char *uri, bool has_channels, - return; - } - -- /* -- * Newly setup incoming QEMU. Mark the block active state to reflect -- * that the src currently owns the disks. -- */ -- migration_block_active_setup(false); -- - once = false; - } - -@@ -3825,8 +3819,6 @@ static void migration_instance_init(Object *obj) - ms->state = MIGRATION_STATUS_NONE; - ms->mbps = -1; - ms->pages_per_second = -1; -- /* Freshly started QEMU owns all the block devices */ -- migration_block_active_setup(true); - qemu_sem_init(&ms->pause_sem, 0); - qemu_mutex_init(&ms->error_mutex); - -diff --git a/migration/migration.h b/migration/migration.h -index 5b17c1344d..c38d2a37e4 100644 ---- a/migration/migration.h -+++ b/migration/migration.h -@@ -534,6 +534,4 @@ int migration_rp_wait(MigrationState *s); - */ - void migration_rp_kick(MigrationState *s); - --/* migration/block-active.c */ --void migration_block_active_setup(bool active); - #endif --- -2.48.1 - diff --git a/SPECS/qemu/kvm-nbd-server-Support-inactive-nodes.patch b/SPECS/qemu/kvm-nbd-server-Support-inactive-nodes.patch deleted file mode 100644 index c37a3411cc5..00000000000 --- a/SPECS/qemu/kvm-nbd-server-Support-inactive-nodes.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 77ec8365bf04afadee0a2dd7354deedd57606c54 Mon Sep 17 00:00:00 2001 -From: Kevin Wolf -Date: Tue, 4 Feb 2025 22:14:04 +0100 -Subject: [PATCH 20/23] nbd/server: Support inactive nodes - -RH-Author: Kevin Wolf -RH-MergeRequest: 339: QMP command for block device reactivation after migration -RH-Jira: RHEL-54296 RHEL-78397 -RH-Acked-by: Eric Blake -RH-Acked-by: Stefan Hajnoczi -RH-Commit: [19/22] 8c113dd6a862b1f4ad4e5d498f4e70a5dbfdfb32 (kmwolf/centos-qemu-kvm) - -In order to support running an NBD export on inactive nodes, we must -make sure to return errors for any operations that aren't allowed on -inactive nodes. Reads are the only operation we know we need for -inactive images, so to err on the side of caution, return errors for -everything else, even if some operations could possibly be okay. - -Signed-off-by: Kevin Wolf -Acked-by: Fabiano Rosas -Message-ID: <20250204211407.381505-14-kwolf@redhat.com> -Reviewed-by: Stefan Hajnoczi -Reviewed-by: Eric Blake -Signed-off-by: Kevin Wolf -(cherry picked from commit 2e73a17c68f4d80023dc616e596e8c1f3ea8dd75) -Signed-off-by: Kevin Wolf ---- - nbd/server.c | 17 +++++++++++++++++ - 1 file changed, 17 insertions(+) - -diff --git a/nbd/server.c b/nbd/server.c -index f64e47270c..2076fb2666 100644 ---- a/nbd/server.c -+++ b/nbd/server.c -@@ -2026,6 +2026,7 @@ static void nbd_export_delete(BlockExport *blk_exp) - const BlockExportDriver blk_exp_nbd = { - .type = BLOCK_EXPORT_TYPE_NBD, - .instance_size = sizeof(NBDExport), -+ .supports_inactive = true, - .create = nbd_export_create, - .delete = nbd_export_delete, - .request_shutdown = nbd_export_request_shutdown, -@@ -2920,6 +2921,22 @@ static coroutine_fn int nbd_handle_request(NBDClient *client, - NBDExport *exp = client->exp; - char *msg; - size_t i; -+ bool inactive; -+ -+ WITH_GRAPH_RDLOCK_GUARD() { -+ inactive = bdrv_is_inactive(blk_bs(exp->common.blk)); -+ if (inactive) { -+ switch (request->type) { -+ case NBD_CMD_READ: -+ /* These commands are allowed on inactive nodes */ -+ break; -+ default: -+ /* Return an error for the rest */ -+ return nbd_send_generic_reply(client, request, -EPERM, -+ "export is inactive", errp); -+ } -+ } -+ } - - switch (request->type) { - case NBD_CMD_CACHE: --- -2.48.1 - diff --git a/SPECS/qemu/kvm-net-Fix-announce_self.patch b/SPECS/qemu/kvm-net-Fix-announce_self.patch deleted file mode 100644 index 7c99e5c49a8..00000000000 --- a/SPECS/qemu/kvm-net-Fix-announce_self.patch +++ /dev/null @@ -1,82 +0,0 @@ -From ba42b9bf3f193bbc7f47d494bdc888e881539f4b Mon Sep 17 00:00:00 2001 -From: Laurent Vivier -Date: Fri, 17 Jan 2025 12:17:08 +0100 -Subject: [PATCH 01/23] net: Fix announce_self -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -RH-Author: Laurent Vivier -RH-MergeRequest: 338: net: Fix announce_self -RH-Jira: RHEL-73891 -RH-Acked-by: Eugenio Pérez -RH-Acked-by: Cindy Lu -RH-Commit: [1/1] dfee696c1c444af0ba2b2d3d8c7012385e84885c (lvivier/qemu-kvm-centos) - -JIRA: https://issues.redhat.com/browse/RHEL-73891 - -b9ad513e1876 ("net: Remove receive_raw()") adds an iovec entry -in qemu_deliver_packet_iov() to add the virtio-net header -in the data when QEMU_NET_PACKET_FLAG_RAW is set but forgets -to increase the number of iovec entries in the array, so -receive_iov() will only send the first entry (the virtio-net -entry, full of 0) and no data. The packet will be discarded. - -The only user of QEMU_NET_PACKET_FLAG_RAW is announce_self. - -We can see the problem with tcpdump: - -- QEMU parameters: - - .. -monitor stdio \ - -netdev bridge,id=netdev0,br=virbr0 \ - -device virtio-net,mac=9a:2b:2c:2d:2e:2f,netdev=netdev0 \ - -- HMP command: - - (qemu) announce_self - -- TCP dump: - - $ sudo tcpdump -nxi virbr0 - - without the fix: - - - - with the fix: - - ARP, Reverse Request who-is 9a:2b:2c:2d:2e:2f tell 9a:2b:2c:2d:2e:2f, length 46 - 0x0000: 0001 0800 0604 0003 9a2b 2c2d 2e2f 0000 - 0x0010: 0000 9a2b 2c2d 2e2f 0000 0000 0000 0000 - 0x0020: 0000 0000 0000 0000 0000 0000 0000 - -Reported-by: Xiaohui Li -Bug: https://issues.redhat.com/browse/RHEL-73891 -Fixes: b9ad513e1876 ("net: Remove receive_raw()") -Cc: akihiko.odaki@daynix.com -Signed-off-by: Laurent Vivier -Reviewed-by: Akihiko Odaki -Reviewed-by: Michael Tokarev -Signed-off-by: Michael Tokarev -(cherry picked from commit 84dfdcbff33fff185528501be408c25c44499f32) -Signed-off-by: Laurent Vivier ---- - net/net.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/net/net.c b/net/net.c -index fc1125111c..94f51b6e5f 100644 ---- a/net/net.c -+++ b/net/net.c -@@ -828,6 +828,7 @@ static ssize_t qemu_deliver_packet_iov(NetClientState *sender, - iov_copy[0].iov_len = nc->vnet_hdr_len; - memcpy(&iov_copy[1], iov, iovcnt * sizeof(*iov)); - iov = iov_copy; -+ iovcnt++; - } - - if (nc->info->receive_iov) { --- -2.48.1 - diff --git a/SPECS/qemu/kvm-qmp-cont-Only-activate-disks-if-migration-completed.patch b/SPECS/qemu/kvm-qmp-cont-Only-activate-disks-if-migration-completed.patch deleted file mode 100644 index db8efd2fcb2..00000000000 --- a/SPECS/qemu/kvm-qmp-cont-Only-activate-disks-if-migration-completed.patch +++ /dev/null @@ -1,73 +0,0 @@ -From a99282ca32a1fef256c1fc155ef4f43aed9e1e48 Mon Sep 17 00:00:00 2001 -From: Peter Xu -Date: Fri, 6 Dec 2024 18:08:34 -0500 -Subject: [PATCH 03/23] qmp/cont: Only activate disks if migration completed - -RH-Author: Kevin Wolf -RH-MergeRequest: 339: QMP command for block device reactivation after migration -RH-Jira: RHEL-54296 RHEL-78397 -RH-Acked-by: Eric Blake -RH-Acked-by: Stefan Hajnoczi -RH-Commit: [2/22] 942fea0b972c992c52e6a1c85172afe899e4e312 (kmwolf/centos-qemu-kvm) - -As the comment says, the activation of disks is for the case where -migration has completed, rather than when QEMU is still during -migration (RUN_STATE_INMIGRATE). - -Move the code over to reflect what the comment is describing. - -Cc: Kevin Wolf -Cc: Markus Armbruster -Signed-off-by: Peter Xu -Reviewed-by: Fabiano Rosas -Message-Id: <20241206230838.1111496-3-peterx@redhat.com> -Signed-off-by: Fabiano Rosas -(cherry picked from commit e4e5e89bbd8e731e86735d9d25b7b5f49e8f08b6) -Signed-off-by: Kevin Wolf ---- - monitor/qmp-cmds.c | 26 ++++++++++++++------------ - 1 file changed, 14 insertions(+), 12 deletions(-) - -diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c -index f84a0dc523..76f21e8af3 100644 ---- a/monitor/qmp-cmds.c -+++ b/monitor/qmp-cmds.c -@@ -96,21 +96,23 @@ void qmp_cont(Error **errp) - } - } - -- /* Continuing after completed migration. Images have been inactivated to -- * allow the destination to take control. Need to get control back now. -- * -- * If there are no inactive block nodes (e.g. because the VM was just -- * paused rather than completing a migration), bdrv_inactivate_all() simply -- * doesn't do anything. */ -- bdrv_activate_all(&local_err); -- if (local_err) { -- error_propagate(errp, local_err); -- return; -- } -- - if (runstate_check(RUN_STATE_INMIGRATE)) { - autostart = 1; - } else { -+ /* -+ * Continuing after completed migration. Images have been -+ * inactivated to allow the destination to take control. Need to -+ * get control back now. -+ * -+ * If there are no inactive block nodes (e.g. because the VM was -+ * just paused rather than completing a migration), -+ * bdrv_inactivate_all() simply doesn't do anything. -+ */ -+ bdrv_activate_all(&local_err); -+ if (local_err) { -+ error_propagate(errp, local_err); -+ return; -+ } - vm_start(); - } - } --- -2.48.1 - diff --git a/SPECS/qemu/kvm-virtio-net-Add-queues-before-loading-them.patch b/SPECS/qemu/kvm-virtio-net-Add-queues-before-loading-them.patch deleted file mode 100644 index 0474c68a04a..00000000000 --- a/SPECS/qemu/kvm-virtio-net-Add-queues-before-loading-them.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 873e57548d92eb916656b6304a780f63958aa9fe Mon Sep 17 00:00:00 2001 -From: Akihiko Odaki -Date: Tue, 22 Oct 2024 15:49:01 +0900 -Subject: [PATCH 01/10] virtio-net: Add queues before loading them -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -RH-Author: 小田喜陽彦 -RH-MergeRequest: 299: virtio-net: Add queues before loading them -RH-Jira: RHEL-69477 -RH-Acked-by: Laurent Vivier -RH-Acked-by: Jason Wang -RH-Commit: [1/1] 7bd06d5f9c0f0ce3d211204c404451d7002bb7fb (akihiko.odaki/qemu-kvm) - -Call virtio_net_set_multiqueue() to add queues before loading their -states. Otherwise the loaded queues will not have handlers and elements -in them will not be processed. - -Cc: qemu-stable@nongnu.org -Fixes: 8c49756825da ("virtio-net: Add only one queue pair when realizing") -Reported-by: Laurent Vivier -Signed-off-by: Akihiko Odaki -Acked-by: Michael S. Tsirkin -Signed-off-by: Jason Wang -(cherry picked from commit 9379ea9db3c0064fa2787db0794a23a30f7b2d2d) ---- - hw/net/virtio-net.c | 10 ++++++++++ - hw/virtio/virtio.c | 7 +++++++ - include/hw/virtio/virtio.h | 2 ++ - 3 files changed, 19 insertions(+) - -diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c -index ed33a32877..90d05f94d4 100644 ---- a/hw/net/virtio-net.c -+++ b/hw/net/virtio-net.c -@@ -3032,6 +3032,15 @@ static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue) - virtio_net_set_queue_pairs(n); - } - -+static int virtio_net_pre_load_queues(VirtIODevice *vdev) -+{ -+ virtio_net_set_multiqueue(VIRTIO_NET(vdev), -+ virtio_has_feature(vdev->guest_features, VIRTIO_NET_F_RSS) || -+ virtio_has_feature(vdev->guest_features, VIRTIO_NET_F_MQ)); -+ -+ return 0; -+} -+ - static int virtio_net_post_load_device(void *opaque, int version_id) - { - VirtIONet *n = opaque; -@@ -4010,6 +4019,7 @@ static void virtio_net_class_init(ObjectClass *klass, void *data) - vdc->guest_notifier_mask = virtio_net_guest_notifier_mask; - vdc->guest_notifier_pending = virtio_net_guest_notifier_pending; - vdc->legacy_features |= (0x1 << VIRTIO_NET_F_GSO); -+ vdc->pre_load_queues = virtio_net_pre_load_queues; - vdc->post_load = virtio_net_post_load_virtio; - vdc->vmsd = &vmstate_virtio_net_device; - vdc->primary_unplug_pending = primary_unplug_pending; -diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c -index 9e10cbc058..10f24a58dd 100644 ---- a/hw/virtio/virtio.c -+++ b/hw/virtio/virtio.c -@@ -3251,6 +3251,13 @@ virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id) - config_len--; - } - -+ if (vdc->pre_load_queues) { -+ ret = vdc->pre_load_queues(vdev); -+ if (ret) { -+ return ret; -+ } -+ } -+ - num = qemu_get_be32(f); - - if (num > VIRTIO_QUEUE_MAX) { -diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h -index 0fcbc5c0c6..953dfca27c 100644 ---- a/include/hw/virtio/virtio.h -+++ b/include/hw/virtio/virtio.h -@@ -210,6 +210,8 @@ struct VirtioDeviceClass { - void (*guest_notifier_mask)(VirtIODevice *vdev, int n, bool mask); - int (*start_ioeventfd)(VirtIODevice *vdev); - void (*stop_ioeventfd)(VirtIODevice *vdev); -+ /* Called before loading queues. Useful to add queues before loading. */ -+ int (*pre_load_queues)(VirtIODevice *vdev); - /* Saving and loading of a device; trying to deprecate save/load - * use vmsd for new devices. - */ --- -2.39.3 - diff --git a/SPECS/qemu/qemu.signatures.json b/SPECS/qemu/qemu.signatures.json index fce8eb4a2ac..5870dca555c 100644 --- a/SPECS/qemu/qemu.signatures.json +++ b/SPECS/qemu/qemu.signatures.json @@ -2,7 +2,7 @@ "Signatures": { "95-kvm-memlock.conf": "9e3aba4d5c045fd7035c79286727d45ca15fc48ac1fa665dda84bdb128b1009d", "99-qemu-guest-agent.rules": "ab34240fa8f3e8ce37ced642493184a610e187b2d9e5e15f1132975b9f076c43", - "README.tests": "aff7743296f6db8ce40c0d116a91ef2dfd50db6c52aec6b56ffd03ea320a04c2", + "README.tests": "36be35e6a9c27c50ad5c0fd0d5baa1bee33f89fc0af1045fdfa59d2fbf4c7391", "bridge.conf": "13deacdf79d5afb01c48984cc3cd5291341ca5b28d43298e804dc511ce581895", "kvm-s390x.conf": "09aee1f49c96e77c65858daf20f1095eb6bef3267470c9d8f82a22ff164c96cd", "kvm-x86.conf": "9ab7f0565e6af908350387b83ee95755250ee2e6822af787c1c2e5e9388ddcd5", @@ -10,6 +10,6 @@ "qemu-ga.sysconfig": "bd1cdb44c121a1285995c939a411b63283792c66fbd623be2497d08d9b840ad9", "qemu-guest-agent.service": "ac9e9eb8981bcf841e1b6341e4d470c1d1dba396a16f6221840cb358b974d815", "vhost.conf": "a523b6e2082ab5b913c9541295424ce7f3ff7f8161e6f21c7a8f64d23dd22313", - "qemu-9.1.0.tar.xz": "816b7022a8ba7c2ac30e2e0cf973e826f6bcc8505339603212c5ede8e94d7834" + "qemu-10.1.0.tar.xz": "e0517349b50ca73ebec2fa85b06050d5c463ca65c738833bd8fc1f15f180be51" } } diff --git a/SPECS/qemu/qemu.spec b/SPECS/qemu/qemu.spec index 9be5a24a08d..fbe85bbf8cf 100644 --- a/SPECS/qemu/qemu.spec +++ b/SPECS/qemu/qemu.spec @@ -64,6 +64,11 @@ Distribution: Azure Linux %global tools_only 0 +# QEMU 10 no longer builds 64-bit emulators on 32-bit x86 hosts. +%global have_64bit 1 +%ifarch %{ix86} +%global have_64bit 0 +%endif %global user_static 1 @@ -230,25 +235,11 @@ Distribution: Azure Linux %else %define requires_block_ssh %{nil} %endif -%define requires_audio_alsa Requires: %{name}-audio-alsa = %{evr} -%define requires_audio_oss Requires: %{name}-audio-oss = %{evr} -%if %{with pulseaudio} -%define pa_drv pa, -%define requires_audio_pa Requires: %{name}-audio-pa = %{evr} -%else +%define requires_audio_alsa %{nil} +%define requires_audio_oss %{nil} %define requires_audio_pa %{nil} -%endif -%if %{with pipewire} -%define requires_audio_pipewire Requires: %{name}-audio-pipewire = %{evr} -%else %define requires_audio_pipewire %{nil} -%endif -%if %{with sdl} -%define sdl_drv sdl, -%define requires_audio_sdl Requires: %{name}-audio-sdl = %{evr} -%else %define requires_audio_sdl %{nil} -%endif %if %{with brltty} %define requires_char_baum Requires: %{name}-char-baum = %{evr} %else @@ -272,6 +263,7 @@ Distribution: Azure Linux %define requires_device_display_virtio_gpu_pci Requires: %{name}-device-display-virtio-gpu-pci = %{evr} %define requires_device_display_virtio_gpu_ccw Requires: %{name}-device-display-virtio-gpu-ccw = %{evr} %define requires_device_display_virtio_vga Requires: %{name}-device-display-virtio-vga = %{evr} +%define requires_device_uefi_vars Requires: %{name}-device-uefi-vars = %{evr} # virtio-vga-gl requires virglrenderer AND opengl (QEMU 9.1.0+) %if %{have_virgl} && %{have_opengl} %define requires_device_display_virtio_vga_gl Requires: %{name}-device-display-virtio-vga-gl = %{evr} @@ -312,15 +304,10 @@ Distribution: Azure Linux %define requires_device_display_virtio_vga_rutabaga %{nil} %endif -%if %{have_jack} -%define jack_drv jack, -%define requires_audio_jack Requires: %{name}-audio-jack = %{evr} -%else %define requires_audio_jack %{nil} -%endif %if %{have_dbus_display} -%define requires_audio_dbus Requires: %{name}-audio-dbus = %{evr} +%define requires_audio_dbus %{nil} %define requires_ui_dbus Requires: %{name}-ui-dbus = %{evr} %else %define requires_audio_dbus %{nil} @@ -385,6 +372,7 @@ Distribution: Azure Linux %{requires_device_display_virtio_vga} \ %{requires_device_display_virtio_vga_gl} \ %{requires_device_display_virtio_vga_rutabaga} \ +%{requires_device_uefi_vars} \ %{requires_device_usb_host} \ %{requires_device_usb_redirect} \ %{requires_device_usb_smartcard} \ @@ -396,6 +384,8 @@ Distribution: Azure Linux %{obsoletes_block_gluster} \ %{obsoletes_block_rbd} \ %{obsoletes_package_virtiofsd} \ +Obsoletes: %{name}-system-cris <= %{version}-%{release} \ +Obsoletes: %{name}-system-cris-core <= %{version}-%{release} \ Obsoletes: %{name}-system-lm32 <= %{version}-%{release} \ Obsoletes: %{name}-system-lm32-core <= %{version}-%{release} \ Obsoletes: %{name}-system-moxie <= %{version}-%{release} \ @@ -431,8 +421,8 @@ Obsoletes: sgabios-bin <= 1:0.20180715git-10.fc38 Summary: QEMU is a FAST! processor emulator Name: qemu -Version: 9.1.0 -Release: 11%{?dist} +Version: 10.1.0 +Release: 1%{?dist} License: Apache-2.0 AND BSD-2-Clause AND BSD-3-Clause AND FSFAP AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-2.0-or-later WITH GCC-exception-2.0 AND LGPL-2.0-only AND LGPL-2.0-or-later AND LGPL-2.1-only AND LGPL-2.1-or-later AND MIT AND LicenseRef-Fedora-Public-Domain AND CC-BY-3.0 URL: http://www.qemu.org/ @@ -447,29 +437,7 @@ Patch4: CVE-2025-11234.patch Patch5: CVE-2025-12464.patch Patch6: CVE-2024-8354.patch Patch7: CVE-2025-14876.patch -Patch8: kvm-migration-Ensure-vmstate_save-sets-errp.patch -Patch9: kvm-virtio-net-Add-queues-before-loading-them.patch -Patch10: kvm-net-Fix-announce_self.patch -Patch11: kvm-migration-Add-helper-to-get-target-runstate.patch -Patch12: kvm-qmp-cont-Only-activate-disks-if-migration-completed.patch -Patch13: kvm-migration-block-Make-late-block-active-the-default.patch -Patch14: kvm-migration-block-Apply-late-block-active-behavior-to-.patch -Patch15: kvm-migration-block-Fix-possible-race-with-block_inactiv.patch -Patch16: kvm-migration-block-Rewrite-disk-activation.patch -Patch17: kvm-block-Add-active-field-to-BlockDeviceInfo.patch -Patch18: kvm-block-Allow-inactivating-already-inactive-nodes.patch -Patch19: kvm-block-Inactivate-external-snapshot-overlays-when-nec.patch -Patch20: kvm-migration-block-active-Remove-global-active-flag.patch -Patch21: kvm-block-Don-t-attach-inactive-child-to-active-node.patch -Patch22: kvm-block-Fix-crash-on-block_resize-on-inactive-node.patch -Patch23: kvm-block-Add-option-to-create-inactive-nodes.patch -Patch24: kvm-block-Add-blockdev-set-active-QMP-command.patch -Patch25: kvm-block-Support-inactive-nodes-in-blk_insert_bs.patch -Patch26: kvm-block-export-Don-t-ignore-image-activation-error-in-.patch Patch27: kvm-block-Drain-nodes-before-inactivating-them.patch -Patch28: kvm-block-export-Add-option-to-allow-export-of-inactive-.patch -Patch29: kvm-nbd-server-Support-inactive-nodes.patch -Patch30: kvm-migration-Fix-UAF-for-incoming-migration-on-Migratio.patch Patch31: CVE-2026-3195.patch Patch32: CVE-2026-48914.patch Patch33: CVE-2026-3196.patch @@ -683,12 +651,15 @@ BuildRequires: pcre2-devel-static # Requires for the Fedora 'qemu' metapackage Requires: %{name}-user = %{version}-%{release} +%if %{have_64bit} Requires: %{name}-system-aarch64 = %{version}-%{release} Requires: %{name}-system-alpha = %{version}-%{release} +Requires: %{name}-system-hppa = %{version}-%{release} +Requires: %{name}-system-loongarch64 = %{version}-%{release} +Requires: %{name}-system-s390x = %{version}-%{release} +%endif Requires: %{name}-system-arm = %{version}-%{release} Requires: %{name}-system-avr = %{version}-%{release} -Requires: %{name}-system-cris = %{version}-%{release} -Requires: %{name}-system-loongarch64 = %{version}-%{release} Requires: %{name}-system-m68k = %{version}-%{release} Requires: %{name}-system-microblaze = %{version}-%{release} Requires: %{name}-system-mips = %{version}-%{release} @@ -698,7 +669,6 @@ Requires: %{name}-system-ppc = %{version}-%{release} %endif Requires: %{name}-system-riscv = %{version}-%{release} Requires: %{name}-system-rx = %{version}-%{release} -Requires: %{name}-system-s390x = %{version}-%{release} Requires: %{name}-system-sh4 = %{version}-%{release} %if %{with sparc_support} Requires: %{name}-system-sparc = %{version}-%{release} @@ -727,6 +697,18 @@ Requires(post): systemd-units Requires(preun): systemd-units Requires(postun): systemd-units %{obsoletes_some_modules} +%if !%{have_64bit} +Obsoletes: %{name}-system-aarch64 <= %{evr} +Obsoletes: %{name}-system-aarch64-core <= %{evr} +Obsoletes: %{name}-system-alpha <= %{evr} +Obsoletes: %{name}-system-alpha-core <= %{evr} +Obsoletes: %{name}-system-hppa <= %{evr} +Obsoletes: %{name}-system-hppa-core <= %{evr} +Obsoletes: %{name}-system-loongarch64 <= %{evr} +Obsoletes: %{name}-system-loongarch64-core <= %{evr} +Obsoletes: %{name}-system-s390x <= %{evr} +Obsoletes: %{name}-system-s390x-core <= %{evr} +%endif %if %{?azl} # AzLinux specific %ifarch x86_64 @@ -793,8 +775,7 @@ Requires: %{name} = %{version}-%{release} The %{name}-tests rpm contains tests that can be used to verify the functionality of the installed %{name} package -Install this package if you want access to the avocado_qemu -tests, or qemu-iotests. +Install this package if you want access to qemu-iotests. %if %{have_libblkio} @@ -895,58 +876,6 @@ Install this package if you want to access remote NFS storage. %endif -%package audio-alsa -Summary: QEMU ALSA audio driver -Requires: %{name}-common%{?_isa} = %{version}-%{release} -%description audio-alsa -This package provides the additional ALSA audio driver for QEMU. - -%if %{have_dbus_display} -%package audio-dbus -Summary: QEMU D-Bus audio driver -Requires: %{name}-common%{?_isa} = %{version}-%{release} -%description audio-dbus -This package provides the additional D-Bus audio driver for QEMU. -%endif - -%package audio-oss -Summary: QEMU OSS audio driver -Requires: %{name}-common%{?_isa} = %{version}-%{release} -%description audio-oss -This package provides the additional OSS audio driver for QEMU. - -%if %{with pulseaudio} -%package audio-pa -Summary: QEMU PulseAudio audio driver -Requires: %{name}-common%{?_isa} = %{version}-%{release} -%description audio-pa -This package provides the additional PulseAudio audio driver for QEMU. -%endif - -%if %{with pipewire} -%package audio-pipewire -Summary: QEMU Pipewire audio driver -Requires: %{name}-common%{?_isa} = %{version}-%{release} -%description audio-pipewire -This package provides the additional Pipewire audio driver for QEMU. -%endif - -%if %{with sdl} -%package audio-sdl -Summary: QEMU SDL audio driver -Requires: %{name}-common%{?_isa} = %{version}-%{release} -%description audio-sdl -This package provides the additional SDL audio driver for QEMU. -%endif - -%if %{have_jack} -%package audio-jack -Summary: QEMU Jack audio driver -Requires: %{name}-common%{?_isa} = %{version}-%{release} -%description audio-jack -This package provides the additional Jack audio driver for QEMU. -%endif - %if %{have_dbus_display} %package ui-dbus Summary: QEMU D-Bus UI driver @@ -1072,6 +1001,12 @@ Requires: %{name}-common%{?_isa} = %{version}-%{release} This package provides the virtio-vga-rutabaga display device for QEMU. %endif +%package device-uefi-vars +Summary: QEMU UEFI variable service +Requires: %{name}-common%{?_isa} = %{version}-%{release} +%description device-uefi-vars +This package provides the UEFI variable service for QEMU. + %package device-usb-host Summary: QEMU usb host device @@ -1196,24 +1131,32 @@ Requires(postun): systemd-units # introduce conflicts to not install both binfmt rules. Conflicts: qemu-user-binfmt Provides: qemu-user-binfmt +%if %{have_64bit} Requires: qemu-user-static-aarch64 Requires: qemu-user-static-alpha -Requires: qemu-user-static-arm -Requires: qemu-user-static-cris -Requires: qemu-user-static-hexagon Requires: qemu-user-static-hppa Requires: qemu-user-static-loongarch64 +Requires: qemu-user-static-s390x +%else +Obsoletes: %{name}-user-static-aarch64 <= %{evr} +Obsoletes: %{name}-user-static-alpha <= %{evr} +Obsoletes: %{name}-user-static-hppa <= %{evr} +Obsoletes: %{name}-user-static-loongarch64 <= %{evr} +Obsoletes: %{name}-user-static-s390x <= %{evr} +%endif +Requires: qemu-user-static-arm +Requires: qemu-user-static-hexagon Requires: qemu-user-static-m68k Requires: qemu-user-static-microblaze Requires: qemu-user-static-mips Requires: qemu-user-static-or1k Requires: qemu-user-static-ppc Requires: qemu-user-static-riscv -Requires: qemu-user-static-s390x Requires: qemu-user-static-sh4 Requires: qemu-user-static-sparc Requires: qemu-user-static-x86 Requires: qemu-user-static-xtensa +Obsoletes: qemu-user-static-cris <= %{evr} %description user-static This package provides the user mode emulation of qemu targets built as @@ -1237,12 +1180,6 @@ Summary: QEMU user mode emulation of arm qemu targets static build This package provides the arm user mode emulation of qemu targets built as static binaries -%package user-static-cris -Summary: QEMU user mode emulation of cris qemu targets static build -%description user-static-cris -This package provides the cris user mode emulation of qemu targets built as -static binaries - %package user-static-hexagon Summary: QEMU user mode emulation of hexagon qemu targets static build %description user-static-hexagon @@ -1393,20 +1330,6 @@ Requires: %{name}-common = %{version}-%{release} This package provides the QEMU system emulator for AVR systems. -%package system-cris -Summary: QEMU system emulator for CRIS -Requires: %{name}-system-cris-core = %{version}-%{release} -%{requires_all_modules} -%description system-cris -This package provides the system emulator for CRIS systems. - -%package system-cris-core -Summary: QEMU system emulator for CRIS -Requires: %{name}-common = %{version}-%{release} -%description system-cris-core -This package provides the system emulator for CRIS boards. - - %package system-hppa Summary: QEMU system emulator for HPPA Requires: %{name}-system-hppa-core = %{version}-%{release} @@ -1645,13 +1568,12 @@ mkdir -p %{static_builddir} %build %define disable_everything \\\ - --audio-drv-list= \\\ + --audio-drv-list= \\\ --disable-af-xdp \\\ --disable-alsa \\\ + --disable-asan \\\ --disable-attr \\\ --disable-auth-pam \\\ - --disable-avx2 \\\ - --disable-avx512bw \\\ --disable-blkio \\\ --disable-block-drv-whitelist-in-tools \\\ --disable-bochs \\\ @@ -1675,6 +1597,7 @@ mkdir -p %{static_builddir} --disable-debug-graph-lock \\\ --disable-debug-info \\\ --disable-debug-mutex \\\ + --disable-debug-remap \\\ --disable-debug-tcg \\\ --disable-dmg \\\ --disable-docs \\\ @@ -1695,9 +1618,11 @@ mkdir -p %{static_builddir} --disable-hv-balloon \\\ --disable-hvf \\\ --disable-iconv \\\ + --disable-igvm \\\ --disable-jack \\\ --disable-kvm \\\ --disable-l2tpv3 \\\ + --disable-libcbor \\\ --disable-libdaxctl \\\ --disable-libdw \\\ --disable-libkeyutils \\\ @@ -1727,21 +1652,24 @@ mkdir -p %{static_builddir} --disable-oss \\\ --disable-pa \\\ --disable-parallels \\\ + --disable-passt \\\ --disable-pie \\\ --disable-pipewire \\\ --disable-pixman \\\ --disable-plugins \\\ + --disable-pvg \\\ --disable-qcow1 \\\ --disable-qed \\\ --disable-qom-cast-debug \\\ + --disable-qpl \\\ --disable-rbd \\\ --disable-rdma \\\ --disable-relocatable \\\ --disable-replication \\\ + --disable-rust \\\ --disable-rutabaga-gfx \\\ --disable-rng-none \\\ --disable-safe-stack \\\ - --disable-sanitizers \\\ --disable-sdl \\\ --disable-sdl-image \\\ --disable-seccomp \\\ @@ -1754,15 +1682,19 @@ mkdir -p %{static_builddir} --disable-sparse \\\ --disable-spice \\\ --disable-spice-protocol \\\ + --disable-strict-rust-lints \\\ --disable-strip \\\ --disable-system \\\ --disable-tcg \\\ --disable-tools \\\ --disable-tpm \\\ --disable-tsan \\\ + --disable-uadk \\\ --disable-u2f \\\ + --disable-ubsan \\\ --disable-usb-redir \\\ --disable-user \\\ + --disable-valgrind \\\ --disable-vpc \\\ --disable-vde \\\ --disable-vdi \\\ @@ -1825,8 +1757,6 @@ run_configure() { echo "===" } -# --audio-drv-list=%{?pa_drv}%{?sdl_drv}alsa,%{?jack_drv}oss Same as CBLM 2.0 - pushd %{qemu_kvm_build} run_configure \ %if %{defined target_list} @@ -1841,12 +1771,8 @@ run_configure \ %ifarch x86_64 --enable-af-xdp \ %endif - --enable-alsa \ + --disable-alsa \ --enable-attr \ -%ifarch %{ix86} x86_64 - --enable-avx2 \ - --enable-avx512bw \ -%endif %if %{have_libblkio} --enable-blkio \ %endif @@ -1872,9 +1798,7 @@ run_configure \ --enable-tools \ --enable-guest-agent \ --enable-iconv \ -%if %{have_jack} - --enable-jack \ -%endif + --disable-jack \ --enable-kvm \ --enable-l2tpv3 \ --enable-libiscsi \ @@ -1900,14 +1824,10 @@ run_configure \ %if %{have_opengl} --enable-opengl \ %endif - --enable-oss \ -%if %{with pulseaudio} - --enable-pa \ -%endif + --disable-oss \ + --disable-pa \ --enable-pie \ -%if %{with pipewire} - --enable-pipewire \ -%endif + --disable-pipewire \ --enable-pixman \ %if %{have_block_rbd} --enable-rbd \ @@ -1941,7 +1861,7 @@ run_configure \ --enable-xkbcommon \ \ \ - --audio-drv-list=%{?pa_drv}%{?sdl_drv}alsa,%{?jack_drv}oss \ + --audio-drv-list= \ --target-list-exclude=moxie-softmmu \ --with-default-devices \ --enable-auth-pam \ @@ -1981,12 +1901,8 @@ run_configure \ %if %{have_rutabaga_gfx} --enable-rutabaga-gfx \ %endif -%if %{with sdl} - --enable-sdl \ -%if %{have_sdl_image} - --enable-sdl-image \ -%endif -%endif + --disable-sdl \ + --disable-sdl-image \ %if %{have_libcacard} --enable-smartcard \ %endif @@ -2001,7 +1917,6 @@ run_configure \ %endif --enable-vhdx \ --enable-virtfs \ - --enable-virtfs-proxy-helper \ --enable-vpc \ --enable-vnc-jpeg \ --enable-vte \ @@ -2131,14 +2046,10 @@ mkdir -p %{buildroot}%{_datadir}/%{name}/vhost-user # Create new directories and put them all under tests-src mkdir -p %{buildroot}%{testsdir}/python mkdir -p %{buildroot}%{testsdir}/tests -mkdir -p %{buildroot}%{testsdir}/tests/avocado mkdir -p %{buildroot}%{testsdir}/tests/qemu-iotests mkdir -p %{buildroot}%{testsdir}/scripts/qmp -# Install avocado_qemu tests -cp -R %{qemu_kvm_build}/tests/avocado/* %{buildroot}%{testsdir}/tests/avocado/ - -# Install qemu.py and qmp/ scripts required to run avocado_qemu tests +# Install qemu.py and qmp/ scripts used by the packaged tests cp -R %{qemu_kvm_build}/python/qemu %{buildroot}%{testsdir}/python cp -R %{qemu_kvm_build}/scripts/qmp/* %{buildroot}%{testsdir}/scripts/qmp install -p -m 0755 tests/Makefile.include %{buildroot}%{testsdir}/tests/ @@ -2184,8 +2095,9 @@ rm -rf %{buildroot}%{_datadir}/%{name}/firmware # Remove datadir files packaged with excluded targets for AzLinux %if %{without ppc_support} -rm -rf %{buildroot}%{_datadir}/%{name}/bamboo.dtb -rm -rf %{buildroot}%{_datadir}/%{name}/canyonlands.dtb +rm -rf %{buildroot}%{_datadir}/%{name}/dtb/bamboo.dtb +rm -rf %{buildroot}%{_datadir}/%{name}/dtb/canyonlands.dtb +rm -rf %{buildroot}%{_datadir}/%{name}/pnv-pnor.bin rm -rf %{buildroot}%{_datadir}/%{name}/qemu_vga.ndrv rm -rf %{buildroot}%{_datadir}/%{name}/skiboot.lid rm -rf %{buildroot}%{_datadir}/%{name}/u-boot.e500 @@ -2263,8 +2175,6 @@ ln -sf qemu-system-x86_64 %{buildroot}%{_bindir}/qemu-kvm # Needed until CBL-Mariner starts cross-compiling 'ipxe', 'seabios' and 'sgabios' for other architectures. rm -rf %{buildroot}%{_bindir}/qemu-system-i386 rm -rf %{buildroot}%{_bindir}/qemu-system-x86_64 -rm -rf %{buildroot}%{_libdir}/%{name}/accel-tcg-i386.so -rm -rf %{buildroot}%{_libdir}/%{name}/accel-tcg-x86_64.so rm -rf %{buildroot}%{_datadir}/systemtap/tapset/qemu-system-i386*.stp rm -rf %{buildroot}%{_datadir}/systemtap/tapset/qemu-system-x86_64*.stp %if ! %{azl} @@ -2320,6 +2230,31 @@ for regularfmt in %{binfmt_dir}/*; do rm -rf %{static_buildroot} # endif user_static %endif + +%if !%{have_64bit} +rm -f \ +%{buildroot}%{_exec_prefix}/lib/binfmt.d/qemu-aarch64-static.conf \ +%{buildroot}%{_exec_prefix}/lib/binfmt.d/qemu-aarch64_be-static.conf \ +%{buildroot}%{_exec_prefix}/lib/binfmt.d/qemu-alpha-static.conf \ +%{buildroot}%{_exec_prefix}/lib/binfmt.d/qemu-hppa-static.conf \ +%{buildroot}%{_exec_prefix}/lib/binfmt.d/qemu-loongarch64-static.conf \ +%{buildroot}%{_exec_prefix}/lib/binfmt.d/qemu-mips64-static.conf \ +%{buildroot}%{_exec_prefix}/lib/binfmt.d/qemu-mips64el-static.conf \ +%{buildroot}%{_exec_prefix}/lib/binfmt.d/qemu-mipsn32-static.conf \ +%{buildroot}%{_exec_prefix}/lib/binfmt.d/qemu-mipsn32el-static.conf \ +%{buildroot}%{_exec_prefix}/lib/binfmt.d/qemu-ppc64-static.conf \ +%{buildroot}%{_exec_prefix}/lib/binfmt.d/qemu-ppc64le-static.conf \ +%{buildroot}%{_exec_prefix}/lib/binfmt.d/qemu-riscv64-static.conf \ +%{buildroot}%{_exec_prefix}/lib/binfmt.d/qemu-s390x-static.conf \ +%{buildroot}%{_exec_prefix}/lib/binfmt.d/qemu-sparc32plus-static.conf \ +%{buildroot}%{_exec_prefix}/lib/binfmt.d/qemu-sparc64-static.conf \ +%{buildroot}%{_exec_prefix}/lib/binfmt.d/qemu-x86_64-static.conf \ +%{buildroot}%{_datadir}/%{name}/palcode-clipper \ +%{buildroot}%{_datadir}/%{name}/hppa-firmware.img \ +%{buildroot}%{_datadir}/%{name}/hppa-firmware64.img \ +%{buildroot}%{_datadir}/%{name}/s390-ccw.img \ +%{buildroot}%{_datadir}/%{name}/s390-netboot.img +%endif # end Fedora specific # endif !tools_only %endif @@ -2430,15 +2365,6 @@ if [ ! -f %{setbinfmtonce} ];then %try_run_systemd_binfmt fi -%post user-static-cris -if [ ! -f %{setbinfmtonce} ];then - %try_run_systemd_binfmt -fi -%postun user-static-cris -if [ ! -f %{setbinfmtonce} ];then - %try_run_systemd_binfmt -fi - %post user-static-hexagon if [ ! -f %{setbinfmtonce} ];then %try_run_systemd_binfmt @@ -2676,10 +2602,6 @@ fi # Fedora specific %{_datadir}/applications/qemu.desktop %exclude %{_datadir}/%{name}/qemu-nsis.bmp -%{_libexecdir}/virtfs-proxy-helper -%if ! %{azl} -%{_mandir}/man1/virtfs-proxy-helper.1* -%endif %files tests @@ -2719,32 +2641,6 @@ fi %{_libdir}/%{name}/block-nfs.so %endif -%files audio-alsa -%{_libdir}/%{name}/audio-alsa.so -%if %{have_dbus_display} -%files audio-dbus -%{_libdir}/%{name}/audio-dbus.so -%endif -%files audio-oss -%{_libdir}/%{name}/audio-oss.so -%if %{with pulseaudio} -%files audio-pa -%{_libdir}/%{name}/audio-pa.so -%endif -%if %{with pipewire} -%files audio-pipewire -%{_libdir}/%{name}/audio-pipewire.so -%endif -%if %{with sdl} -%files audio-sdl -%{_libdir}/%{name}/audio-sdl.so -%endif -%if %{have_jack} -%files audio-jack -%{_libdir}/%{name}/audio-jack.so -%endif - - %if %{have_dbus_display} %files ui-dbus %{_libdir}/%{name}/ui-dbus.so @@ -2802,6 +2698,8 @@ fi %files device-display-virtio-vga-rutabaga %{_libdir}/%{name}/hw-display-virtio-vga-rutabaga.so %endif +%files device-uefi-vars +%{_libdir}/%{name}/hw-uefi-vars.so %files device-usb-host %{_libdir}/%{name}/hw-usb-host.so %files device-usb-redirect @@ -2844,44 +2742,58 @@ fi %files user %{_bindir}/qemu-i386 +%if %{have_64bit} %{_bindir}/qemu-x86_64 %{_bindir}/qemu-aarch64 %{_bindir}/qemu-aarch64_be %{_bindir}/qemu-alpha +%endif %{_bindir}/qemu-arm %{_bindir}/qemu-armeb -%{_bindir}/qemu-cris +%if %{have_64bit} %{_bindir}/qemu-hppa +%endif %{_bindir}/qemu-hexagon +%if %{have_64bit} %{_bindir}/qemu-loongarch64 +%endif %{_bindir}/qemu-m68k %{_bindir}/qemu-microblaze %{_bindir}/qemu-microblazeel %{_bindir}/qemu-mips %{_bindir}/qemu-mipsel +%if %{have_64bit} %{_bindir}/qemu-mips64 %{_bindir}/qemu-mips64el %{_bindir}/qemu-mipsn32 %{_bindir}/qemu-mipsn32el +%endif %{_bindir}/qemu-or1k %if %{with ppc_support} %{_bindir}/qemu-ppc +%if %{have_64bit} %{_bindir}/qemu-ppc64 %{_bindir}/qemu-ppc64le %endif +%endif %{_bindir}/qemu-riscv32 +%if %{have_64bit} %{_bindir}/qemu-riscv64 %{_bindir}/qemu-s390x +%endif %{_bindir}/qemu-sh4 %{_bindir}/qemu-sh4eb %if %{with sparc_support} %{_bindir}/qemu-sparc +%if %{have_64bit} %{_bindir}/qemu-sparc32plus %{_bindir}/qemu-sparc64 %endif +%endif %{_bindir}/qemu-xtensa %{_bindir}/qemu-xtensaeb +%if %{have_64bit} %{_datadir}/systemtap/tapset/qemu-aarch64.stp %{_datadir}/systemtap/tapset/qemu-aarch64-log.stp %{_datadir}/systemtap/tapset/qemu-aarch64-simpletrace.stp @@ -2891,27 +2803,29 @@ fi %{_datadir}/systemtap/tapset/qemu-alpha.stp %{_datadir}/systemtap/tapset/qemu-alpha-log.stp %{_datadir}/systemtap/tapset/qemu-alpha-simpletrace.stp +%endif %{_datadir}/systemtap/tapset/qemu-armeb.stp %{_datadir}/systemtap/tapset/qemu-armeb-log.stp %{_datadir}/systemtap/tapset/qemu-armeb-simpletrace.stp %{_datadir}/systemtap/tapset/qemu-arm.stp %{_datadir}/systemtap/tapset/qemu-arm-log.stp %{_datadir}/systemtap/tapset/qemu-arm-simpletrace.stp -%{_datadir}/systemtap/tapset/qemu-cris.stp -%{_datadir}/systemtap/tapset/qemu-cris-log.stp -%{_datadir}/systemtap/tapset/qemu-cris-simpletrace.stp %{_datadir}/systemtap/tapset/qemu-hexagon.stp %{_datadir}/systemtap/tapset/qemu-hexagon-log.stp %{_datadir}/systemtap/tapset/qemu-hexagon-simpletrace.stp +%if %{have_64bit} %{_datadir}/systemtap/tapset/qemu-hppa.stp %{_datadir}/systemtap/tapset/qemu-hppa-log.stp %{_datadir}/systemtap/tapset/qemu-hppa-simpletrace.stp +%endif %{_datadir}/systemtap/tapset/qemu-i386.stp %{_datadir}/systemtap/tapset/qemu-i386-log.stp %{_datadir}/systemtap/tapset/qemu-i386-simpletrace.stp +%if %{have_64bit} %{_datadir}/systemtap/tapset/qemu-loongarch64.stp %{_datadir}/systemtap/tapset/qemu-loongarch64-log.stp %{_datadir}/systemtap/tapset/qemu-loongarch64-simpletrace.stp +%endif %{_datadir}/systemtap/tapset/qemu-m68k.stp %{_datadir}/systemtap/tapset/qemu-m68k-log.stp %{_datadir}/systemtap/tapset/qemu-m68k-simpletrace.stp @@ -2924,21 +2838,25 @@ fi %{_datadir}/systemtap/tapset/qemu-mips.stp %{_datadir}/systemtap/tapset/qemu-mips-log.stp %{_datadir}/systemtap/tapset/qemu-mips-simpletrace.stp +%if %{have_64bit} %{_datadir}/systemtap/tapset/qemu-mips64el.stp %{_datadir}/systemtap/tapset/qemu-mips64el-log.stp %{_datadir}/systemtap/tapset/qemu-mips64el-simpletrace.stp %{_datadir}/systemtap/tapset/qemu-mips64.stp %{_datadir}/systemtap/tapset/qemu-mips64-log.stp %{_datadir}/systemtap/tapset/qemu-mips64-simpletrace.stp +%endif %{_datadir}/systemtap/tapset/qemu-mipsel.stp %{_datadir}/systemtap/tapset/qemu-mipsel-log.stp %{_datadir}/systemtap/tapset/qemu-mipsel-simpletrace.stp +%if %{have_64bit} %{_datadir}/systemtap/tapset/qemu-mipsn32.stp %{_datadir}/systemtap/tapset/qemu-mipsn32-log.stp %{_datadir}/systemtap/tapset/qemu-mipsn32-simpletrace.stp %{_datadir}/systemtap/tapset/qemu-mipsn32el.stp %{_datadir}/systemtap/tapset/qemu-mipsn32el-log.stp %{_datadir}/systemtap/tapset/qemu-mipsn32el-simpletrace.stp +%endif %{_datadir}/systemtap/tapset/qemu-or1k.stp %{_datadir}/systemtap/tapset/qemu-or1k-log.stp %{_datadir}/systemtap/tapset/qemu-or1k-simpletrace.stp @@ -2946,6 +2864,7 @@ fi %{_datadir}/systemtap/tapset/qemu-ppc.stp %{_datadir}/systemtap/tapset/qemu-ppc-log.stp %{_datadir}/systemtap/tapset/qemu-ppc-simpletrace.stp +%if %{have_64bit} %{_datadir}/systemtap/tapset/qemu-ppc64.stp %{_datadir}/systemtap/tapset/qemu-ppc64-log.stp %{_datadir}/systemtap/tapset/qemu-ppc64-simpletrace.stp @@ -2953,15 +2872,18 @@ fi %{_datadir}/systemtap/tapset/qemu-ppc64le-log.stp %{_datadir}/systemtap/tapset/qemu-ppc64le-simpletrace.stp %endif +%endif %{_datadir}/systemtap/tapset/qemu-riscv32.stp %{_datadir}/systemtap/tapset/qemu-riscv32-log.stp %{_datadir}/systemtap/tapset/qemu-riscv32-simpletrace.stp +%if %{have_64bit} %{_datadir}/systemtap/tapset/qemu-riscv64.stp %{_datadir}/systemtap/tapset/qemu-riscv64-log.stp %{_datadir}/systemtap/tapset/qemu-riscv64-simpletrace.stp %{_datadir}/systemtap/tapset/qemu-s390x.stp %{_datadir}/systemtap/tapset/qemu-s390x-log.stp %{_datadir}/systemtap/tapset/qemu-s390x-simpletrace.stp +%endif %{_datadir}/systemtap/tapset/qemu-sh4.stp %{_datadir}/systemtap/tapset/qemu-sh4-log.stp %{_datadir}/systemtap/tapset/qemu-sh4-simpletrace.stp @@ -2972,6 +2894,7 @@ fi %{_datadir}/systemtap/tapset/qemu-sparc.stp %{_datadir}/systemtap/tapset/qemu-sparc-log.stp %{_datadir}/systemtap/tapset/qemu-sparc-simpletrace.stp +%if %{have_64bit} %{_datadir}/systemtap/tapset/qemu-sparc32plus.stp %{_datadir}/systemtap/tapset/qemu-sparc32plus-log.stp %{_datadir}/systemtap/tapset/qemu-sparc32plus-simpletrace.stp @@ -2979,9 +2902,12 @@ fi %{_datadir}/systemtap/tapset/qemu-sparc64-log.stp %{_datadir}/systemtap/tapset/qemu-sparc64-simpletrace.stp %endif +%endif +%if %{have_64bit} %{_datadir}/systemtap/tapset/qemu-x86_64.stp %{_datadir}/systemtap/tapset/qemu-x86_64-log.stp %{_datadir}/systemtap/tapset/qemu-x86_64-simpletrace.stp +%endif %{_datadir}/systemtap/tapset/qemu-xtensa.stp %{_datadir}/systemtap/tapset/qemu-xtensa-log.stp %{_datadir}/systemtap/tapset/qemu-xtensa-simpletrace.stp @@ -2997,6 +2923,7 @@ fi %files user-static %license COPYING COPYING.LIB LICENSE +%if %{have_64bit} %files user-static-aarch64 %{_bindir}/qemu-aarch64-static %{_bindir}/qemu-aarch64_be-static @@ -3010,13 +2937,16 @@ fi %{_exec_prefix}/lib/binfmt.d/qemu-aarch64-static.conf %endif %{_exec_prefix}/lib/binfmt.d/qemu-aarch64_be-static.conf +%endif +%if %{have_64bit} %files user-static-alpha %{_bindir}/qemu-alpha-static %{_datadir}/systemtap/tapset/qemu-alpha-log-static.stp %{_datadir}/systemtap/tapset/qemu-alpha-simpletrace-static.stp %{_datadir}/systemtap/tapset/qemu-alpha-static.stp %{_exec_prefix}/lib/binfmt.d/qemu-alpha-static.conf +%endif %files user-static-arm %{_bindir}/qemu-arm-static @@ -3032,12 +2962,6 @@ fi %endif %{_exec_prefix}/lib/binfmt.d/qemu-armeb-static.conf -%files user-static-cris -%{_bindir}/qemu-cris-static -%{_datadir}/systemtap/tapset/qemu-cris-log-static.stp -%{_datadir}/systemtap/tapset/qemu-cris-simpletrace-static.stp -%{_datadir}/systemtap/tapset/qemu-cris-static.stp - %files user-static-hexagon %{_bindir}/qemu-hexagon-static %{_datadir}/systemtap/tapset/qemu-hexagon-log-static.stp @@ -3045,19 +2969,23 @@ fi %{_datadir}/systemtap/tapset/qemu-hexagon-static.stp %{_exec_prefix}/lib/binfmt.d/qemu-hexagon-static.conf +%if %{have_64bit} %files user-static-hppa %{_bindir}/qemu-hppa-static %{_datadir}/systemtap/tapset/qemu-hppa-log-static.stp %{_datadir}/systemtap/tapset/qemu-hppa-simpletrace-static.stp %{_datadir}/systemtap/tapset/qemu-hppa-static.stp %{_exec_prefix}/lib/binfmt.d/qemu-hppa-static.conf +%endif +%if %{have_64bit} %files user-static-loongarch64 %{_bindir}/qemu-loongarch64-static %{_datadir}/systemtap/tapset/qemu-loongarch64-log-static.stp %{_datadir}/systemtap/tapset/qemu-loongarch64-simpletrace-static.stp %{_datadir}/systemtap/tapset/qemu-loongarch64-static.stp %{_exec_prefix}/lib/binfmt.d/qemu-loongarch64-static.conf +%endif %files user-static-m68k %{_bindir}/qemu-m68k-static @@ -3080,35 +3008,47 @@ fi %files user-static-mips %{_bindir}/qemu-mips-static +%if %{have_64bit} %{_bindir}/qemu-mips64-static %{_bindir}/qemu-mips64el-static +%endif %{_bindir}/qemu-mipsel-static +%if %{have_64bit} %{_bindir}/qemu-mipsn32-static %{_bindir}/qemu-mipsn32el-static +%endif %{_datadir}/systemtap/tapset/qemu-mips-log-static.stp %{_datadir}/systemtap/tapset/qemu-mips-simpletrace-static.stp %{_datadir}/systemtap/tapset/qemu-mips-static.stp +%if %{have_64bit} %{_datadir}/systemtap/tapset/qemu-mips64-log-static.stp %{_datadir}/systemtap/tapset/qemu-mips64-simpletrace-static.stp %{_datadir}/systemtap/tapset/qemu-mips64-static.stp %{_datadir}/systemtap/tapset/qemu-mips64el-log-static.stp %{_datadir}/systemtap/tapset/qemu-mips64el-simpletrace-static.stp %{_datadir}/systemtap/tapset/qemu-mips64el-static.stp +%endif %{_datadir}/systemtap/tapset/qemu-mipsel-log-static.stp %{_datadir}/systemtap/tapset/qemu-mipsel-simpletrace-static.stp %{_datadir}/systemtap/tapset/qemu-mipsel-static.stp +%if %{have_64bit} %{_datadir}/systemtap/tapset/qemu-mipsn32-log-static.stp %{_datadir}/systemtap/tapset/qemu-mipsn32-simpletrace-static.stp %{_datadir}/systemtap/tapset/qemu-mipsn32-static.stp %{_datadir}/systemtap/tapset/qemu-mipsn32el-log-static.stp %{_datadir}/systemtap/tapset/qemu-mipsn32el-simpletrace-static.stp %{_datadir}/systemtap/tapset/qemu-mipsn32el-static.stp +%endif %{_exec_prefix}/lib/binfmt.d/qemu-mips-static.conf +%if %{have_64bit} %{_exec_prefix}/lib/binfmt.d/qemu-mips64-static.conf %{_exec_prefix}/lib/binfmt.d/qemu-mips64el-static.conf +%endif %{_exec_prefix}/lib/binfmt.d/qemu-mipsel-static.conf +%if %{have_64bit} %{_exec_prefix}/lib/binfmt.d/qemu-mipsn32-static.conf %{_exec_prefix}/lib/binfmt.d/qemu-mipsn32el-static.conf +%endif %files user-static-or1k %{_bindir}/qemu-or1k-static @@ -3119,29 +3059,38 @@ fi %files user-static-ppc %{_bindir}/qemu-ppc-static +%if %{have_64bit} %{_bindir}/qemu-ppc64-static %{_bindir}/qemu-ppc64le-static +%endif %{_datadir}/systemtap/tapset/qemu-ppc-log-static.stp %{_datadir}/systemtap/tapset/qemu-ppc-simpletrace-static.stp %{_datadir}/systemtap/tapset/qemu-ppc-static.stp +%if %{have_64bit} %{_datadir}/systemtap/tapset/qemu-ppc64-log-static.stp %{_datadir}/systemtap/tapset/qemu-ppc64-simpletrace-static.stp %{_datadir}/systemtap/tapset/qemu-ppc64-static.stp %{_datadir}/systemtap/tapset/qemu-ppc64le-log-static.stp %{_datadir}/systemtap/tapset/qemu-ppc64le-simpletrace-static.stp %{_datadir}/systemtap/tapset/qemu-ppc64le-static.stp +%endif %{_exec_prefix}/lib/binfmt.d/qemu-ppc-static.conf +%if %{have_64bit} %{_exec_prefix}/lib/binfmt.d/qemu-ppc64-static.conf %ifnarch ppc64le %{_exec_prefix}/lib/binfmt.d/qemu-ppc64le-static.conf %endif +%endif %files user-static-riscv %{_bindir}/qemu-riscv32-static +%if %{have_64bit} %{_bindir}/qemu-riscv64-static +%endif %{_datadir}/systemtap/tapset/qemu-riscv32-log-static.stp %{_datadir}/systemtap/tapset/qemu-riscv32-simpletrace-static.stp %{_datadir}/systemtap/tapset/qemu-riscv32-static.stp +%if %{have_64bit} %{_datadir}/systemtap/tapset/qemu-riscv64-log-static.stp %{_datadir}/systemtap/tapset/qemu-riscv64-simpletrace-static.stp %{_datadir}/systemtap/tapset/qemu-riscv64-static.stp @@ -3149,7 +3098,9 @@ fi %ifnarch riscv64 %{_exec_prefix}/lib/binfmt.d/qemu-riscv64-static.conf %endif +%endif +%if %{have_64bit} %files user-static-s390x %{_bindir}/qemu-s390x-static %{_datadir}/systemtap/tapset/qemu-s390x-log-static.stp @@ -3158,6 +3109,7 @@ fi %ifnarch s390x %{_exec_prefix}/lib/binfmt.d/qemu-s390x-static.conf %endif +%endif %files user-static-sh4 %{_bindir}/qemu-sh4-static @@ -3173,35 +3125,47 @@ fi %files user-static-sparc %{_bindir}/qemu-sparc-static +%if %{have_64bit} %{_bindir}/qemu-sparc32plus-static %{_bindir}/qemu-sparc64-static +%endif %{_datadir}/systemtap/tapset/qemu-sparc-log-static.stp %{_datadir}/systemtap/tapset/qemu-sparc-simpletrace-static.stp %{_datadir}/systemtap/tapset/qemu-sparc-static.stp +%if %{have_64bit} %{_datadir}/systemtap/tapset/qemu-sparc64-log-static.stp %{_datadir}/systemtap/tapset/qemu-sparc64-simpletrace-static.stp %{_datadir}/systemtap/tapset/qemu-sparc64-static.stp %{_datadir}/systemtap/tapset/qemu-sparc32plus-log-static.stp %{_datadir}/systemtap/tapset/qemu-sparc32plus-simpletrace-static.stp %{_datadir}/systemtap/tapset/qemu-sparc32plus-static.stp +%endif %{_exec_prefix}/lib/binfmt.d/qemu-sparc-static.conf +%if %{have_64bit} %{_exec_prefix}/lib/binfmt.d/qemu-sparc32plus-static.conf %{_exec_prefix}/lib/binfmt.d/qemu-sparc64-static.conf +%endif %files user-static-x86 %{_bindir}/qemu-i386-static +%if %{have_64bit} %{_bindir}/qemu-x86_64-static +%endif %{_datadir}/systemtap/tapset/qemu-i386-log-static.stp %{_datadir}/systemtap/tapset/qemu-i386-simpletrace-static.stp %{_datadir}/systemtap/tapset/qemu-i386-static.stp +%if %{have_64bit} %{_datadir}/systemtap/tapset/qemu-x86_64-log-static.stp %{_datadir}/systemtap/tapset/qemu-x86_64-simpletrace-static.stp %{_datadir}/systemtap/tapset/qemu-x86_64-static.stp +%endif %ifnarch %{ix86} x86_64 %{_exec_prefix}/lib/binfmt.d/qemu-i386-static.conf %{_exec_prefix}/lib/binfmt.d/qemu-i486-static.conf +%if %{have_64bit} %{_exec_prefix}/lib/binfmt.d/qemu-x86_64-static.conf %endif +%endif %files user-static-xtensa %{_bindir}/qemu-xtensa-static @@ -3218,6 +3182,7 @@ fi %endif +%if %{have_64bit} %files system-aarch64 %files system-aarch64-core %{_bindir}/qemu-system-aarch64 @@ -3227,8 +3192,10 @@ fi %if ! %{azl} %{_mandir}/man1/qemu-system-aarch64.1* %endif +%endif +%if %{have_64bit} %files system-alpha %files system-alpha-core %{_bindir}/qemu-system-alpha @@ -3239,12 +3206,15 @@ fi %{_mandir}/man1/qemu-system-alpha.1* %endif %{_datadir}/%{name}/palcode-clipper +%endif %files system-arm %files system-arm-core %{_bindir}/qemu-system-arm +%{_datadir}/%{name}/ast27x0_bootrom.bin %{_datadir}/%{name}/npcm7xx_bootrom.bin +%{_datadir}/%{name}/npcm8xx_bootrom.bin %{_datadir}/systemtap/tapset/qemu-system-arm.stp %{_datadir}/systemtap/tapset/qemu-system-arm-log.stp %{_datadir}/systemtap/tapset/qemu-system-arm-simpletrace.stp @@ -3264,17 +3234,7 @@ fi %endif -%files system-cris -%files system-cris-core -%{_bindir}/qemu-system-cris -%{_datadir}/systemtap/tapset/qemu-system-cris.stp -%{_datadir}/systemtap/tapset/qemu-system-cris-log.stp -%{_datadir}/systemtap/tapset/qemu-system-cris-simpletrace.stp -%if ! %{azl} -%{_mandir}/man1/qemu-system-cris.1* -%endif - - +%if %{have_64bit} %files system-hppa %files system-hppa-core %{_bindir}/qemu-system-hppa @@ -3286,8 +3246,10 @@ fi %endif %{_datadir}/%{name}/hppa-firmware.img %{_datadir}/%{name}/hppa-firmware64.img +%endif +%if %{have_64bit} %files system-loongarch64 %files system-loongarch64-core %{_bindir}/qemu-system-loongarch64 @@ -3297,6 +3259,7 @@ fi %if ! %{azl} %{_mandir}/man1/qemu-system-loongarch64.1* %endif +%endif %files system-m68k @@ -3324,33 +3287,39 @@ fi %{_mandir}/man1/qemu-system-microblaze.1* %{_mandir}/man1/qemu-system-microblazeel.1* %endif -%{_datadir}/%{name}/petalogix*.dtb +%{_datadir}/%{name}/dtb/petalogix*.dtb %files system-mips %files system-mips-core %{_bindir}/qemu-system-mips %{_bindir}/qemu-system-mipsel +%if %{have_64bit} %{_bindir}/qemu-system-mips64 %{_bindir}/qemu-system-mips64el +%endif %{_datadir}/systemtap/tapset/qemu-system-mips.stp %{_datadir}/systemtap/tapset/qemu-system-mips-log.stp %{_datadir}/systemtap/tapset/qemu-system-mips-simpletrace.stp %{_datadir}/systemtap/tapset/qemu-system-mipsel.stp %{_datadir}/systemtap/tapset/qemu-system-mipsel-log.stp %{_datadir}/systemtap/tapset/qemu-system-mipsel-simpletrace.stp +%if %{have_64bit} %{_datadir}/systemtap/tapset/qemu-system-mips64.stp %{_datadir}/systemtap/tapset/qemu-system-mips64-log.stp %{_datadir}/systemtap/tapset/qemu-system-mips64-simpletrace.stp %{_datadir}/systemtap/tapset/qemu-system-mips64el.stp %{_datadir}/systemtap/tapset/qemu-system-mips64el-log.stp %{_datadir}/systemtap/tapset/qemu-system-mips64el-simpletrace.stp +%endif %if ! %{azl} %{_mandir}/man1/qemu-system-mips.1* %{_mandir}/man1/qemu-system-mipsel.1* +%if %{have_64bit} %{_mandir}/man1/qemu-system-mips64el.1* %{_mandir}/man1/qemu-system-mips64.1* %endif +%endif %files system-or1k @@ -3367,20 +3336,27 @@ fi %files system-ppc %files system-ppc-core %{_bindir}/qemu-system-ppc +%if %{have_64bit} %{_bindir}/qemu-system-ppc64 +%endif %{_datadir}/systemtap/tapset/qemu-system-ppc.stp %{_datadir}/systemtap/tapset/qemu-system-ppc-log.stp %{_datadir}/systemtap/tapset/qemu-system-ppc-simpletrace.stp +%if %{have_64bit} %{_datadir}/systemtap/tapset/qemu-system-ppc64.stp %{_datadir}/systemtap/tapset/qemu-system-ppc64-log.stp %{_datadir}/systemtap/tapset/qemu-system-ppc64-simpletrace.stp +%endif %if ! %{azl} %{_mandir}/man1/qemu-system-ppc.1* +%if %{have_64bit} %{_mandir}/man1/qemu-system-ppc64.1* %endif -%{_datadir}/%{name}/bamboo.dtb -%{_datadir}/%{name}/canyonlands.dtb +%endif +%{_datadir}/%{name}/dtb/bamboo.dtb +%{_datadir}/%{name}/dtb/canyonlands.dtb %{_datadir}/%{name}/qemu_vga.ndrv +%{_datadir}/%{name}/pnv-pnor.bin %{_datadir}/%{name}/skiboot.lid %{_datadir}/%{name}/u-boot.e500 %{_datadir}/%{name}/u-boot-sam460-20100605.bin @@ -3393,14 +3369,18 @@ fi %files system-riscv %files system-riscv-core %{_bindir}/qemu-system-riscv32 +%if %{have_64bit} %{_bindir}/qemu-system-riscv64 +%endif %{_datadir}/%{name}/opensbi-riscv*.bin %{_datadir}/systemtap/tapset/qemu-system-riscv32.stp %{_datadir}/systemtap/tapset/qemu-system-riscv32-log.stp %{_datadir}/systemtap/tapset/qemu-system-riscv32-simpletrace.stp +%if %{have_64bit} %{_datadir}/systemtap/tapset/qemu-system-riscv64.stp %{_datadir}/systemtap/tapset/qemu-system-riscv64-log.stp %{_datadir}/systemtap/tapset/qemu-system-riscv64-simpletrace.stp +%endif %if ! %{azl} %{_mandir}/man1/qemu-system-riscv*.1* %endif @@ -3415,6 +3395,7 @@ fi %{_mandir}/man1/qemu-system-rx.1* %endif +%if %{have_64bit} %files system-s390x %files system-s390x-core %{_bindir}/qemu-system-s390x @@ -3425,7 +3406,7 @@ fi %{_mandir}/man1/qemu-system-s390x.1* %endif %{_datadir}/%{name}/s390-ccw.img -%{_datadir}/%{name}/s390-netboot.img +%endif %files system-sh4 @@ -3447,15 +3428,21 @@ fi %files system-sparc %files system-sparc-core %{_bindir}/qemu-system-sparc +%if %{have_64bit} %{_bindir}/qemu-system-sparc64 +%endif %{_datadir}/systemtap/tapset/qemu-system-sparc.stp %{_datadir}/systemtap/tapset/qemu-system-sparc-log.stp %{_datadir}/systemtap/tapset/qemu-system-sparc-simpletrace.stp +%if %{have_64bit} %{_datadir}/systemtap/tapset/qemu-system-sparc64.stp %{_datadir}/systemtap/tapset/qemu-system-sparc64-log.stp %{_datadir}/systemtap/tapset/qemu-system-sparc64-simpletrace.stp +%endif %{_mandir}/man1/qemu-system-sparc.1* +%if %{have_64bit} %{_mandir}/man1/qemu-system-sparc64.1* +%endif %{_datadir}/%{name}/QEMU,tcx.bin %{_datadir}/%{name}/QEMU,cgthree.bin %endif @@ -3478,19 +3465,23 @@ fi %files system-x86 %files system-x86-core %{_bindir}/qemu-system-i386 +%if %{have_64bit} %{_bindir}/qemu-system-x86_64 -%{_libdir}/%{name}/accel-tcg-i386.so -%{_libdir}/%{name}/accel-tcg-x86_64.so +%endif %{_datadir}/systemtap/tapset/qemu-system-i386.stp %{_datadir}/systemtap/tapset/qemu-system-i386-log.stp %{_datadir}/systemtap/tapset/qemu-system-i386-simpletrace.stp +%if %{have_64bit} %{_datadir}/systemtap/tapset/qemu-system-x86_64.stp %{_datadir}/systemtap/tapset/qemu-system-x86_64-log.stp %{_datadir}/systemtap/tapset/qemu-system-x86_64-simpletrace.stp +%endif %if ! %{azl} %{_mandir}/man1/qemu-system-i386.1* +%if %{have_64bit} %{_mandir}/man1/qemu-system-x86_64.1* %endif +%endif %{_datadir}/%{name}/kvmvapic.bin %{_datadir}/%{name}/linuxboot.bin %{_datadir}/%{name}/multiboot.bin @@ -3523,6 +3514,33 @@ fi # endif !tools_only %endif %changelog +* Wed Aug 05 2026 Azure Linux Security Servicing Account - 10.1.0-1 +- Upgrade QEMU to 10.1.0 while preserving the Azure Linux 3.0 package identity, + dependency policy, firmware paths, static user builds, and headless feature set. +- Remove CRIS system and user packages because QEMU 10 removed CRIS emulation; + obsolete the retired packages to support clean upgrades. +- Add the qemu-device-uefi-vars package for the new hw-uefi-vars module. +- Guard 64-bit emulators, packages, tapsets, and binfmt rules on 32-bit x86 because + QEMU 10 no longer builds 64-bit targets on 32-bit hosts. +- Disable new optional QEMU 10 features whose dependencies are unavailable in + Azure Linux 3.0, and remove obsolete AVX and sanitizer configure switches. +- Disable generic audio and SDL backends and remove their empty module packages, + matching the Azure Linux QEMU 10 headless build policy. +- Remove the virtio queue-loading and late block-activation patch series now + included upstream, while retaining the drain-before-inactivation fix. +- Rebase the Azure Linux migration test exclusions onto the split QEMU 10 test + framework, preserving X.509 coverage while skipping userfaultfd and TLS-PSK. +- Remove stale avocado_qemu test packaging because QEMU 10 replaced the + tests/avocado source tree with the functional test framework. +- Remove virtfs-proxy-helper packaging because QEMU 9.2 removed the insecure, + unmaintained 9p proxy backend and its root helper. +- Reconcile QEMU 10 firmware manifests: use the dtb subdirectory, package new + AST/NPCM/POWER firmware, and remove the retired s390-netboot image entry. +- Remove stale accel-tcg module entries because QEMU 10 links TCG into the + system emulators instead of installing per-target accelerator modules. +- Rebase the CVE-2026-3842 Hyper-V synthetic debugger fix for the QEMU 10 buffer + layout, and remove other patches already included verbatim upstream. + * Mon Jul 20 2026 Azure Linux Security Servicing Account - 9.1.0-11 - Patch for CVE-2026-3842 diff --git a/cgmanifest.json b/cgmanifest.json index 5a17a59c9bd..56bb5c17cc2 100644 --- a/cgmanifest.json +++ b/cgmanifest.json @@ -26083,8 +26083,8 @@ "type": "other", "other": { "name": "qemu", - "version": "9.1.0", - "downloadUrl": "https://download.qemu.org/qemu-9.1.0.tar.xz" + "version": "10.1.0", + "downloadUrl": "https://download.qemu.org/qemu-10.1.0.tar.xz" } } },