Grants can be offered read-only by the owning domain. While a domain mapping
a RO grant may have a need to invalidate the cache, it must not modify the
other-guests data while doing so. Force-upgrade to a clean operation in this
case.
This is CVE-2026-102702, part of XSA-519.
Fixes: 18e8d22fe7 ("introduce GNTTABOP_cache_flush")
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
(cherry picked from commit c89185286c)
When the start address is not cacheline aligned, the bytes covered by
the first, partial cacheline are subtracted from 'size'. Nothing checks
that the region actually extends beyond that cacheline, so if it does
not, the unsigned subtraction underflows and the loop that follows walks
practically the entire address space.
For example, with a 64-byte cacheline, p = 0x40000001 and size = 1:
p & cacheline_mask -> 1, so the partial head is taken
size -= 64 - 1 -> 1 - 63 underflows to 0xffffffffffffffc2
Instead of a single "dc civac" at 0x40000000, the loop then runs
288230376151711743 times, issuing "dc ivac" from 0x40000040 upwards.
Invalidating without cleaning discards dirty cachelines, so this
corrupts whatever is mapped along the way until Xen takes a data abort.
Moreover, _cache_flush() in common/grant_table.c, reachable from a guest
via GNTTABOP_cache_flush, bounds 'offset' and 'length' against the page
size but requires no alignment, so GNTTAB_CACHE_INVAL with offset = 1
and length = 1 is enough to trigger this. Note that the page may belong
to a different domain (the d != owner path), so the data being discarded
is not necessarily the caller's own.
The subtraction dates back to the fix for XSA-437, so this is a regression
in that change.
Fix this by detecting the underflow instead of letting it happen: if the
region ends inside the first cacheline, there is nothing left to flush
and the function bails out right after cleaning it. Partially covered
cachelines are still cleaned as well as invalidated, so that data outside
of the region is not discarded.
Additionally, drop 'idx' and advance 'p' directly instead. It simplifies
the logic while using fewer variables and less arithmetic.
Note that the partial head is now cleaned using the unaligned start of the
region instead of the start of its cacheline. This is permitted by the
architecture; the Arm ARM (DDI 0487) states:
"When a DC instruction requires an address argument this takes the form
of a 64-bit register that holds the VA argument. No alignment
restrictions apply for this address."
The same applies on Arm32.
Also, switch the asm() in the loop to asm_inline, like the neighbouring
ones: the wrapper expands to a single instruction with a trailing
semicolon, which GCC counts as two statements, overestimating the size
of the function when deciding whether to inline it.
This is CVE-2026-102699, part of XSA-519.
Fixes: 9a216e92de ("xen/arm: page: Handle cache flush of an element at the top of the address space")
Signed-off-by: Leonid Komarianskyi <leonid_komarianskyi@epam.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Julien Grall <julien@xen.org>
(cherry picked from commit 4b8a11b421)
The consistency checks in effect when Blocked-by-STI/MovSS are active includes
DEBUGCTL.BTF too. Take this into account when editing PENDING_DBG.BS.
This ends up narrowing the cases where PENDING_DBG is modified. Rework the
comment to be more precise.
This is XSA-518 / CVE-2026-79611.
Fixes: 1d3eb82598 ("x86/vtx: Work around SingleStep + STI/MovSS VMEntry failures")
Reported-by: Teddy Astie <teddy.astie@vates.tech>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Teddy Astie <teddy.astie@vates.tech>
(cherry picked from commit 1017562ac0)
A v1 -> v2 change isn't the only scenario where "status" may go stale in
map_grant_ref(). Across a v2 -> v1 -> v2 change the status pages would
have been freed and re-populated, possibly changing the pages used for the
array. Check the pointer against the expected version-dependent value.
This is XSA-517 / CVE-2026-79610.
Fixes: 96dfeb4177 ("gnttab: cope with version changes racing other operations")
Assisted-by: Claude
Reported-by: Teddy Astie <teddy.astie@vates.tech>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Teddy Astie <teddy.astie@vates.tech>
(cherry picked from commit e0a0823ee0)
For XPTI enabled VMs, restore_all_guest() copies most of the active L4
pagetable into the per-CPU root_pgt. The L4 is read via the
directmap.
Unfortunately, there was no accounting for the fact that PV guests
have short directmaps. For an L4 living beyond the 5T boundary (3.5T
for CONFIG_BIGMEM), Xen will copy arbitrary data from guest-controlled
virtual address space into the per-CPU root_pgt, instead of the
intended L4.
Xen has per-domain mappings for the LDT and GDT, with two pages
reserved for Xen's use in the GDT but only one in use. Reuse GDT page
15 to map the effective L4. The GDT limit keeps implicit accesses out
of this page.
We update this mapping in make_cr3(), the only place a non-empty value
of v->arch.cr3 is written into a guest's vcpu struct, for two reasons.
First is reference counting: this makes it easier to argue that the
reference for v->arch.cr3 itself covers the reference for the mapping.
Secondly, this guarantees that all updates, even updates made in
shadow mode, result in an update to the mapping. During live
migration, it's possible for guest_get_eff_kern_l1e() to result in a
modified value of v->arch.cr3 (sketch below); placing the mapping
update at make_cr3() catches this, while other candidate locations
like write_ptbase() and toggle_guest_mode() don't.
Note that we introduce the idea of an "effective L4" here, to mean
"guest L4 after any transformations": XPTI copies either the actual
guest L4 if not shadowed, or the shadow L4 (transformed) if shadowed.
Sketch: guest_get_eff_kern_l1e() has a pair of toggle_guest_pt() calls
which happen if the guest is in user mode. During live migration, a
log-dirty clean will do a domain_pause and then call
shadow_blow_tables(), unpinning the shadow of the guest user root
pagetable. After execution resumes, the first toggle_guest_pt() could
then cause that page to become unshadowed. The second
toggle_guest_pt() would then re-shadow it, possibly with a different
backing shadow page.
This is XSA-516 / CVE-2026-79609.
Fixes: 5784de3e20 ("x86: Meltdown band-aid against malicious 64-bit PV guests")
Assisted-by: Claude Code:claude-fable-5-1
Signed-off-by: George Dunlap <gwd@xenproject.org>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
(cherry picked from commit 288fb61585)
The identified commit inverted the condition under which Xen chooses
to set the Zenbleed chickenbit.
Undo that, and leave a better comment explaining why.
Found by AI review of the referenced commit.
This is XSA-515 / CVE-2026-79608.
Fixes: d0c75dc4c0 ("x86/amd: Fix race editing DE_CFG")
Assisted-by: Sashiko + Opus 5.0
Reported-by: George Dunlap <dunlapg@umich.edu>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
(cherry picked from commit 0c5ec39d91)
For the .p_paddr, .p_vaddr, and .sh_addr fields the image load base
(passed in by command line argument) also needs taking into account. It is
_not_ merely the delta between incoming PT_NOTE and PT_LOAD segments. (The
fields aren't really used anywhere, so this is largely a cosmetic issue;
static analysis tools may be affected, though.)
Fixes: a353cab905 ("build_id: Provide ld-embedded build-ids")
Reported-by: Barr Detwix <timotheecisnard@gmail.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Ross Lagerwall <ross.lagerwall@citrix.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
master commit: 19d3c4825d
master date: 2026-09-28 14:27:11 +0200
AAM is defined in APM as
AH = (AL/10d)
AL = (AL mod 10d)
However, due to the order of operations, we're incorrectly computing it as
AL = (AL mod 10d)
AH = (AL/10d) = ((originalAL mod 10d)/10d) = 0
Fix it by reordering the operations to match what's defined in APM
and avoid the unexpected dependency between the 2 operations.
Fixes: 8993572b9c ("x86emul: fold/eliminate some local variables")
Signed-off-by: Teddy Astie <teddy.astie@vates.tech>
Reviewed-by: Andrew Cooper <andrew.cooper3@citix.com>
master commit: 4c1aba82cf
master date: 2026-09-25 14:44:27 +0100
Failing to mark Xen as Reserved in the E820 is catastrophic; RAM regions get
handed to the physical memory allocator for general use. Similarly, failure
to mark the boot modules as reserved is not going to result in a working
system.
Mark reserve_e820_ram() as __must_check, and panic() on failure. To avoid
opencoding the range in every caller, print a general failure message in
reserve_e820_ram().
Reported-by: Ross Lagerwall <ross.lagerwall@citrix.com>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Ross Lagerwall <ross.lagerwall@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
master commit: b7c0ac4467
master date: 2026-09-24 20:54:37 +0100
On hardware that supports TDX, guests can cause VMEXIT related to
TDX instructions (SEAMCALL and TDCALL) regardless of VMCS configuration.
Currently, that causes the domain to crash when a domain tries to
use these instructions in kernel-mode, and emit #UD when used in user-mode.
Adjust the behavior so that the guest always gets #UD when trying to
use these instructions regardless of the privilege level that the vCPU
is running.
In the nested virtualization case, also reinject the exit reason to L1
rather than failing on "Unhandled nested vmexit" (leading to a L1 crash
that can be caused by L2 by executing one of the TDX instructions).
Signed-off-by: Teddy Astie <teddy.astie@vates.tech>
Acked-by: Jan Beulich <jbeulich@suse.com>
master commit: 755c9fbbfe
master date: 2026-09-22 09:59:37 +0200
The Viridian spec requires the vector to be >= 0x10 when writing to the
SINTx MSR, otherwise it should #GP fault.
The spec-defined initial value is 0x10000, i.e. the vector is 0. On
startup, for some reason Windows 11 Hyper-V tries to set the MSR to
the spec-defined initial value and since the vector is 0, it GP faults.
Fix this by doing as Hyper-V does and only fault if the SINT is
unmasked.
Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
master commit: 33829ead9a
master date: 2026-09-21 10:10:22 +0200
sched_move_domain() derives the number of units to rebuild from
d->max_vcpus, which is fixed at domain creation and never rolled
back if vcpu_create() fails partway through building a domain. So
d->vcpu[i] can be NULL for some i even though max_vcpus still
counts it - this happens if sched_alloc_udata() returns NULL.
The per-unit loop doesn't check for this: it sets
unit->vcpu_list = d->vcpu[unit_id] (NULL) and hands that broken
unit straight to the destination scheduler's alloc_udata(),
which assumes vcpu_list is always valid and crashes Xen when
it is not.
Reproduced by building a domain in a non-default cpupool where
vcpu creation fails partway through, then destroying it.
domain_kill() moves the domain back to the default cpupool via
sched_move_domain() before actually destroying it, crashing
inside the destination scheduler's alloc_udata() (seen in
Credit2's csched2_alloc_udata() -> is_idle_unit() -> NULL deref).
Before building a unit in sched_move_domain(), check whether all
vpcu slots belonging to that unit are populated. If any of its
vpcus is missing:
- For a dying domain, skip the unit allocation.
- For an active domain, abort the move and return -EINVAL to
prevent running with dropped vCPUs.
Fixes: 70fadc4163 ("xen/cpupool: support moving domain between cpupools with different granularity")
Signed-off-by: Furkan Caliskan <frn1furkan10@gmail.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
master commit: 4835c078e5
master date: 2026-09-21 09:54:12 +0200
Introduce a specific check that prevents an accesses from spilling across
two devices.
Signed-off-by: Roger Pau Monné <roger@xenproject.org>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Stewart Hildebrand <stewart.hildebrand@amd.com>
master commit: 6acdfad3da
master date: 2026-08-26 11:50:42 +0200
When creating a domain on ARM, and passing XEN_DOMCTL_CONFIG_GIC_NATIVE
for the gic_version field in the struct xen_arch_domainconfig,
arch_sanitise_domain_config() resolves this to the approrpiate GIC_V2 or
GIC_V3 version the domain actually has, based on the host's
gic_hw_version(). That value is stored in the domain as
d->arch.vgic.version, but can't be queried through any other domctl
later. Toolstacks that create and build a domain in the same call
already have this info from the createdomain reply and never need to ask
again.
Toolstacks that create a domain and build it later from a separate
process do need to ask again. But, the ARM implementation only fills in
info->flags and info->gpaddr_bits. info->arch_config is left zeroed, so
XEN_DOMCTL_getdomaininfo always reports gic_version as
XEN_DOMCTL_CONFIG_GIC_NATIVE (0) regardless of what was actually
configured earlier.
Signed-off-by: Julian Vetter <julian.vetter@vates.tech>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Michal Orzel <michal.orzel@amd.com>
(cherry picked from commit adbbbd47a1)
decode_fsc() derives the fault level from the low two bits of the FSC, so
level 0 is a valid output: FSC_FLT_TRANS is 0x04, i.e. "translation fault,
level 0 or translation table base register".
This is reachable on arm64 because xen_pgtable is the zeroeth-level root,
but fsc_level_str() has no case for it and prints " (level invalid)"
instead. At the time the function was created Xen used only three levels.
Add the missing case. On arm32 the zeroeth level does not exist but FSC
0 denotes address size fault at translation table base register.
While at it, make decode_fsc() decode also address size faults.
Signed-off-by: Michal Orzel <michal.orzel@amd.com>
Reviewed-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
(cherry picked from commit 4e1f58ea1a)
On ARMv8.4-A and newer platforms, booting Dom0 Linux with ACPI enabled
causes the domain to probe advanced PMU feature based on system ID
register ID_AA64DFR0_EL1. During this probe, Linux accesses PMMIR_EL1,
which causes unhandled register traps and crashes the domain.
To address this issue, implement the following:
- Add emulation for ID_AA64DFR{0,1}_EL1, ID_DFR{0,1}_EL1 and
ID_DFR{0,1} register accesses for guest domains.
- Hide PMU registers from a guest domain when its vPMU feature is
disabled.
- Proactively make SPE, TRBE, BRBE, Trace Extensions, SPMU, ITE and
EBEP inaccessible to arm64 guest domains and hide TraceFilt,
MMapTrc and CopTrc to arm32 guest domains, as they could
potentially cause similar issues.
Fixes: dbb948110a ("xen: Expose the PMU to the guests")
Fixes: 07b9acea11 ("xen/arm: Add handler for ID registers on arm64")
Fixes: 3669a1cb95 ("xen/arm: create a cpuinfo structure for guest")
Signed-off-by: Hirokazu Takahashi <taka@valinux.co.jp>
Reviewed-by: Michal Orzel <michal.orzel@amd.com>
(cherry picked from commit b836ef686e)
The comments on the PMINTENSET/PMINTENCLR cases claim that an EL0 access
may be trapped to EL2 when MDCR_EL2.TPM is set, and that such a case is
handled. Both are inaccurate. PMINTENSET_EL1/PMINTENCLR_EL1 are accessible
at EL1 and above only, with no enable making them accessible at EL0.
Arm ARM (DDI 0487M.b) D1.4.5.6 "Prioritization of Synchronous
exceptions" orders the two exceptions. An access that is never
accessible at the current Exception level regardless of any enables or
traps is priority 18, whereas an exception taken to EL2 as the result of
a configuration control in MDCR_EL2 is priority 24. An EL0 access is
therefore UNDEFINED and taken to EL1.
Signed-off-by: Michal Orzel <michal.orzel@amd.com>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
(cherry picked from commit 87a8a5728e)
The GICv3 secondary_init() callback can fail while discovering or
waking a Redistributor, enabling LPIs, or setting up an ITS collection.
gic_init_secondary_cpu() currently discards that status. start_secondary()
then marks the CPU online even though its per-CPU GIC interface may be
unusable.
Return the callback status through the common GIC layer. Have
start_secondary() report the failure and stop the affected CPU before it
updates system features or is added to cpu_online_map.
Fixes: bc183a0235 ("xen/arm: Add support for GIC v3")
Signed-off-by: Mykola Kvach <mykola_kvach@epam.com>
Reviewed-by: Michal Orzel <michal.orzel@amd.com>
(cherry picked from commit 0102b592f4)
process_domain_node() parses "xen,static-mem" regardless of
CONFIG_STATIC_MEMORY. With the feature off, init_staticmem_pages() is a
no-op stub, so boot carries on until construct_domU() reaches the
ASSERT_UNREACHABLE() stubs of allocate_static_memory() /
assign_static_memory_11(): a debug build trips the assertion, a production
build gives the domain no memory at all.
Bail out at parse time instead, like process_shm_node() already does for
CONFIG_STATIC_SHM.
Fixes: 41c031ff43 ("xen/arm: introduce domain on Static Allocation")
Signed-off-by: Michal Orzel <michal.orzel@amd.com>
Acked-by: Bertrand Marquis <bertrand.marquis@arm.com>
(cherry picked from commit e888192d13)
PSR_GUEST64_INIT currently masks SError, IRQ and FIQ, but leaves debug
exceptions unmasked. Both the AArch64 Linux boot protocol and PSCI entry
requirements expect PSTATE.DAIF to be masked.
Add PSR_DBG_MASK to PSR_GUEST64_INIT. This fixes the initial AArch64 guest
entry state as well as virtual PSCI CPU_ON and SYSTEM_SUSPEND resume entry.
Signed-off-by: Mykola Kvach <mykola_kvach@epam.com>
Reviewed-by: Julien Grall <julien@xen.org>
(cherry picked from commit ad8663a75a)
Recent Clang objects to types differing between alias and aliasee. Accept
the unnecessary overhead and make the two compat stubs real functions.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
master commit: 5df9425a73
master date: 2026-09-09 14:15:15 +0200
.data.rel.ro really is merely a special case of .rodata: r/o data, but
with runtime relocations (not relevant to Xen), i.e. r/o only after
relocations were performed (by the dynamic loader).
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
master commit: f7eab298bb
master date: 2026-09-08 09:50:48 +0200
Recent Clang complains about the "debug" static variable only ever being
written to. Drop it and the command line option controlling it.
Fixes: 19ab8356ab ("tools: remove support for running a guest with qemu-traditional")
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Roger Pau Monné <roger@xenproject.org>
master commit: f907784c32
master date: 2026-09-07 14:11:35 +0200
The requested PCI segment needs including in the call to
xsm_pci_config_permission(). Otherwise in a multi-segment system we can check
the perimssions on one device but operate on a different one.
This is only not a vulnerability because pci_conf_write_intercept() is only
reachable by the hardware domain.
Fixes: 300bb048ca ("x86/PCI: make all config space writes subject to XSM checking")
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Daniel P. Smith <dpsmith@apertussolutions.com>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
master commit: b4a671acf1
master date: 2026-09-03 09:45:16 +0100
sched_init_vcpu() calls init_timer() for a vcpu's periodic_timer,
singleshot_timer and poll_timer before it can fail -- these
become live, linked into their target pCPU's per-cpu timer list
regardless of what happens next. If the sched_alloc_udata() call
further down then fails, the function frees the sched_unit via
sched_free_unit() and returns 1, but never unlinks these three
timers.
The caller, vcpu_create(), makes this worse: on sched_init_vcpu()
returning nonzero it jumps to fail_wq, skipping fail_sched and
thus sched_destroy_vcpu() -- the only function on this path that
calls kill_timer() on them. vcpu_destroy() then frees the vcpu,
and the three timers embedded in it, while they are still linked
into that shared list.
This silently corrupts that list. It only shows up later, when
something else touches a neighboring timer: sched_move_domain()
crashed with "Assertion 'entry->prev->next == entry' failed" on a
completely unrelated, valid vcpu's timer.
Call sched_destroy_vcpu() in sched_init_vcpu()'s own failure
branch instead of sched_free_unit(), so it doesn't depend
on the caller reaching sched_destroy_vcpu() to undo what it set
up itself. sched_destroy_vcpu() assumes unit->priv is set, which
is not the case here, so make it only free the udata and remove
the unit if unit->priv in non-NULL.
Fixes: d884b10778 ("Domain creation/destruction cleanups.")
Signed-off-by: Furkan Caliskan <frn1furkan10@gmail.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
master commit: 2565341135
master date: 2026-09-01 10:02:13 +0200
It's possible for domains to generate unaligned PCI config space accesses
when using ECAM, and hence vPCI should support those at least for the
hardware domain. Such unaligned accesses to the PCI config space have been
reported to come from ACPI logic.
Relax the checking in vpci_access_allowed() to allow such accesses for the
hardware domain, and fix the handling in pci_conf_{read,write}{16,32}() to
fulfill them using MMCFG.
MMCFG regions are identity exposed to the hardware domain, and hence such
unaligned accesses can only come as a result of the host having MMCFG in the
first place, as otherwise MMCFG won't be exposed to the hardware domain
either.
Note that vpci_ecam_{read,write}() already refuse accesses that cross a
device boundary unconditionally.
Reported-by: Jason Andryuk <jason.andryuk@amd.com>
Signed-off-by: Roger Pau Monné <roger@xenproject.org>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Stewart Hildebrand <stewart.hildebrand@amd.com>
master commit: 79175b1390
master date: 2026-08-26 11:50:42 +0200
oxenstored maintains two datastructures about watches; one global trie, and
one hashtable tracked per domain. Both need keeping in sync, and right now
the global trie is not emptied when a xenbus reconnect is requested.
This is basically the same bug as XSA-330, commit 491a077ed4
("tools/ocaml/xenstored: delete watch from trie too when resetting watches"),
just tickled via another path.
Arrange for both Process.do_reset_watches() and Process.do_reconnect() to
share a common codepath for the resetting of watches and transactions.
Notably, this means that the latter now calls Connections.del_watches() which
clears the global trie too.
Connections.del_watches() already calls Connection.del_watches() so remove the
re-clearing of the state from Connection.do_reconnect().
Move History.trim() into reset_watches_and_transactions() so it's on the
common path, and place it after removing the transactions rather than before.
This is part of XSA-512 / CVE-2026-79604.
Reported-by: David Korczynski <David@Adalogics.com>
Fixes: 674ad2be40 ("xenstore: extend the xenstore ring with a 'closing' signal")
Signed-off-by: Andrii Sultanov <andriy.sultanov@vates.tech>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Andrii Sultanov <andriy.sultanov@vates.tech>
(cherry picked from commit a2ca4f8b98)
The logic flow here is complicated. In preparation to fix a bug, factor out
reconnecting a xenbus connection, and fold History.reconnect into it's single
caller.
No functional change.
This is part of XSA-512 / CVE-2026-79604.
Signed-off-by: Andrii Sultanov <andriy.sultanov@vates.tech>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Andrii Sultanov <andriy.sultanov@vates.tech>
(cherry picked from commit 9c5a46b120)
The current way in which idle TLB flush and TLB flushing when allocating a
page are done allows for the scrubbing to be done ahead of the TLB flush.
A PV domain can still have a TLB entry for the page after scrubbing, and
hence it may be able to modify it. Such unintended page accessing allows
domains to possibly exchange information even when `xsm=silo scrub-domheap`
are in effect.
Remove the MEMF_no_tlbflush memory allocation flag, and reorder the
flushing so it's always done ahead of the scrubbing in
alloc_{,color_}heap_pages(). The sole user of MEMF_no_tlbflush is
populate_physmap(), and given the constrains above it's no longer safe
to defer the flush, hence the flag removal and the folding of the flush in
the allocator function itself.
This is XSA-511 / CVE-2026-79603.
Fixes: 24f1a58d19 ("mm: option to _always_ scrub freed domheap pages")
Signed-off-by: Roger Pau Monné <roger@xenproject.org>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
(cherry picked from commit ed7e656e6c)
hvm_io_intercept() can return X86EMUL_RETRY, and as such it needs to be
handled in the switch in hvmemul_do_io() to avoid triggering the BUG() from
the default case.
Reset the vCPU state to no in-flight IOREQ and return X86EMUL_RETRY so that
the access is retried.
This is XSA-510 / CVE-2026-79602.
Reported-by: Jiqian Chen <Jiqian.Chen@amd.com>
Signed-off-by: Roger Pau Monné <roger@xenproject.org>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
(cherry picked from commit 62aff07326)
DMs may invoke XEN_DOMCTL_bind_pt_irq for domains already under
destruction. When XEN_DOMCTL_bind_pt_irq is invoked after
pci_release_devices() (invoked from underneath domain_kill()) had already
completed, it would allocate hvm_domain_irq(d)->dpci anew, without that
ever being freed during subsequent domain cleanup.
Leverage evtchn_destroy()'s kind-of-spin-barrier, allowing to simply check
->is_dying with the domain's event lock held.
This is XSA-509 / CVE-2026-62437.
Fixes: 7a26b541a2 ("vtd: Dynamically allocate IRQ-tracking structures, only for those")
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
(cherry picked from commit 328a146143)
Right now it's only checked in setup_p4_watchdog(), and not in
setup_p6_watchdog().
Perform the check in the common Intel path in setup_apic_nmi_watchdog(), and
pass misc_enable as a parameter into setup_p4_watchdog() to avoid reading it
twice.
Fixes: 0dfba864fb ("NMI watchdog support in Xen.")
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
master commit: dfb428cb11
master date: 2026-08-18 12:51:08 +0100
It used to be the case that cpu_data[] inherited the BSP's cpuid_level until
the AP had calculated it itself. Following the rework, cpuid_level has a
placeholder 1 until it is calculated properly.
setup_apic_nmi_watchdog() happens to be called on the BSP after SMP bring-up,
meaning that the first call is on CPU1. It is also positioned in the window
where cpu_data[] is wrong.
As a result, setup_p6_watchdog()'s one-time calculation of the performance
counter width falls back into Pentium compatibility mode assuming 32bit
counters. This causes a watchdog NMI which is delayed a little (e.g. from an
SMI), to appear as if it hadn't overflowed, and therefore be considered as not
a watchdog NMI. On systems where unknown NMIs are treated as fatal, this
results in a spurious crash.
Switch setup_p6_watchdog() to use boot_cpu_data.cpuid_level, which is how this
is checked almost everywhere else.
core2_vpmu_init() used the same pattern to look at leaf 0xa. Despite being
init code and only running on the BSP, {boot,current}_cpu_data are different
objects, so switch it over to checking boot_cpu_data.cpuid_level too.
Fixes: 7126b7f806 ("x86/CPU: re-work populating of cpu_data[]")
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
master commit: dc5a77c6c4
master date: 2026-08-17 18:46:08 +0100
Radix trees are in principle usable as soon as memory allocation works.
(Radix trees with only index 0 populated are usable even earlier.) If only
there wasn't height_to_maxindex[], which is filled only by a pre-SMP
initcall. The benefit of this array is rather limited - the calculations
done by __maxindex() can as well be done by radix_tree_maxindex(); the
overhead isn't all this high.
This was found by UBSAN on a multi-segment system:
(XEN) UBSAN: Undefined behaviour in common/radix-tree.c:83:27
(XEN) index 12 is out of range for type 'long unsigned int [12]'
...
(XEN) Xen call trace:
(XEN) [<ffff82d040323f9c>] R common/ubsan/ubsan.c#ubsan_epilogue+0xa/0xd5
(XEN) [<ffff82d040324d91>] F __ubsan_handle_out_of_bounds+0x9d/0xd4
(XEN) [<ffff82d04029265a>] F radix_tree_insert+0x24d/0x570
(XEN) [<ffff82d04037ac3e>] F drivers/passthrough/pci.c#alloc_pseg+0xc4/0x165
(XEN) [<ffff82d040a3b526>] F pci_add_segment+0xc/0x1b
(XEN) [<ffff82d040a5ad1b>] F acpi_parse_mcfg+0x29b/0x344
(XEN) [<ffff82d040a3f612>] F acpi_table_parse+0x5d/0x92
(XEN) [<ffff82d040a5bf55>] F acpi_mmcfg_init+0x3a2/0x71d
(XEN) [<ffff82d040a71ba6>] F pci_setup+0x17/0x29
(XEN) [<ffff82d040a784d0>] F __start_xen+0x394c/0x4ed8
(XEN) [<ffff82d040423057>] F __high_start+0xb7/0xb8
Fixes: 21844b0e32 ("PCI multi-seg: introduce notion of PCI segments")
Fixes: 8dc6738dbb ("Update radix-tree.[ch] from upstream Linux to gain RCU awareness")
Reported-by: Andrew Cooper <andrew.cooper3@citrix.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
master commit: 1077a93425
master date: 2026-08-05 12:00:17 +0200
The size passed to array_index_nospec() in evtchn_fifo_word_from_port()
doesn't match the value it is meant to clamp.
Fix it by clamping the port to a safe interval and use that value to
calculate the event_array[] index.
Fixes: 443d3ab6da ("evtchn: block speculative out-of-bound accesses")
Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
master commit: 3a6cb6aae4
master date: 2026-08-03 09:50:07 +0200
With the introduction of core scheduling, cpus not used by any cpupool
have been switched to use the very simple idle scheduler instead of the
default scheduler.
Trying to obtain diagnostic scheduling data via the "r" debug key is
scanning through all cpupools using the per-cpupool scheduler to print
the related data. Unfortunately the switch to use the idle scheduler
for free cpus wasn't reflected in schedule_dump(), causing the default
scheduler's dump_cpu_state callback to be used for free cpus.
This causes NULL dereferences in case the default scheduler is one of
credit or null.
Fix that by using the idle scheduler instead of the default scheduler
for free cpus. Note that it is fine for a scheduler to have no
dump_cpu_state callback.
Fixes: f855dd9625 ("sched: add minimalistic idle scheduler for free cpus")
Reported-by: Dietmar Hahn <dietmar.hahn@fujitsu.com>
Tested-by: Dietmar Hahn <dietmar.hahn@fujitsu.com>
Signed-off-by: Juergen Gross <jgross@suse.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
master commit: f38e8cb85a
master date: 2026-07-29 14:41:22 +0100
When removing a CPU from a cpupool running the credit scheduler, a
race might happen between schedule_cpu_rm() and csched_timer(),
resulting in a NULL dereference.
The timer associated with csched_timer() is killed only in
csched_deinit_pdata(), which is called by schedule_cpu_rm() after
setting the scheduler's per-cpu data to NULL AND after enabling
interrupts again. This can result in the timer firing before being
killed, so csched_timer() needs to test the per-cpu data being set
before accessing it.
Fixes: 78be3dbbfe ("cpupools [1/6]: hypervisor changes")
Reported-by: Dietmar Hahn <dietmar.hahn@fujitsu.com>
Signed-off-by: Juergen Gross <jgross@suse.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
master commit: ea1d785a5f
master date: 2026-07-29 14:41:22 +0100
schedule_cpu_rm() clears the cpupool pointer of the scheduling
resource before calling sched_deinit_pdata():
sr->cpupool = NULL;
...
sched_deinit_pdata(data->old_ops, data->ppriv_old, cpu);
For RTDS, rt_deinit_pdata() calls move_repl_timer() when the
replenishment timer lives on the cpu being removed, and
move_repl_timer() dereferences get_sched_res(old_cpu)->cpupool
without checking it for NULL. Removing a pCPU owning the timer from
an RTDS cpupool therefore dereferences NULL + 0x10 (the res_valid
member) and panics:
(XEN) Data Abort Trap. Syndrome=0x1c28005
(XEN) Walking Hypervisor VA 0x10 on CPU0 via TTBR ...
(XEN) Xen call trace:
(XEN) [<...>] find_next_bit+0x74/0xa8 (PC)
(XEN) [<...>] rt.c#move_repl_timer+0xb8/0xec (LR)
(XEN)
(XEN) Panic on CPU 0:
(XEN) CPU0: Unexpected Trap: Data Abort
Reproducer, on any host with at least 2 pCPUs and RTDS compiled in
(observed on arm64, but the path is common code):
xl cpupool-create name="test" sched="rtds"
xl cpupool-cpu-remove Pool-0 1
xl cpupool-cpu-add test 1
xl cpupool-cpu-remove test 1
The last command moves the RTDS replenishment timer to cpu1 (first
and only cpu of the pool) and then removes cpu1, hitting the NULL
dereference in the sched_deinit_pdata() callback.
Use the cpupool back-pointer of the scheduler instead of the one of
the scheduling resource. It is set by cpupool_create() before any
pCPU can be assigned to the pool and stays valid for the whole
lifetime of the scheduler, so it is still available when
rt_deinit_pdata() runs. Other schedulers already rely on it the same
way, e.g. credit2 in cpu_add_to_runqueue().
Fixes: b6f5334aea ("sched: fix cpu offlining with core scheduling")
Signed-off-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
master commit: f294e3abe4
master date: 2026-07-21 09:47:36 +0200
Add the missing ARM logic, populating xen_arm_arch_domainconfig
from the raw xc_domaininfo_t the same way the x86 branch does for
xen_x86_arch_domainconfig.
Fixes: 9d683b5e37 ("tools/ocaml: Expose arch_config in domaininfo")
Fixes: 81838c9067 ("ocaml: fix arm build")
Signed-off-by: Julian Vetter <julian.vetter@vates.tech>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Teddy Astie <teddy.astie@vates.tech>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
(cherry picked from commit 01b4b39e2e)
The Store_field(result, 16, arch_config) sits inside an #ifdef x86, meaning
that on other architectures the pointer is not filled in. Ocaml code then
falls over a NULL(ish) pointer (really the Val_unit used to initialise
'result') when the layout in the heap doesn't match the type system.
Rearrange alloc_domaininfo() to avoid this. Similarly to
physinfo_arch_caps(), raise an exception if the architecture code hasn't
filled in an appropriate tag. Move the setup of arch_domainconfig to be
common logic.
In order to simplify the addition of other architectures, remove the
arch_config variable (reusing tmp as it's touched exactly once), and rename
x86_arch_config to be arch_config so each architecture can fill in a suitable
one without needing more local variables.
Fixes: 9d683b5e37 ("tools/ocaml: Expose arch_config in domaininfo")
Fixes: 81838c9067 ("ocaml: fix arm build")
Reported-by: Julian Vetter <julian.vetter@vates.tech>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Teddy Astie <teddy.astie@vates.tech>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
(cherry picked from commit 365d2a5be3)
XSA-443 and XSA-497 addressed specific issues in specific file system
drivers (libfsimage) used by pygrub. Further issues were reported, and yet
more are to be expected. XSA-443 introduced a means to run pygrub de-
privileged. Only this mode of operation is security supported from now on.
This is XSA-508.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
(cherry picked from commit 75f920bd47)
When doing PoD cache reclaim as part of a decrease reservation call, avoid
reclaiming special pages for the PoD cache. Otherwise such pages get moved
from the domain ->xenpage_list to the ->page_list, while still being
referenced in ->shared_info domain field.
Prevent PoD cache from reclaiming special pages, as nothing good can come
out of it.
This is XSA-507 / CVE-2026-62434.
Fixes: 41aa0b6269 ("PoD memory 4/9: Decrease reservation")
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
(cherry picked from commit 372497ce42)
The hypercall requires at least one input buffer, as both arch-specific
implementations of dm_op() unconditionally assume ->buf[0] to be valid (and
not stack rubble).
Additionally, XEN_DMOP_modified_memory requires two input buffers, yet the
code was assuming the second buffer to always be provided by the user when
checking for the number of extents. In case the caller sets nr_bufs to 1,
the code in modified_memory() will read stack garbage as the size of the
buffer, thus allowing the caller some degree of insight on the contents of
the stack by probing whether the hypercall returns -EINVAL or -EFAULT as a
result of such bogus call.
This is XSA-506 / CVE-2026-62433.
Fixes: e3b93b3c59 ("dmop: add xendevicemodel_modified_memory_bulk()")
Fixes: 85cb15dfe4 ("x86/hvm/dmop: only copy what is needed to/from the guest")
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
(cherry picked from commit aef948a300)
evtchn_fifo_expand_array() will check for the domain evtchn_fifo being
populated without holding the event_lock, which can lead to a race with a
concurrent evtchn_reset().
Ensure the checking for evtchn_fifo presence is done while holding the
event_lock.
This is XSA-505 / CVE-2026-62432.
Fixes: 400b3bd642 ("evtchn: make EVTCHNOP_reset suitable for kexec")
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
(cherry picked from commit 0e9d647aca)
Otherwise in periodic mode a division by 0 would happen on the second call
to start_stimer() when using periodic mode.
Note that the HyperV specification states: "Writing the value zero to the
Count register will stop the counter, thereby disabling the timer,
independent of the setting of AutoEnable in the configuration register."
so a timer with a 0 count should never be in the enabled state.
This is XSA-504 / CVE-2026-62431.
Fixes: 26fba3c855 ("viridian: add implementation of synthetic timers")
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
(cherry picked from commit ff7d9aa77e)
Do the checking for a valid CMOS index while holding the spinlock,
otherwise the value could be changed by the guest after having been
checked.
This is XSA-503 / CVE-2026-62430.
Fixes: 34bef0e6d5 ("hvm: Add locking to platform timers.")
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
(cherry picked from commit 52350da926)
Calling vnuma_destroy() without any locking can race the handling of both
XENMEM_get_vnumainfo and XEN_DOMCTL_setvnumainfo. While the latter is,
without Flask, strictly only exposed to the control domain, the former
can also be invoked by a stubdom DM or a de-privileged DM running in the
control domain. Isolate the logic used by XEN_DOMCTL_setvnumainfo into a
new helper function, which then is also used from domain_kill(). While
doing so also move the vnuma_destroy() invocation out of the locked
region.
With d->vnuma properly cleared by domain_kill(), XENMEM_get_vnumainfo now
really only needs to check for the field being NULL. That check needs
repeating, though, after re-acquiring the lock.
This is CVE-2026-62429 / XSA-502.
Fixes: 9695014966 ("xen: vnuma topology and subop hypercalls")
Reported-by: Teddy Astie <teddy.astie@vates.tech>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
(cherry picked from commit 2afa6fea9d)