Commit Graph
48547 Commits
Author SHA1 Message Date
Jan Beulich b3bf1a021b x86/mkelf32: correct VA/PA of PT_NOTE / .note
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
2026-09-30 13:08:24 +02:00
Teddy Astie b3b2fce742 x86emul: Fix AAM emulation AH output
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
2026-09-30 13:08:07 +02:00
Andrew Cooper c2a0004aba x86/boot: Force error checking for reserve_e820_ram()
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
2026-09-30 13:07:47 +02:00
Teddy Astie 9f993bafc3 vmx: Handle TDX instruction exit reasons
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
2026-09-30 13:07:25 +02:00
Ross Lagerwall fd0eb50604 x86/viridian: Workaround Hyper-V GP fault writing to MSR
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
2026-09-30 13:06:58 +02:00
Furkan Caliskan b85247239d xen/sched: core: skip missing vcpu slots in sched_move_domain()
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
2026-09-30 13:06:39 +02:00
Roger Pau Monné 47f84fcb06 x86/pci: prevent cross-device accesses in pci_mmcfg_{read,write}()
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
2026-09-30 13:06:08 +02:00
Julian Vetter f9c21d1718 xen/arm: report proper GIC version via XEN_DOMCTL_getdomaininfo
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)
2026-09-21 14:04:44 +02:00
Michal Orzel c1a06e5121 xen/arm: traps: report level 0 faults in panic_PAR()
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)
2026-09-21 14:04:44 +02:00
Hirokazu Takahashi 80bc532b38 xen/arm: Hide PMU registers from the guest, when the vPMU feature is disabled
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)
2026-09-21 14:04:44 +02:00
Michal Orzel 1633c8148a xen/arm: drop incorrect EL0 accessibility comments for PMINTEN{SET,CLR}
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)
2026-09-21 14:04:44 +02:00
Mykola Kvach 99cdf4a4d4 xen/arm: propagate secondary GIC initialization failures
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)
2026-09-21 14:04:44 +02:00
Michal Orzel ec0c241602 xen/dt: reject "xen,static-mem" when CONFIG_STATIC_MEMORY is disabled
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>
[michal: adjust for code movement]
(cherry picked from commit e888192d13)
2026-09-21 14:04:11 +02:00
Mykola Kvach 75f866e9f7 xen/arm: mask debug exceptions in initial AArch64 guest state
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)
2026-09-21 14:00:01 +02:00
Andrew Cooper afd8175444 x86/ucode: Work around Granite Rapids erraturm GNR98
Block loads which are known to hang the system.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Teddy Astie <teddy.astie@vates.tech>
Reviewed-by: Roger Pau Monné <roger@xenproject.org>
Acked-by: Jan Beulich <jbeulich@suse.com>
master commit: 70cbd9a08d
master date: 2026-09-09 18:07:32 +0100
2026-09-10 12:40:03 +02:00
Jan Beulich 568e954b5a EFI: don't use alias attribute for compat hypercall stubs
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
2026-09-10 12:39:45 +02:00
Jan Beulich 754fda48d3 build: also exclude .data.rel.ro in $(cmd_obj_init_o)
.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
2026-09-10 12:39:35 +02:00
Andrew Cooper 3cf9223bbd x86/pci: Perform XSM checks on the correct device in pci_conf_write_intercept()
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
2026-09-10 12:39:18 +02:00
Furkan Caliskan e2ca9c64ca xen/sched: core: kill unarmed timers on sched_init_vcpu() failure
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
2026-09-10 12:39:00 +02:00
Roger Pau Monné 5c61919058 xen/vpci: allow unaligned accesses by the hardware domain
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
2026-09-10 12:38:34 +02:00
Andrii Sultanov 08daadcf1f oxenstored: Reset the watches trie on domain reconnect
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)
2026-08-26 17:49:40 +01:00
Andrii Sultanov d40ecc7950 oxenstored: Factor out Process.do_reconnect()
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)
2026-08-26 17:49:40 +01:00
Roger Pau Monne bd0a1cf020 xen/page_alloc: ensure TLB flush is done ahead of page scrubbing
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)
2026-08-26 17:49:40 +01:00
Roger Pau Monne 1514f2808b x86/emul: cope with internal handlers returning X86EMUL_RETRY
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)
2026-08-26 17:49:40 +01:00
Jan Beulich b26451ec71 x86/pass-through: disallow pt_irq_create_bind() on dying domains
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)
2026-08-26 17:49:40 +01:00
Andrew Cooper 7b7f5be456 x86/nmi: Check MSR_MISC_ENABLE for all Intel platforms
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
2026-08-24 11:55:13 +02:00
Jan Beulich 88c2d7324b radix-tree: drop radix_tree_init_maxindex()
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
2026-08-24 11:54:59 +02:00
Juergen Gross d3eddf948f xen/evtchn: fix wrong usage of array_index_nospec()
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
2026-08-24 11:54:36 +02:00
Juergen Gross ee3befc2cd xen/sched: fix schedule_dump() handling of free cpus
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
2026-08-24 11:54:22 +02:00
Juergen Gross da5a2144bb xen/credit: fix race with schedule_cpu_rm() in csched_timer()
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
2026-08-24 11:54:05 +02:00
Oleksii Moisieiev 934897ea5e xen/sched: rt: fix NULL cpupool dereference in move_repl_timer()
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
2026-08-24 11:53:49 +02:00
Jan Beulich 2862edcacd update Xen version to 4.20.5-pre 2026-08-24 11:53:22 +02:00
Jan Beulich 9611e26eff update Xen version to 4.20.4 RELEASE-4.20.4 2026-07-29 17:18:52 +02:00
Julian Vetter 1b917fef1a tools/ocaml: Fill arch_config for ARM in domain_getinfo{,list}()
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)
2026-07-29 13:46:53 +01:00
Andrew Cooper 9f4431e6d1 tools/ocaml: Fix crash in Xenctrl.domain_getinfo{,list}() on ARM
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)
2026-07-29 13:46:53 +01:00
Jan Beulich c42374a105 pygrub: security-supported only when run de-privileged
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)
2026-07-28 13:08:27 +01:00
Roger Pau Monne 4314e6ded0 x86/pod: do not reclaim special pages for PoD cache
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)
2026-07-28 13:08:27 +01:00
Roger Pau Monne d05f4c9832 xen/dmop: check number of input buffers
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)
2026-07-28 13:08:27 +01:00
Roger Pau Monne 96f4c9df24 xen/evtchn: fix race between FIFO expand and reset operations
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)
2026-07-28 13:08:27 +01:00
Roger Pau Monne be02aa3f4a x86/viridian: ensure count is always set when starting a timer
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)
2026-07-28 13:08:27 +01:00
Roger Pau Monne 8ecf1dc325 x86/vrtc: fix race in CMOS index checking
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)
2026-07-28 13:08:27 +01:00
Jan Beulich 8a37bfe876 vNUMA: close race window in domain cleanup
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)
2026-07-28 13:08:27 +01:00
Jan Beulich 35e4a6ae4d gnttab: cope with version changes racing other operations
Dropping and re-acquiring the grant table lock for a particular operation
requires special care, as in the meantime the grant table version can
change.

During a v2 -> v1 change, status frames going away means that pre-
calculated status pointers go stale, referencing freed (and possibly
already re-used) memory. Record in-flight v2 operations, permitting the
version change only when there are none of them. Recalculate "status" in
the one place (map_grant_ref()'s error path) where it could be stale, but
confine this to reserved entries.

This is CVE-2026-62436.

Reported-by: Mark Esler <mark@hexproof.dev>

During a v1 -> v2 change, the number of shared table entries reduces,
meaning that previously validated grant references may now be out of
bounds. Because of the checking of pin counts in gnttab_set_version()
(with the grant table lock held for writing), for now-out-of-bounds gref-s
neither active mappings can exist, nor can there be in-progress copy
operations. Nevertheless bounds checks are added there, just to be on the
safe side.

For gnttab_transfer(), to cover the gap between the lock being dropped by
gnttab_prepare_for_transfer() and it being re-acquired, have the helper
return the version it found, and fail the operation if the version turns
out to have changed after re-acquiring the lock.

Further avoid needless use of shared_entry_header(), as it involves
pointer arithmetic which, when using an out-of-bounds ref, is UB.

This is CVE-2026-62435.

Everything together is XSA-501.

Fixes: a98dc13703 ("Introduce a grant_entry_v2 structure")
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Tested-by: Mark Esler <mark@hexproof.dev>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
(cherry picked from commit 96dfeb4177)
2026-07-28 13:08:27 +01:00
Jan Beulich 42093dac70 gnttab: check values against active entry when copying an already-pinned one
acquire_grant_for_copy() passes to its caller both an MFN and a struct
page_info *. The two really need to be in sync for the get_page()
underlying get_paged_frame() and get_page_type() (both acting on the
passed back struct page_info *) and the map_domain_page() (acting on the
passed back MFN) to achieve the intended effect.

Go further and also check other properties: GTF_transitive / GTF_sub_page
may have been flipped in the shared entry, so respective fields / values
also may not match.

The one field which we can be sure does match (as it was checked earlier
in the function) is ->domid. Add an assertion nevertheless.

This is CVE-2026-62428 / XSA-500.

Fixes: d8cbecb1ee ("grant-tables: Use get_page_from_gfn() instead of get_gfn()/put_gfn")
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
(cherry picked from commit 61b0a59ce2)
2026-07-28 13:08:27 +01:00
Jan Beulich 1e57ed1796 sysctl/XSM: drop .page_offline() hook
Integrate the checking with xsm_sysctl(), now that it has the full op
struct passed. As a positive side effect, permissions are then checked at
the same early point with and without Flask.

This is part of CVE-2026-62426 / XSA-499.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-By: Daniel P. Smith <dpsmith@apertussolutions.com>
(cherry picked from commit 299de2aeda)
2026-07-28 13:08:27 +01:00
Jan Beulich bfc1439cd0 sysctl/XSM: drop .resource_{,un}plug_core() hooks
Integrate the checking with xsm_sysctl(), now that it has the full op
struct passed. As a positive side effect, permissions are then checked at
the same early point with and without Flask. Note that these were x86-
only, i.e. some dead/unreachable code gets eliminated for (in particular)
Arm.

This is part of CVE-2026-62426 / XSA-499.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-By: Daniel P. Smith <dpsmith@apertussolutions.com>
(cherry picked from commit 0501e1dc04)
2026-07-28 13:08:27 +01:00
Jan Beulich 0bb0f564f3 sysctl/XSM: drop .readconsole() hook
Integrate the checking with xsm_sysctl(), now that it has the full op
struct passed. As a positive side effect, permissions are then checked at
the same early point with and without Flask.

This is part of CVE-2026-62426 / XSA-499.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-By: Daniel P. Smith <dpsmith@apertussolutions.com>
(cherry picked from commit 4b249cba4b)
2026-07-28 13:08:27 +01:00
Jan Beulich 5ddc886662 sysctl/Flask: add preliminary check for XEN_SYSCTL_getdomaininfolist
To shield the sysctl lock from abuse by unauthorized domains, follow what
5154fdda11 ("domctl: protect locking for get_domain_state") did: Check
for permission to issue the operation against DOM_XEN in flask_sysctl().
The finer-grained xsm_getdomaininfo() later in the handling of the sub-op
remains unaltered.

In the in-tree policy respective permission therefore needs granting.

This is part of CVE-2026-62426 / XSA-499.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Daniel P. Smith <dpsmith@apertussolutions.com>
(cherry picked from commit 3179bf2931)
2026-07-28 13:08:27 +01:00
Jan Beulich edd856bb64 sysctl/XSM: drop .scheduler_op() hook
Integrate the checking with xsm_sysctl(), now that it has the full op
struct passed. As a positive side effect, permissions are then checked at
the same early point with and without Flask.

This is part of CVE-2026-62426 / XSA-499.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-By: Daniel P. Smith <dpsmith@apertussolutions.com>
(cherry picked from commit 751e371c91)
2026-07-28 13:08:27 +01:00
Jan Beulich 46fe95efa8 sysctl/XSM: pass full struct xen_sysctl to xsm_sysctl()
Subsequently some sub-ops will want to inspect their sub-sub-ops.

This is part of CVE-2026-62426 / XSA-499.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Daniel P. Smith <dpsmith@apertussolutions.com>
(cherry picked from commit 9f4aa6d00a)
2026-07-28 13:08:27 +01:00