summaryrefslogtreecommitdiff
path: root/opt/xen
diff options
context:
space:
mode:
Diffstat (limited to 'opt/xen')
-rw-r--r--opt/xen/.footprint4
-rw-r--r--opt/xen/.signature13
-rw-r--r--opt/xen/MAKEPKG126
-rw-r--r--opt/xen/hotplug-Linux-iscsi-block-handle-lun-1.patch41
-rw-r--r--opt/xen/hotplug-vif-vtrill.patch138
-rw-r--r--opt/xen/xsa477.patch105
-rw-r--r--opt/xen/xsa479.patch81
-rw-r--r--opt/xen/xsa480.patch46
-rw-r--r--opt/xen/xsa481.patch56
9 files changed, 610 insertions, 0 deletions
diff --git a/opt/xen/.footprint b/opt/xen/.footprint
new file mode 100644
index 0000000..0dafb3f
--- /dev/null
+++ b/opt/xen/.footprint
@@ -0,0 +1,4 @@
+drwxr-xr-x root/root boot/
+-rw-r--r-- root/root boot/xen-4.22.0.config
+-rw-r--r-- root/root boot/xen-4.22.0.efi
+-rw-r--r-- root/root boot/xen-4.22.0.gz
diff --git a/opt/xen/.signature b/opt/xen/.signature
new file mode 100644
index 0000000..cf4c2b1
--- /dev/null
+++ b/opt/xen/.signature
@@ -0,0 +1,13 @@
+RWTZ9IduCSQ/mD39r2tDeyj1Hqqfm+3O+dukYuoyxwG6TYaFwz3/Kyxm4WePO+USTIwnX7ijVTNtGBmCJYjrnRD5eXFS2d8Hzwc=
+
+SHA256 (MAKEPKG) = cd157b697db21087bd8ffe18f7191e8dd770f1d842d14eefed7d57ae41af50ac
+SHA256 (.footprint) = 770152a3315fcf253631adf4c21f006125cbe79ad84eafe247825ee466a6155e
+SHA256 (xen-4.22.0.tar.gz) = b2a14ca369e3cf26f123a455b1603f3962ae9fcee0b8640a9cc33879de198223
+SHA256 (binutils-2.46.0.tar.xz) = d75a94f4d73e7a4086f7513e67e439e8fcdcbb726ffe63f4661744e6256b2cf2
+SHA256 (xsa477.patch) = 025783441d7db846e717a1e48547b0db7a36fcc6af652b688524c684f0c3d2a7
+SHA256 (xsa479.patch) = 82369898d0287e69272d0d65fb0e6be5fd0106bda19cedb3c9f6e75688f6fb4b
+SHA256 (xsa480.patch) = 578f8fec3f34656e085419f6376d43987ffd6ed32e067b4024d3c83ce03a5901
+SHA256 (xsa481.patch) = 148147e4545a4670578c0f24aa136f67bc203c7b18ec980b8cc80cfbb04ace68
+SHA256 (hotplug-vif-vtrill.patch) = c3994774305807f607742b6d49691c913fe3455cf1ab871254bc8fe2a4906b43
+SHA256 (hotplug-Linux-iscsi-block-handle-lun-1.patch) = a9dfb68d615aa4ee9e1137fa6bcc69a291e9603202db40bb343d50caf30dae3d
+SHA256 (xen#4.22.0-2.pkg.tar.gz) = 3c10126537d211a84c48efd97b38ccf59e13c74becb357fb8a2fb2fc5ee85ab1
diff --git a/opt/xen/MAKEPKG b/opt/xen/MAKEPKG
new file mode 100644
index 0000000..39a68dd
--- /dev/null
+++ b/opt/xen/MAKEPKG
@@ -0,0 +1,126 @@
+#!/bin/mkpkg
+# description: Xen hypervisor
+# url: https://xenproject.org
+
+name=xen
+version=4.22.0
+release=2
+depends=()
+makedeps=(python3 iasl perl)
+source=(https://downloads.xenproject.org/release/xen/$version/xen-$version.tar.gz
+ https://ftp.gnu.org/gnu/binutils/binutils-2.46.0.tar.xz
+ xsa477.patch
+ xsa479.patch
+ xsa480.patch
+ xsa481.patch
+ hotplug-vif-vtrill.patch
+ hotplug-Linux-iscsi-block-handle-lun-1.patch)
+sha256sums=(
+ "b2a14ca369e3cf26f123a455b1603f3962ae9fcee0b8640a9cc33879de198223"
+ "d75a94f4d73e7a4086f7513e67e439e8fcdcbb726ffe63f4661744e6256b2cf2"
+ "025783441d7db846e717a1e48547b0db7a36fcc6af652b688524c684f0c3d2a7"
+ "82369898d0287e69272d0d65fb0e6be5fd0106bda19cedb3c9f6e75688f6fb4b"
+ "578f8fec3f34656e085419f6376d43987ffd6ed32e067b4024d3c83ce03a5901"
+ "148147e4545a4670578c0f24aa136f67bc203c7b18ec980b8cc80cfbb04ace68"
+ "c3994774305807f607742b6d49691c913fe3455cf1ab871254bc8fe2a4906b43"
+ "a9dfb68d615aa4ee9e1137fa6bcc69a291e9603202db40bb343d50caf30dae3d"
+)
+
+build() {
+ # Build private GNU ld — needed for PE/EFI link (x86_64-pep target)
+ cd $SRC/binutils-2.46.0
+ CONFIG_SHELL=/bin/bash ./configure \
+ --prefix=$SRC/ld-local \
+ --disable-nls \
+ --disable-multilib \
+ --disable-werror \
+ --disable-gdb \
+ --disable-gdbserver \
+ --disable-gold \
+ --disable-gprofng \
+ --disable-gas \
+ --disable-sim \
+ --disable-libdecnumber \
+ --disable-readline \
+ --enable-ld \
+ --enable-targets=x86_64-linux,x86_64-pep \
+ --with-system-zlib \
+ CC=clang CXX=clang++
+ make
+ make install
+ export PATH="$SRC/ld-local/bin:$PATH"
+
+ # Verify GNU ld has PE support before proceeding
+ ld -V | grep -i "pep\|pe-x86" || { echo "GNU ld missing PE support"; exit 1; }
+
+ cd $SRC/xen-$version
+
+ for p in $SRC/xsa477.patch $SRC/xsa479.patch $SRC/xsa480.patch $SRC/xsa481.patch \
+ $SRC/hotplug-vif-vtrill.patch $SRC/hotplug-Linux-iscsi-block-handle-lun-1.patch; do
+ [ -f "$p" ] && patch -N -p1 < "$p" || true
+ done
+
+ unset CFLAGS CXXFLAGS CPPFLAGS ASFLAGS LDFLAGS AR OBJCOPY RANLIB CC LD LANG LC_ALL
+
+ # These two seds are a pair and the order is load-bearing.
+ # xen/Makefile:293 has '-Werror=unknown-warning-option'; the
+ # strip below reduces it to '=unknown-warning-option', and the
+ # second sed rewrites that to '-Wno-unknown-warning-option'.
+ # Net effect: clang IGNORES warning flags it does not know
+ # instead of erroring on them. Xen adds GCC-only flags via
+ # cc-option-add (e.g. -Wflex-array-member-not-at-end at line
+ # 404), and cc-option probes without -Werror=..., so clang
+ # accepts them at probe time and would reject them at compile
+ # time. Do not 'repair' the strip to preserve -Werror= — that
+ # re-arms the exact error this exists to disarm.
+ find . \( -name '*.mk' -o -name 'Make*' \) \
+ -exec sed -i -e 's/-Werror//g' {} +
+
+ sed -i 's/CLANG_FLAGS += =unknown-warning-option/CLANG_FLAGS += -Wno-unknown-warning-option/' \
+ xen/Makefile
+
+ sed -e '/-include $(XEN_ROOT)\/.config/d' -i Config.mk
+
+ sed -i 's/efi-nr-fixups :=.*/efi-nr-fixups := 2/' xen/arch/x86/arch.mk
+
+ # -fno-jump-tables: clang emits switch tables into
+ # .data.rel.ro..Lswitch.table.*, and Rules.mk:277 rejects any section
+ # outside the init sections when building a .init.o (seen on
+ # common/unzstd.o). EXTRA_CFLAGS_XEN_CORE is the hook xen/Makefile:421
+ # documents for this; it is appended last, so it also overrides
+ # anything set earlier. Needed on both invocations — install-xen
+ # re-enters the build.
+ make \
+ CC=clang CXX=clang++ LD=ld \
+ AR=llvm-ar RANLIB=llvm-ranlib OBJDUMP=llvm-objdump \
+ HOSTCC=clang HOSTCXX=clang++ \
+ clang=y XEN_TARGET_ARCH=x86_64 \
+ EXTRA_CFLAGS_XEN_CORE="-fno-jump-tables" \
+ xen
+
+ make \
+ CC=clang CXX=clang++ LD=ld \
+ AR=llvm-ar RANLIB=llvm-ranlib OBJDUMP=llvm-objdump \
+ HOSTCC=clang HOSTCXX=clang++ \
+ clang=y XEN_TARGET_ARCH=x86_64 \
+ EXTRA_CFLAGS_XEN_CORE="-fno-jump-tables" \
+ LIBDIR=lib \
+ EFI_DIR=/boot \
+ INSTALL_EFI_STRIP=1 \
+ DESTDIR=$PKG \
+ install-xen
+
+ # Xen's EFI loader walks a config name back through version
+ # components (xen-4.22.0.cfg -> xen-4.22.cfg -> xen-4.cfg ->
+ # xen.cfg), which is what the version-stripped symlinks are
+ # for. The ESP is FAT and has no symlinks, and limine-sync
+ # mirrors regular files only, so drop them all. Generic on
+ # purpose: per-version 'rm -f' lines went stale at each bump.
+ find $PKG/boot -type l -delete
+ rm -rf $PKG/usr
+}
+signify() {
+ untrusted comment: public key
+ RWTZ9IduCSQ/mL8337TEUinPwT92xFEUpD92hkS7IxcOnzTt9QdpohT3
+}
+# vim: filetype=sh
diff --git a/opt/xen/hotplug-Linux-iscsi-block-handle-lun-1.patch b/opt/xen/hotplug-Linux-iscsi-block-handle-lun-1.patch
new file mode 100644
index 0000000..fdccee6
--- /dev/null
+++ b/opt/xen/hotplug-Linux-iscsi-block-handle-lun-1.patch
@@ -0,0 +1,41 @@
+From 15cdf8ac5f93ace4c489333da81d2a077c771f9c Mon Sep 17 00:00:00 2001
+From: Henrik Riomar <henrik.riomar@gmail.com>
+Date: Sun, 28 Jan 2018 18:54:49 +0100
+Subject: [PATCH] hotplug/Linux: iscsi block, handle lun-1
+
+With tgtd lun-0 is the controller and lun-1 is the disk, check
+for both 0 and 1 in the readlink call.
+
+Reference:
+ http://inqbus-hosting.de/support/dokumentation/docs/target-daemon-tgtd-tgtadm#show-targets
+
+Signed-off-by: Henrik Riomar <henrik.riomar@gmail.com>
+---
+ tools/hotplug/Linux/block-iscsi | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/tools/hotplug/Linux/block-iscsi b/tools/hotplug/Linux/block-iscsi
+index 3615905252..6bbf56fe5a 100644
+--- a/tools/hotplug/Linux/block-iscsi
++++ b/tools/hotplug/Linux/block-iscsi
+@@ -73,7 +73,7 @@ parse_target()
+ find_device()
+ {
+ count=0
+- while [ ! -e /dev/disk/by-path/*"$iqn"-lun-0 ]; do
++ while [ ! -e /dev/disk/by-path/*"$iqn"-lun-[01] ]; do
+ sleep 1
+ count=`expr $count + 1`
+ if [ count = 100 ]; then
+@@ -81,7 +81,7 @@ find_device()
+ fatal "timeout waiting for iSCSI disk to settle"
+ fi
+ done
+- sddev=$(readlink -f /dev/disk/by-path/*"$iqn"-lun-0 || true)
++ sddev=$(readlink -f /dev/disk/by-path/*"$iqn"-lun-[01] || true)
+ if [ ! -b "$sddev" ]; then
+ fatal "Unable to find attached device path"
+ fi
+--
+2.16.1
+
diff --git a/opt/xen/hotplug-vif-vtrill.patch b/opt/xen/hotplug-vif-vtrill.patch
new file mode 100644
index 0000000..a50d643
--- /dev/null
+++ b/opt/xen/hotplug-vif-vtrill.patch
@@ -0,0 +1,138 @@
+--- a/tools/hotplug/Linux/Makefile
++++ b/tools/hotplug/Linux/Makefile
+@@ -6,6 +6,7 @@ XEN_SCRIPTS = vif-bridge
+ XEN_SCRIPTS += vif-route
+ XEN_SCRIPTS += vif-nat
+ XEN_SCRIPTS += vif-openvswitch
++XEN_SCRIPTS += vif-vtrill
+ XEN_SCRIPTS += vif-setup
+ XEN_SCRIPTS-$(CONFIG_LIBNL) += remus-netbuf-setup
+ XEN_SCRIPTS += block
+--- a/tools/hotplug/Linux/vif-common.sh
++++ b/tools/hotplug/Linux/vif-common.sh
+@@ -244,3 +244,31 @@ dom0_ip()
+ fi
+ echo "$result"
+ }
++
++ip6_of()
++{
++ ip -6 -o addr show scope global dev "$1" | awk '$3 == "inet6" { split($4,i,"/"); print i[1]; exit }'
++}
++
++dom0_ip6_gateway()
++{
++ ip -6 -o route show "default" | awk '$1 == "default" { print $3; exit }'
++}
++
++dom0_ip6()
++{
++ local nd=${netdev:-eth0}
++ local result=$(ip6_of "$nd")
++ if [ -z "$result" ]
++ then
++ echo ""
++ else
++ echo "$result"
++ fi
++}
++
++is_ipv6()
++{
++ echo "${1}" | grep -q ':' && echo "ipv6"
++}
++
+--- /dev/null
++++ b/tools/hotplug/Linux/vif-vtrill
+@@ -0,0 +1,91 @@
++#!/bin/bash
++#============================================================================
++# ${XEN_SCRIPT_DIR}/vif-vtrill
++# Based on ${XEN_SCRIPT_DIR}/vif-openvswitch
++#
++# Script for configuring a vif in routed + bridged mode.
++# The hotplugging system will call this script if it is specified either in
++# the device configuration given to Xend, or the default Xend configuration
++# in ${XEN_CONFIG_DIR}/xend-config.sxp. If the script is specified in
++# neither of those places, then this script is the default.
++#
++# Usage:
++# vif-openvswitch (add|remove|online|offline)
++#
++# Environment vars:
++# vif vif interface name (required).
++# XENBUS_PATH path to this device's details in the XenStore (required).
++#
++# Read from the store:
++# ip list of IP networks for the vif, space-separated (optional).
++#
++# up:
++# Enslaves the vif interface to a VM-specific bridge and adds iptables rules
++# for its ip addresses (if any).
++#
++# down:
++# Removes the vif interface from the VM-bridge bridge and removes the iptables
++# rules for its ip addresses (if any).
++#============================================================================
++
++dir=$(dirname "$0")
++. "${dir}/vif-common.sh"
++
++main_ip=$(dom0_ip)
++main_ip6=$(dom0_ip6)
++gateway_ip6=$(dom0_ip6_gateway)
++vlanname=$(echo ${dev} | cut -d'.' -f1)
++
++case "${command}" in
++ online)
++ create_bridge ${vlanname}
++ add_to_bridge ${vlanname} ${dev}
++ ifconfig ${vlanname} ${main_ip} netmask 255.255.255.255 up
++ if [ ! -z "${main_ip6}" ]
++ then
++ ip -6 addr add ${main_ip6} dev ${vlanname}
++ ip -6 neighbor add proxy ${gateway_ip6} dev ${vlanname}
++ echo 1 >/proc/sys/net/ipv6/conf/${vlanname}/proxy_ndp
++ fi
++ echo 1 >/proc/sys/net/ipv4/conf/${vlanname}/proxy_arp
++ ipcmd='add'
++ cmdprefix=''
++ ;;
++ offline)
++ ifconfig ${vlanname} down
++ brctl delbr ${vlanname}
++ ipcmd='del'
++ cmdprefix='do_without_error'
++ ;;
++ add)
++ create_bridge ${vlanname}
++ add_to_bridge ${vlanname} ${dev}
++ ;;
++ remove)
++ ;;
++esac
++
++if [ "${ip}" -a "$type_if" != "tap" ] ; then
++ # If we've been given a list of IP addresses, then add routes from dom0 to
++ # the guest using those addresses.
++ for addr in ${ip} ; do
++ do_without_error ip route del ${addr}
++ if [ "$(is_ipv6 ${addr})" = "ipv6" ]; then
++ ${cmdprefix} ip -6 route ${ipcmd} ${addr} dev ${vlanname} src ${main_ip6}
++ ${cmdprefix} ip -6 neighbor ${ipcmd} proxy ${addr} dev ${netdev:-eth0}
++ else
++ do_without_error ip route ${ipcmd} ${addr} dev ${vlanname} src ${main_ip}
++ fi
++ done
++fi
++
++log "iptable"
++handle_iptable
++
++call_hooks vif post
++
++log debug "Successful vif-vtrill ${command} for ${dev}."
++if [ "${command}" = "online" ]
++then
++ success
++fi
diff --git a/opt/xen/xsa477.patch b/opt/xen/xsa477.patch
new file mode 100644
index 0000000..48a9484
--- /dev/null
+++ b/opt/xen/xsa477.patch
@@ -0,0 +1,105 @@
+From: Jan Beulich <jbeulich@suse.com>
+Subject: x86/shadow: don't overrun trace_emul_write_val
+
+Guests can do wider-than-PTE-size writes on page tables. The tracing
+helper variable, however, only offers space for a single PTE (and it is
+being switched to the more correct type right here). Therefore bound
+incoming write sizes to the amount of space available.
+
+To not leave dead code (which is a Misra concern), drop the now unused
+guest_pa_t as well.
+
+Also move and adjust GUEST_PTE_SIZE: Derive it rather than using hard-
+coded numbers, and put it in the sole source file where it's actually
+needed. This then also addresses a Misra rule 20.9 ("All identifiers
+used in the controlling expression of #if or #elif preprocessing
+directives shall be #define'd before evaluation") violation:
+GUEST_PAGING_LEVELS is #define'd only in multi.c.
+
+This is XSA-477 / CVE-2025-58150.
+
+Fixes: 9a86ac1aa3d2 ("xentrace 5/7: Additional tracing for the shadow code")
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
+
+--- a/xen/arch/x86/mm/shadow/multi.c
++++ b/xen/arch/x86/mm/shadow/multi.c
+@@ -1970,15 +1970,15 @@ static void sh_prefetch(struct vcpu *v,
+
+ #if GUEST_PAGING_LEVELS == 4
+ typedef u64 guest_va_t;
+-typedef u64 guest_pa_t;
+ #elif GUEST_PAGING_LEVELS == 3
+ typedef u32 guest_va_t;
+-typedef u64 guest_pa_t;
+ #else
+ typedef u32 guest_va_t;
+-typedef u32 guest_pa_t;
+ #endif
+
++/* Size (in bytes) of a guest PTE */
++#define GUEST_PTE_SIZE sizeof(guest_l1e_t)
++
+ /* Shadow trace event with GUEST_PAGING_LEVELS folded into the event field. */
+ static void sh_trace(uint32_t event, unsigned int extra, const void *extra_data)
+ {
+@@ -2048,11 +2048,14 @@ static void __maybe_unused sh_trace_gfn_
+ static DEFINE_PER_CPU(guest_va_t,trace_emulate_initial_va);
+ static DEFINE_PER_CPU(int,trace_extra_emulation_count);
+ #endif
+-static DEFINE_PER_CPU(guest_pa_t,trace_emulate_write_val);
++static DEFINE_PER_CPU(guest_l1e_t, trace_emulate_write_val);
+
+ static void cf_check trace_emulate_write_val(
+ const void *ptr, unsigned long vaddr, const void *src, unsigned int bytes)
+ {
++ if ( bytes > sizeof(this_cpu(trace_emulate_write_val)) )
++ bytes = sizeof(this_cpu(trace_emulate_write_val));
++
+ #if GUEST_PAGING_LEVELS == 3
+ if ( vaddr == this_cpu(trace_emulate_initial_va) )
+ memcpy(&this_cpu(trace_emulate_write_val), src, bytes);
+@@ -2077,13 +2080,16 @@ static inline void sh_trace_emulate(gues
+ /*
+ * For GUEST_PAGING_LEVELS=3 (PAE paging), guest_l1e is 64 while
+ * guest_va is 32. Put it first to avoid padding.
++ *
++ * Note: .write_val is an arbitrary set of written bytes, possibly
++ * misaligned and possibly spanning the next gl1e.
+ */
+ guest_l1e_t gl1e, write_val;
+ guest_va_t va;
+ uint32_t flags:29, emulation_count:3;
+ } d = {
+ .gl1e = gl1e,
+- .write_val.l1 = this_cpu(trace_emulate_write_val),
++ .write_val = this_cpu(trace_emulate_write_val),
+ .va = va,
+ #if GUEST_PAGING_LEVELS == 3
+ .emulation_count = this_cpu(trace_extra_emulation_count),
+@@ -2672,7 +2677,7 @@ static int cf_check sh_page_fault(
+ paging_unlock(d);
+ put_gfn(d, gfn_x(gfn));
+
+- this_cpu(trace_emulate_write_val) = 0;
++ this_cpu(trace_emulate_write_val) = (guest_l1e_t){};
+
+ #if SHADOW_OPTIMIZATIONS & SHOPT_FAST_EMULATION
+ early_emulation:
+--- a/xen/arch/x86/mm/shadow/private.h
++++ b/xen/arch/x86/mm/shadow/private.h
+@@ -120,14 +120,6 @@ enum {
+ TRCE_SFLAG_OOS_FIXUP_EVICT,
+ };
+
+-
+-/* Size (in bytes) of a guest PTE */
+-#if GUEST_PAGING_LEVELS >= 3
+-# define GUEST_PTE_SIZE 8
+-#else
+-# define GUEST_PTE_SIZE 4
+-#endif
+-
+ /******************************************************************************
+ * Auditing routines
+ */
diff --git a/opt/xen/xsa479.patch b/opt/xen/xsa479.patch
new file mode 100644
index 0000000..448d46b
--- /dev/null
+++ b/opt/xen/xsa479.patch
@@ -0,0 +1,81 @@
+From: Roger Pau Monné <roger.pau@citrix.com>
+Subject: x86/spec-ctrl: Fix incomplete IBPB flushing during context switch
+
+The previous logic attempted to skip an IBPB in the case of vCPU returning to
+a CPU on which it was the previous vCPU to run. While safe for Xen's
+isolation between vCPUs, this prevents the guest kernel correctly isolation
+between tasks. Consider:
+
+ 1) vCPU runs on CPU A, running task 1.
+ 2) vCPU moves to CPU B, idle gets scheduled on A. Xen skips IBPB.
+ 3) On CPU B, guest kernel switches from task 1 to 2, issuing IBPB.
+ 4) vCPU moves back to CPU A. Xen skips IBPB again.
+
+Now, task 2 is running on CPU A with task 1's training still in the BTB.
+
+Do the flush unconditionally when switching to a vCPU different than the
+idle one. Note there's no need to explicitly gate the IBPB to next domain
+!= idle, as the context where the IBPB is issued is subject to that
+condition already unless the pCPU is going offline, at which point we don't
+really care to issue an extra IBPB.
+
+Also add a comment with the reasoning why the IBPB needs to be in
+context_switch() rather than __context_switch().
+
+This is XSA-479 / CVE-2026-23553.
+
+Fixes: a2ed643ed783 ("x86/ctxt: Issue a speculation barrier between vcpu contexts")
+Reported-by: David Kaplan <david.kaplan@amd.com>
+Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
+Reviewed-by: Jan Beulich <jbeulich@suse.com>
+---
+ xen/arch/x86/domain.c | 36 +++++++++---------------------------
+ 1 file changed, 9 insertions(+), 27 deletions(-)
+
+diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
+index c29a6b0decee..c1eded3eb604 100644
+--- a/xen/arch/x86/domain.c
++++ b/xen/arch/x86/domain.c
+@@ -2174,33 +2174,15 @@ void context_switch(struct vcpu *prev, struct vcpu *next)
+
+ ctxt_switch_levelling(next);
+
+- if ( opt_ibpb_ctxt_switch && !is_idle_domain(nextd) )
+- {
+- static DEFINE_PER_CPU(unsigned int, last);
+- unsigned int *last_id = &this_cpu(last);
+-
+- /*
+- * Squash the domid and vcpu id together for comparison
+- * efficiency. We could in principle stash and compare the struct
+- * vcpu pointer, but this risks a false alias if a domain has died
+- * and the same 4k page gets reused for a new vcpu.
+- */
+- unsigned int next_id = (((unsigned int)nextd->domain_id << 16) |
+- (uint16_t)next->vcpu_id);
+- BUILD_BUG_ON(MAX_VIRT_CPUS > 0xffff);
+-
+- /*
+- * When scheduling from a vcpu, to idle, and back to the same vcpu
+- * (which might be common in a lightly loaded system, or when
+- * using vcpu pinning), there is no need to issue IBPB, as we are
+- * returning to the same security context.
+- */
+- if ( *last_id != next_id )
+- {
+- spec_ctrl_new_guest_context();
+- *last_id = next_id;
+- }
+- }
++ /*
++ * Issue an IBPB when scheduling a different vCPU if required.
++ *
++ * IBPB clears the RSB/RAS/RAP, but that's fine as we leave this
++ * function via reset_stack_and_call_ind() rather than via a RET
++ * instruction.
++ */
++ if ( opt_ibpb_ctxt_switch )
++ spec_ctrl_new_guest_context();
+
+ /* Update the top-of-stack block with the new speculation settings. */
+ info->scf =
diff --git a/opt/xen/xsa480.patch b/opt/xen/xsa480.patch
new file mode 100644
index 0000000..d01ea35
--- /dev/null
+++ b/opt/xen/xsa480.patch
@@ -0,0 +1,46 @@
+From 45f6866e34b7e9ee8b6ac16d646a2e954c97e48e Mon Sep 17 00:00:00 2001
+From: Roger Pau Monne <roger.pau@citrix.com>
+Date: Tue, 17 Feb 2026 09:33:43 +0100
+Subject: [PATCH] x86/p2m: issue a sync flush before freeing paging pages
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+In the EPT implementation, the defer flushing logic is used
+unconditionally, and that would lead to paging memory being returned to the
+paging pool before its references had been flushed.
+
+Issue any pending flushes before freeing the paging memory back to the
+pool.
+
+Note AMD (NPT) and Shadow paging are not affected, as they don't implement
+the deferred flushing logic.
+
+This is XSA-480 / CVE-2026-23554
+
+Fixes: 4a59e6bb3a96 ("x86/EPT: squash meaningless TLB flush")
+Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
+Reviewed-by: Jan Beulich <jbeulich@suse.com>
+---
+ xen/arch/x86/mm/p2m.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
+index e915da26a832..fddecdf978ec 100644
+--- a/xen/arch/x86/mm/p2m.c
++++ b/xen/arch/x86/mm/p2m.c
+@@ -479,6 +479,11 @@ void p2m_free_ptp(struct p2m_domain *p2m, struct page_info *pg)
+ ASSERT(p2m->domain);
+ ASSERT(p2m->domain->arch.paging.free_page);
+
++ /*
++ * Issue any pending flush here, in case it was deferred before. The page
++ * will be returned to the paging pool now.
++ */
++ p2m_tlb_flush_sync(p2m);
+ page_list_del(pg, &p2m->pages);
+ p2m->domain->arch.paging.free_page(p2m->domain, pg);
+
+--
+2.51.0
+
diff --git a/opt/xen/xsa481.patch b/opt/xen/xsa481.patch
new file mode 100644
index 0000000..c21f910
--- /dev/null
+++ b/opt/xen/xsa481.patch
@@ -0,0 +1,56 @@
+From 0cff16f0a997f1b0871b621a1d6050652530e5d9 Mon Sep 17 00:00:00 2001
+From: Juergen Gross <jgross@suse.com>
+Date: Thu, 12 Feb 2026 08:29:38 +0100
+Subject: [PATCH] tools/xenstored: fix canonicalize() error testing
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The setting of errno in canonicalize() is rather fragile and seems to
+be even wrong in one corner case: when the invalid path "/local/domain/"
+is passed, sscanf() will set errno to 0, resulting in canonicalize() to
+return NULL with errno being 0. This can result in triggering the
+assert(conn->in == NULL) in consider_message().
+
+Don't assume the initial setting of errno to "EINVAL" will stay valid
+in all cases and set it to EINVAL only when returning NULL due to an
+invalid path.
+
+This is XSA-481/CVE-2026-23555
+
+Reported-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Reviewed-by: Julien Grall <julien@xen.org>
+---
+ tools/xenstored/core.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/tools/xenstored/core.c b/tools/xenstored/core.c
+index 64c478a801..2e826f99eb 100644
+--- a/tools/xenstored/core.c
++++ b/tools/xenstored/core.c
+@@ -1240,11 +1240,10 @@ const char *canonicalize(struct connection *conn, const void *ctx,
+ * - illegal character in node
+ * - starts with '@' but no special node allowed
+ */
+- errno = EINVAL;
+ if (!node ||
+ !valid_chars(node) ||
+ (node[0] == '@' && !allow_special))
+- return NULL;
++ goto inval;
+
+ if (node[0] != '/' && node[0] != '@') {
+ name = talloc_asprintf(ctx, "%s/%s", get_implicit_path(conn),
+@@ -1272,6 +1271,8 @@ const char *canonicalize(struct connection *conn, const void *ctx,
+ if (name != node)
+ talloc_free(name);
+
++ inval:
++ errno = EINVAL;
+ return NULL;
+ }
+
+--
+2.53.0
+