Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package xen for openSUSE:Factory checked in 
at 2026-10-14 18:34:21
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/xen (Old)
 and      /work/SRC/openSUSE:Factory/.xen.new.3698736 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "xen"

Wed Oct 14 18:34:21 2026 rev:379 rq:1384649 version:4.22.0_06

Changes:
--------
--- /work/SRC/openSUSE:Factory/xen/xen.changes  2026-09-09 16:21:30.436916241 
+0200
+++ /work/SRC/openSUSE:Factory/.xen.new.3698736/xen.changes     2026-10-14 
18:34:51.739218651 +0200
@@ -1,0 +2,24 @@
+Tue Oct 13 06:05:33 MDT 2026 - [email protected]
+
+- bsc#1283315 - VUL-0: CVE-2026-79607: xen: Xenstore: Guests can
+  crash xenstored during Live Update (XSA-514)
+  6aad1183-tools-xenstored-fix-live-update-with-watches-specifying-depth.patch
+- bsc#1283317 - VUL-0: CVE-2026-79608: xen: x86/AMD: ineffectual
+  Zenbleed workaround (XSA-515)
+  6abbdd30-amd-Fix-inverted-condition-in-zenbleed_use_chickenbit.patch
+- bsc#1283321 - VUL-0: CVE-2026-79609: xen: x86: XPTI may break on
+  huge-memory systems (XSA-516)
+  6abbe079-pv-map-each-vCPUs-root-page-table-in-its-per-domain-area.patch
+- bsc#1283322 - VUL-0: CVE-2026-79610: xen: grant-table: double
+  version change race (XSA-517)
+  6abbe20c-gnttab-address-fallout-from-XSA-501.patch
+- bsc#1283323 - VUL-0: CVE-2026-79611: xen: VMX: VMentry failure
+  with branch tracing and blocked states (XSA-518)
+  6abbe28e-vmx-Rework-#DB-intercept-logic-to-fix-VMEntry-failure-with-BTF.patch
+- Upstream bug fixes (bsc#1027519)
+  6aa28713-xen-sched-core-kill-unarmed-timers-on-sched_init_vcpu-failure.patch
+  6abceba2-xen-sched-core-skip-missing-vcpu-slots-in-sched_move_domain.patch
+  6abcebd8-vmx-Handle-TDX-instruction-exit-reasons.patch
+  6abcec00-boot-Force-error-checking-for-reserve_e820_ram.patch
+
+-------------------------------------------------------------------

New:
----
  6aa28713-xen-sched-core-kill-unarmed-timers-on-sched_init_vcpu-failure.patch
  6aad1183-tools-xenstored-fix-live-update-with-watches-specifying-depth.patch
  6abbdd30-amd-Fix-inverted-condition-in-zenbleed_use_chickenbit.patch
  6abbe079-pv-map-each-vCPUs-root-page-table-in-its-per-domain-area.patch
  6abbe20c-gnttab-address-fallout-from-XSA-501.patch
  6abbe28e-vmx-Rework-#DB-intercept-logic-to-fix-VMEntry-failure-with-BTF.patch
  6abceba2-xen-sched-core-skip-missing-vcpu-slots-in-sched_move_domain.patch
  6abcebd8-vmx-Handle-TDX-instruction-exit-reasons.patch
  6abcec00-boot-Force-error-checking-for-reserve_e820_ram.patch

----------(New B)----------
  New:- Upstream bug fixes (bsc#1027519)
  6aa28713-xen-sched-core-kill-unarmed-timers-on-sched_init_vcpu-failure.patch
  6abceba2-xen-sched-core-skip-missing-vcpu-slots-in-sched_move_domain.patch
  New:  crash xenstored during Live Update (XSA-514)
  6aad1183-tools-xenstored-fix-live-update-with-watches-specifying-depth.patch
- bsc#1283317 - VUL-0: CVE-2026-79608: xen: x86/AMD: ineffectual
  New:  Zenbleed workaround (XSA-515)
  6abbdd30-amd-Fix-inverted-condition-in-zenbleed_use_chickenbit.patch
- bsc#1283321 - VUL-0: CVE-2026-79609: xen: x86: XPTI may break on
  New:  huge-memory systems (XSA-516)
  6abbe079-pv-map-each-vCPUs-root-page-table-in-its-per-domain-area.patch
- bsc#1283322 - VUL-0: CVE-2026-79610: xen: grant-table: double
  New:  version change race (XSA-517)
  6abbe20c-gnttab-address-fallout-from-XSA-501.patch
- bsc#1283323 - VUL-0: CVE-2026-79611: xen: VMX: VMentry failure
  New:  with branch tracing and blocked states (XSA-518)
  6abbe28e-vmx-Rework-#DB-intercept-logic-to-fix-VMEntry-failure-with-BTF.patch
- Upstream bug fixes (bsc#1027519)
  New:  
6aa28713-xen-sched-core-kill-unarmed-timers-on-sched_init_vcpu-failure.patch
  6abceba2-xen-sched-core-skip-missing-vcpu-slots-in-sched_move_domain.patch
  6abcebd8-vmx-Handle-TDX-instruction-exit-reasons.patch
  New:  
6abceba2-xen-sched-core-skip-missing-vcpu-slots-in-sched_move_domain.patch
  6abcebd8-vmx-Handle-TDX-instruction-exit-reasons.patch
  6abcec00-boot-Force-error-checking-for-reserve_e820_ram.patch
  New:  6abcebd8-vmx-Handle-TDX-instruction-exit-reasons.patch
  6abcec00-boot-Force-error-checking-for-reserve_e820_ram.patch
----------(New E)----------

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ xen.spec ++++++
--- /var/tmp/diff_new_pack.8oMrtz/_old  2026-10-14 18:34:55.486375715 +0200
+++ /var/tmp/diff_new_pack.8oMrtz/_new  2026-10-14 18:34:55.488375799 +0200
@@ -126,7 +126,7 @@
 BuildRequires:  python-rpm-macros
 Provides:       installhint(reboot-needed)
 
-Version:        4.22.0_04
+Version:        4.22.0_06
 Release:        0
 Summary:        Xen Virtualization: Hypervisor (aka VMM aka Microkernel)
 License:        GPL-2.0-only
@@ -164,6 +164,15 @@
 Patch1:         
6a8f18ad-pass-through-disallow-pt_irq_create_bind-on-dying-domains.patch
 Patch2:         
6a759f74-emul-cope-with-internal-handlers-returning-X86EMUL_RETRY.patch
 Patch3:         
6a71bd97-xen-page_alloc-ensure-TLB-flush-is-done-ahead-of-page-scrubbing.patch
+Patch4:         
6aa28713-xen-sched-core-kill-unarmed-timers-on-sched_init_vcpu-failure.patch
+Patch5:         
6abceba2-xen-sched-core-skip-missing-vcpu-slots-in-sched_move_domain.patch
+Patch6:         6abcebd8-vmx-Handle-TDX-instruction-exit-reasons.patch
+Patch7:         6abcec00-boot-Force-error-checking-for-reserve_e820_ram.patch
+Patch8:         
6aad1183-tools-xenstored-fix-live-update-with-watches-specifying-depth.patch
+Patch9:         
6abbdd30-amd-Fix-inverted-condition-in-zenbleed_use_chickenbit.patch
+Patch10:        
6abbe079-pv-map-each-vCPUs-root-page-table-in-its-per-domain-area.patch
+Patch11:        6abbe20c-gnttab-address-fallout-from-XSA-501.patch
+Patch12:        
6abbe28e-vmx-Rework-#DB-intercept-logic-to-fix-VMEntry-failure-with-BTF.patch
 # Our platform specific patches
 Patch400:       xen-destdir.patch
 Patch401:       vif-bridge-no-iptables.patch

++++++ 
6aa28713-xen-sched-core-kill-unarmed-timers-on-sched_init_vcpu-failure.patch 
++++++
Subject: xen/sched: core: kill unarmed timers on sched_init_vcpu() failure
From: Furkan Caliskan [email protected] Thu Sep 10 12:31:47 2026 +0200
Date: Thu Sep 10 12:31:47 2026 +0200:
Git: f692b1badf84233e0bd905778bd284b4df7ff935

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: d884b1077817 ("Domain creation/destruction cleanups.")
Signed-off-by: Furkan Caliskan <[email protected]>
Reviewed-by: Juergen Gross <[email protected]>
master commit: 2565341135f88081535f6830a6256277e2834403
master date: 2026-09-01 10:02:13 +0200

diff --git a/xen/common/sched/core.c b/xen/common/sched/core.c
index 9ccf5811bf..67ae5a7968 100644
--- a/xen/common/sched/core.c
+++ b/xen/common/sched/core.c
@@ -584,7 +584,7 @@ int sched_init_vcpu(struct vcpu *v)
     unit->priv = sched_alloc_udata(dom_scheduler(d), unit, d->sched_priv);
     if ( unit->priv == NULL )
     {
-        sched_free_unit(unit, v);
+        sched_destroy_vcpu(v);
         rcu_read_unlock(&sched_res_rculock);
         return 1;
     }
@@ -864,8 +864,11 @@ void sched_destroy_vcpu(struct vcpu *v)
     {
         rcu_read_lock(&sched_res_rculock);
 
-        sched_remove_unit(vcpu_scheduler(v), unit);
-        sched_free_udata(vcpu_scheduler(v), unit->priv);
+        if ( unit->priv )
+        {
+            sched_remove_unit(vcpu_scheduler(v), unit);
+            sched_free_udata(vcpu_scheduler(v), unit->priv);
+        }
         sched_free_unit(unit, v);
 
         rcu_read_unlock(&sched_res_rculock);

++++++ 
6aad1183-tools-xenstored-fix-live-update-with-watches-specifying-depth.patch 
++++++
Subject: tools/xenstored: fix live update with watches specifying depth
From: Juergen Gross [email protected] Fri Sep 18 12:25:07 2026 +0200
Date: Tue Oct 13 13:48:17 2026 +0100:
Git: 1672ef1a5fd48844412928b2a690255846646695

Due to a typo the state record for a watch specifying a depth is
written only partially. Instead of using the correct length of the
xs_state_watch_ext structure only the length of the xs_state_watch
structure was used when writing the data.

Fix that by using the correct length.

This is XSA-514 / CVE-2026-79607

Fixes: db98de120cb8 ("tools/xenstored: add depth information to watches")
Reported-by: Andrii Sultanov <[email protected]>
Signed-off-by: Juergen Gross <[email protected]>
(cherry picked from commit 6b30eca0e388e5aaa4319c647a777d703d7ee752)

diff --git a/tools/xenstored/watch.c b/tools/xenstored/watch.c
index c143e6fbcf..7097ab0b0d 100644
--- a/tools/xenstored/watch.c
+++ b/tools/xenstored/watch.c
@@ -354,7 +354,7 @@ const char *dump_state_watches(FILE *fp, struct connection 
*conn,
                        return "Dump watch state error";
 
                if (watch->depth >= 0) {
-                       if (fwrite(&swe, sizeof(sw), 1, fp) != 1)
+                       if (fwrite(&swe, sizeof(swe), 1, fp) != 1)
                                return "Dump watch state ext error";
                } else {
                        if (fwrite(&sw, sizeof(sw), 1, fp) != 1)

++++++ 6abbdd30-amd-Fix-inverted-condition-in-zenbleed_use_chickenbit.patch 
++++++
Subject: x86/amd: Fix inverted condition in zenbleed_use_chickenbit()
From: Andrew Cooper [email protected] Tue Sep 29 16:45:52 2026 +0100
Date: Tue Oct 13 13:48:17 2026 +0100:
Git: 26cb5f56dea2660f8fe2755b4b8371a193f17344

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: d0c75dc4c028 ("x86/amd: Fix race editing DE_CFG")
Assisted-by: Sashiko + Opus 5.0
Reported-by: George Dunlap <[email protected]>
Signed-off-by: Andrew Cooper <[email protected]>
Reviewed-by: Jan Beulich <[email protected]>
(cherry picked from commit 0c5ec39d9106e6a06bf153400e8e1e324e457583)

diff --git a/xen/arch/x86/cpu/amd.c b/xen/arch/x86/cpu/amd.c
index 70783c9a0a..148886fe2e 100644
--- a/xen/arch/x86/cpu/amd.c
+++ b/xen/arch/x86/cpu/amd.c
@@ -891,7 +891,12 @@ static bool zenbleed_use_chickenbit(void)
         return is_zen2_uarch();
     }
 
-    return (uint8_t)curr_rev >= fixed_rev;
+    /*
+     * Zenbleed can be mitigated by disabling Floating-Point
+     * Mov-Elimination, but this is expensive.  Only do so when we
+     * don't have a fix in microcode.
+     */
+    return (uint8_t)curr_rev < fixed_rev;
 }
 
 void amd_init_de_cfg(const struct cpuinfo_x86 *c)

++++++ 6abbe079-pv-map-each-vCPUs-root-page-table-in-its-per-domain-area.patch 
++++++
Subject: x86/pv: map each vCPU's root page table in its per-domain area
From: George Dunlap [email protected] Tue Sep 29 16:59:53 2026 +0100
Date: Tue Oct 13 13:48:17 2026 +0100:
Git: f749e516b1648987ed9894ac8188614166eb66af

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: 5784de3e2067 ("x86: Meltdown band-aid against malicious 64-bit PV 
guests")
Assisted-by: Claude Code:claude-fable-5-1
Signed-off-by: George Dunlap <[email protected]>
Reviewed-by: Jan Beulich <[email protected]>
(cherry picked from commit 288fb615858ef9a55b327ba61973a99329809183)

diff --git a/xen/arch/x86/include/asm/config.h 
b/xen/arch/x86/include/asm/config.h
index 1b28349a42..0c004edc66 100644
--- a/xen/arch/x86/include/asm/config.h
+++ b/xen/arch/x86/include/asm/config.h
@@ -249,11 +249,30 @@ extern unsigned long xen_phys_start;
 #define GDT_LDT_VIRT_START       PERDOMAIN_VIRT_SLOT(0)
 #define GDT_LDT_VIRT_END         (GDT_LDT_VIRT_START + (GDT_LDT_MBYTES << 20))
 
-/* The address of a particular VCPU's GDT or LDT. */
+/*
+ * The address of a particular VCPU's GDT or LDT; each is the architectural
+ * maximum of 64k.
+ */
+#define GDT_VIRT_SIZE        KB(64)
 #define GDT_VIRT_START(v)    \
     (PERDOMAIN_VIRT_START + ((v)->vcpu_id << GDT_LDT_VCPU_VA_SHIFT))
 #define LDT_VIRT_START(v)    \
-    (GDT_VIRT_START(v) + (64*1024))
+    (GDT_VIRT_START(v) + GDT_VIRT_SIZE)
+
+/*
+ * The vCPU's effective root page table, mapped read-only in the last
+ * page of its GDT: the page after Xen's reserved range, beyond the
+ * GDT limit Xen loads (LAST_RESERVED_GDT_BYTE), so no selector can
+ * reach it.  "Effective" is the root page table the vCPU is meant to
+ * run on after any transformation: the guest's own, or its shadow
+ * under shadow paging.  XPTI does not transform it further but copies
+ * from it: the exit path reads the guest-visible L4 slots from here.
+ * Adding a reserved GDT page would mean moving the window out of the
+ * GDT first; pv_map_eff_root_pt() checks the layout at build time.
+ */
+#define PV_EFF_ROOT_PT_PAGE    (FIRST_RESERVED_GDT_PAGE + 1)
+#define PV_EFF_ROOT_PT_OFFSET  (PV_EFF_ROOT_PT_PAGE << PAGE_SHIFT)
+#define PV_EFF_ROOT_PT(v)      (GDT_VIRT_START(v) + PV_EFF_ROOT_PT_OFFSET)
 
 /* map_domain_page() map cache. The second per-domain-mapping sub-area. */
 #define MAPCACHE_VCPU_ENTRIES    (CONFIG_PAGING_LEVELS * CONFIG_PAGING_LEVELS)
diff --git a/xen/arch/x86/include/asm/desc.h b/xen/arch/x86/include/asm/desc.h
index dcbdac3ff7..7cbb9a7336 100644
--- a/xen/arch/x86/include/asm/desc.h
+++ b/xen/arch/x86/include/asm/desc.h
@@ -6,6 +6,16 @@
 /*
  * Xen reserves a memory page of GDT entries.
  * No guest GDT entries exist beyond the Xen reserved area.
+ *
+ * The page after the reserved area, the last of the GDT's 64k, is the
+ * PV effective root-table window (PV_EFF_ROOT_PT_PAGE, config.h):
+ * beyond the GDT limit Xen loads (LAST_RESERVED_GDT_BYTE), so no
+ * selector reaches it.  Xen uses only a few of the reserved page's
+ * 512 slots, so more Xen descriptors never need another page; if one
+ * were needed regardless, the window would have to move out of the
+ * GDT first (into a per-domain sub-area of its own), as this is the
+ * GDT's last page.  pv_map_eff_root_pt() checks the layout at build
+ * time.
  */
 #define NR_RESERVED_GDT_PAGES   1
 #define NR_RESERVED_GDT_BYTES   (NR_RESERVED_GDT_PAGES * PAGE_SIZE)
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index bb4ba0afe2..3cc7ec6eb4 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -511,13 +511,52 @@ void share_xen_page_with_guest(struct page_info *page, 
struct domain *d,
     nrspin_unlock(&d->page_alloc_lock);
 }
 
+/*
+ * Map @mfn read-only at v's PV_EFF_ROOT_PT() window.  The window lives in
+ * v's per-domain area, so v need not be current; the local flush is for
+ * when it is, with its own page tables loaded.
+ */
+static void pv_map_eff_root_pt(const struct vcpu *v, mfn_t mfn)
+{
+    /*
+     * The window must lie beyond the GDT limit Xen loads, so that no
+     * selector reaches it, and within the GDT's 64k.
+     */
+    BUILD_BUG_ON(PV_EFF_ROOT_PT_OFFSET <= LAST_RESERVED_GDT_BYTE);
+    BUILD_BUG_ON(PV_EFF_ROOT_PT_OFFSET + PAGE_SIZE > GDT_VIRT_SIZE);
+
+    l1e_write(pv_gdt_ptes(v) + PV_EFF_ROOT_PT_PAGE,
+              l1e_from_mfn(mfn, __PAGE_HYPERVISOR_RO));
+    flush_tlb_one_local(PV_EFF_ROOT_PT(v));
+}
+
+/*
+ * Clear the window.  Its lifetime is v->arch.cr3's: make_cr3() writes it
+ * wherever v->arch.cr3 is set, and vcpu_destroy_pagetables() clears it where
+ * v->arch.cr3 is zeroed.  In shadow mode both name a top-level shadow, which
+ * shadow_teardown() releases before that point; nothing uses either once the
+ * vCPU can no longer run.
+ */
+static void pv_unmap_eff_root_pt(const struct vcpu *v)
+{
+    l1e_write(pv_gdt_ptes(v) + PV_EFF_ROOT_PT_PAGE, l1e_empty());
+    flush_tlb_one_local(PV_EFF_ROOT_PT(v));
+}
+
 void make_cr3(struct vcpu *v, mfn_t mfn)
 {
     struct domain *d = v->domain;
 
     v->arch.cr3 = mfn_x(mfn) << PAGE_SHIFT;
-    if ( is_pv_domain(d) && d->arch.pv.pcid )
-        v->arch.cr3 |= get_pcid_bits(v, false);
+
+    if ( is_pv_domain(d) )
+    {
+        if ( d->arch.pv.pcid )
+            v->arch.cr3 |= get_pcid_bits(v, false);
+
+        if ( d->arch.pv.xpti )
+            pv_map_eff_root_pt(v, mfn);
+    }
 }
 
 void write_ptbase(struct vcpu *v)
@@ -3225,6 +3264,8 @@ int vcpu_destroy_pagetables(struct vcpu *v)
         return rc;
 
     v->arch.cr3 = 0;
+    if ( is_pv_domain(v->domain) && v->domain->arch.pv.xpti )
+        pv_unmap_eff_root_pt(v);
 
     /*
      * Get the top-level guest page; either the guest_table itself, for
diff --git a/xen/arch/x86/x86_64/asm-offsets.c 
b/xen/arch/x86/x86_64/asm-offsets.c
index 9d45364026..2872904ae2 100644
--- a/xen/arch/x86/x86_64/asm-offsets.c
+++ b/xen/arch/x86/x86_64/asm-offsets.c
@@ -81,6 +81,7 @@ void __dummy__(void)
 
 #undef OFFSET_EF
 
+    OFFSET(VCPU_id, struct vcpu, vcpu_id);
     OFFSET(VCPU_processor, struct vcpu, processor);
     OFFSET(VCPU_domain, struct vcpu, domain);
     OFFSET(VCPU_vcpu_info, struct vcpu, vcpu_info_area.map);
diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S
index de5d854f55..54c036d9da 100644
--- a/xen/arch/x86/x86_64/entry.S
+++ b/xen/arch/x86/x86_64/entry.S
@@ -200,9 +200,14 @@ FUNC_LOCAL(restore_all_guest)
         movabs $PADDR_MASK & PAGE_MASK, %rsi
         movabs $DIRECTMAP_VIRT_START, %rcx
         and   %rsi, %rdi
-        and   %r9, %rsi
         add   %rcx, %rdi
+
+        /* Effective root page table is mapped at PV_EFF_ROOT_PT(v) */
+        mov   VCPU_id(%rbx), %esi
+        shl   $GDT_LDT_VCPU_VA_SHIFT, %rsi
+        movabs $GDT_LDT_VIRT_START + PV_EFF_ROOT_PT_OFFSET, %rcx
         add   %rcx, %rsi
+
         mov   $ROOT_PAGETABLE_FIRST_XEN_SLOT, %ecx
         mov   root_table_offset(SH_LINEAR_PT_VIRT_START)*8(%rsi), %r8
         mov   %r8, root_table_offset(SH_LINEAR_PT_VIRT_START)*8(%rdi)

++++++ 6abbe20c-gnttab-address-fallout-from-XSA-501.patch ++++++
Subject: gnttab: address fallout from XSA-501
From: Jan Beulich [email protected] Tue Sep 29 17:06:36 2026 +0100
Date: Tue Oct 13 13:48:17 2026 +0100:
Git: edcad3da3e65eac45bf21c19cf8cd52e659195a6

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: 96dfeb41774a ("gnttab: cope with version changes racing other 
operations")
Assisted-by: Claude
Reported-by: Teddy Astie <[email protected]>
Signed-off-by: Jan Beulich <[email protected]>
Reviewed-by: Teddy Astie <[email protected]>
(cherry picked from commit e0a0823ee0a97f7e3c43dd7307b008eeb6120cbf)

diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
index 33ef5f651b..8892653ced 100644
--- a/xen/common/grant_table.c
+++ b/xen/common/grant_table.c
@@ -1350,13 +1350,19 @@ map_grant_ref(
 
     grant_read_lock(rgt);
 
-    if ( unlikely(evaluate_nospec((rgt->gt_version == 1) !=
-                                  (status == &shah->flags))) )
+    /*
+     * After a v1 -> v2 change behind our backs "ref" may now be out of
+     * bounds.  While after a v2 -> v1 -> v2 change "ref" would still be
+     * suitably bounded, the underlying status page may have moved.
+     */
+    if ( evaluate_nospec(rgt->gt_version == 1
+                         ? status != &shah->flags
+                         : (ref >= nr_grant_entries(rgt) ||
+                            status != &status_entry(rgt, ref))) )
     {
         /*
-         * After a v1 -> v2 change behind our backs "ref" may now be out of
-         * bounds.  Recalculate it, but only for reserved entries.  Others
-         * will have been cleared anyway by the version change.
+         * Recalculate status, but only for reserved entries.  Others will
+         * have been cleared anyway by the version change(s).
          */
         if ( ref < GNTTAB_NR_RESERVED_ENTRIES )
             status = evaluate_nospec(rgt->gt_version == 1)

++++++ 
6abbe28e-vmx-Rework-#DB-intercept-logic-to-fix-VMEntry-failure-with-BTF.patch 
++++++
Subject: x86/vmx: Rework #DB intercept logic to fix VMEntry failure with BTF
From: Andrew Cooper [email protected] Tue Sep 29 17:08:46 2026 +0100
Date: Tue Oct 13 13:48:17 2026 +0100:
Git: 7e80d14127f9b0b159f2040e67e33372e6a24456

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: 1d3eb8259804 ("x86/vtx: Work around SingleStep + STI/MovSS VMEntry 
failures")
Reported-by: Teddy Astie <[email protected]>
Signed-off-by: Andrew Cooper <[email protected]>
Reviewed-by: Jan Beulich <[email protected]>
Reviewed-by: Teddy Astie <[email protected]>
(cherry picked from commit 1017562ac0f2e6885cc9ec904bb75a5c29abe6b7)

diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index afd77b4552..55c42ad99a 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -4396,33 +4396,28 @@ void asmlinkage vmx_vmexit_handler(struct cpu_user_regs 
*regs)
              * We intercept #DB unconditionally to work around CVE-2015-8104 /
              * XSA-156 (guest-kernel induced host DoS).
              *
-             * STI/MovSS shadows block/defer interrupts/exceptions (exact
-             * details are complicated and poorly documented).  Debug
-             * exceptions delayed for any reason are stored in the
-             * PENDING_DBG_EXCEPTIONS field.
+             * Most sources of #DB accumuate status in PENDING_DBG, which are
+             * then dispatched in priority order prior to fetching the next
+             * instruction.  When the #DB intercept triggers, PENDING_DBG is 0
+             * with the status bits having moved into EXIT_QUALIFICATION.
              *
-             * The falling edge of PENDING_DBG causes #DB to be delivered,
-             * resulting in a VMExit, as #DB is intercepted.  The VMCS still
-             * reports blocked-by-STI/MovSS.
+             * At any point if Blocked-by-STI/MovSS are active, extra VMEntry
+             * consistency checks are applied, cross-checking EFLAGS.TF,
+             * PENDING_DBG.BS and DEBUGCTL.BTF.  These consistency checks
+             * apply to Activity-state-HLT too, but Xen doesn't support this.
              *
-             * The VMEntry checks when EFLAGS.TF is set don't like a VMCS in
-             * this state.  Despite a #DB queued in VMENTRY_INTR_INFO, the
-             * state is rejected as DR6.BS isn't pending.  Fix this up.
+             * The VMCS state at the point of #DB intercept does not satisfy
+             * the consistency checks.  In the case that a SingleStep should
+             * be pending, fill PENDING_DBG back in to satisfy the consitency
+             * check.
              */
-            if ( unlikely(regs->eflags & X86_EFLAGS_TF) )
+            if ( unlikely(regs->eflags & X86_EFLAGS_TF) &&
+                 (vmread(GUEST_INTERRUPTIBILITY_INFO) &
+                  (VMX_INTR_SHADOW_STI | VMX_INTR_SHADOW_MOV_SS)) &&
+                 !(vmread(GUEST_IA32_DEBUGCTL) & IA32_DEBUGCTLMSR_BTF) )
             {
-                unsigned long int_info;
-
-                __vmread(GUEST_INTERRUPTIBILITY_INFO, &int_info);
-
-                if ( int_info & (VMX_INTR_SHADOW_STI | VMX_INTR_SHADOW_MOV_SS) 
)
-                {
-                    unsigned long pending_dbg;
-
-                    __vmread(GUEST_PENDING_DBG_EXCEPTIONS, &pending_dbg);
-                    __vmwrite(GUEST_PENDING_DBG_EXCEPTIONS,
-                              pending_dbg | DR_STEP);
-                }
+                ASSERT(vmread(GUEST_PENDING_DBG_EXCEPTIONS) == 0);
+                __vmwrite(GUEST_PENDING_DBG_EXCEPTIONS, X86_DR6_BS);
             }
 
             if ( !v->domain->debugger_attached )

++++++ 
6abceba2-xen-sched-core-skip-missing-vcpu-slots-in-sched_move_domain.patch 
++++++
Subject: xen/sched: core: skip missing vcpu slots in sched_move_domain()
From: Furkan Caliskan [email protected] Wed Sep 30 12:59:46 2026 +0200
Date: Wed Sep 30 12:59:46 2026 +0200:
Git: 2a797c6d6ec24eb7aa1fd0692a892a21b054bbbc

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: 70fadc41635b ("xen/cpupool: support moving domain between cpupools with 
different granularity")
Signed-off-by: Furkan Caliskan <[email protected]>
Reviewed-by: Juergen Gross <[email protected]>
master commit: 4835c078e5cf52fbcf842f4e8a2e61808b8ff869
master date: 2026-09-21 09:54:12 +0200

diff --git a/xen/common/sched/core.c b/xen/common/sched/core.c
index 67ae5a7968..6de3a13545 100644
--- a/xen/common/sched/core.c
+++ b/xen/common/sched/core.c
@@ -740,6 +740,38 @@ int sched_move_domain(struct domain *d, struct cpupool *c)
 
     for ( unit_idx = 0; unit_idx < n_units; unit_idx++ )
     {
+        /*
+         * A vcpu slot can be missing if creation failed partway
+         * through. A dying domain is being torn down regardless, so
+         * skip the unit -- but a domain that isn't dying still needs
+         * every vcpu it has schedulable, so fail instead of silently
+         * dropping some of them.
+         */
+        bool vcpu_failed = false;
+
+        for ( unsigned int i = 0;
+              i < gran && unit_idx * gran + i < d->max_vcpus; i++ )
+        {
+            if ( !d->vcpu[unit_idx * gran + i] )
+            {
+                vcpu_failed = true;
+                break;
+            }
+        }
+
+        if ( vcpu_failed )
+        {
+            if ( !d->is_dying )
+            {
+                sched_move_domain_cleanup(c->sched, new_units, domdata);
+                rcu_read_unlock(&sched_res_rculock);
+
+                return -EINVAL;
+            }
+
+            continue;
+        }
+
         unit = sched_alloc_unit_mem();
         if ( unit )
         {

++++++ 6abcebd8-vmx-Handle-TDX-instruction-exit-reasons.patch ++++++
Subject: vmx: Handle TDX instruction exit reasons
From: Teddy Astie [email protected] Wed Sep 30 13:00:40 2026 +0200
Date: Wed Sep 30 13:00:40 2026 +0200:
Git: 52d71fc5606c7dc4705c67c5877ef46ebab57129

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 <[email protected]>
Acked-by: Jan Beulich <[email protected]>
master commit: 755c9fbbfe4bcd8671a6621ae050f45441300579
master date: 2026-09-22 09:59:37 +0200

diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index 269ca56433..afd77b4552 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -4681,6 +4681,8 @@ void asmlinkage vmx_vmexit_handler(struct cpu_user_regs 
*regs)
     case EXIT_REASON_MWAIT_INSTRUCTION:
     case EXIT_REASON_MONITOR_INSTRUCTION:
     case EXIT_REASON_GETSEC:
+    case EXIT_REASON_SEAMCALL:
+    case EXIT_REASON_TDCALL:
         /*
          * We should never exit on GETSEC because CR4.SMXE is always 0 when
          * running in guest context, and the CPU checks that before getting
diff --git a/xen/arch/x86/hvm/vmx/vvmx.c b/xen/arch/x86/hvm/vmx/vvmx.c
index e4cdfe55c1..b2ad7db332 100644
--- a/xen/arch/x86/hvm/vmx/vvmx.c
+++ b/xen/arch/x86/hvm/vmx/vvmx.c
@@ -2496,6 +2496,8 @@ int nvmx_n2_vmexit_handler(struct cpu_user_regs *regs,
     case EXIT_REASON_INVEPT:
     case EXIT_REASON_XSETBV:
     case EXIT_REASON_INVVPID:
+    case EXIT_REASON_SEAMCALL:
+    case EXIT_REASON_TDCALL:
         /* inject to L1 */
         nvcpu->nv_vmexit_pending = 1;
         break;
diff --git a/xen/arch/x86/include/asm/hvm/vmx/vmx.h 
b/xen/arch/x86/include/asm/hvm/vmx/vmx.h
index da04752e17..b8219e0408 100644
--- a/xen/arch/x86/include/asm/hvm/vmx/vmx.h
+++ b/xen/arch/x86/include/asm/hvm/vmx/vmx.h
@@ -201,6 +201,8 @@ static inline void pi_clear_sn(struct pi_desc *pi_desc)
 #define EXIT_REASON_XRSTORS             64
 #define EXIT_REASON_BUS_LOCK            74
 #define EXIT_REASON_NOTIFY              75
+#define EXIT_REASON_SEAMCALL            76
+#define EXIT_REASON_TDCALL              77
 /* Remember to also update VMX_PERF_EXIT_REASON_SIZE! */
 
 /*
diff --git a/xen/arch/x86/include/asm/perfc_defn.h 
b/xen/arch/x86/include/asm/perfc_defn.h
index ac7439b992..102b9be6ef 100644
--- a/xen/arch/x86/include/asm/perfc_defn.h
+++ b/xen/arch/x86/include/asm/perfc_defn.h
@@ -6,7 +6,7 @@ PERFCOUNTER_ARRAY(exceptions,           "exceptions", 32)
 
 #ifdef CONFIG_HVM
 
-#define VMX_PERF_EXIT_REASON_SIZE 76
+#define VMX_PERF_EXIT_REASON_SIZE 78
 #define VMEXIT_NPF_PERFC 166
 #define SVM_PERF_EXIT_REASON_SIZE (VMEXIT_NPF_PERFC + 1)
 PERFCOUNTER_ARRAY(vmexits,              "vmexits",

++++++ 6abcec00-boot-Force-error-checking-for-reserve_e820_ram.patch ++++++
Subject: x86/boot: Force error checking for reserve_e820_ram()
From: Andrew Cooper [email protected] Wed Sep 30 13:01:20 2026 +0200
Date: Wed Sep 30 13:01:20 2026 +0200:
Git: 3703b32f3644f76922499fb2b356adfa48d7dbae

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 <[email protected]>
Signed-off-by: Andrew Cooper <[email protected]>
Reviewed-by: Ross Lagerwall <[email protected]>
Reviewed-by: Jan Beulich <[email protected]>
master commit: b7c0ac446722e9d3aa05a025a96a5fc901e2881d
master date: 2026-09-24 20:54:37 +0100

diff --git a/xen/arch/x86/e820.c b/xen/arch/x86/e820.c
index 872208ab37..f09a01f0c5 100644
--- a/xen/arch/x86/e820.c
+++ b/xen/arch/x86/e820.c
@@ -670,7 +670,13 @@ int __init e820_change_range_type(
 /* Set E820_RAM area (@s,@e) as RESERVED in specified e820 map. */
 int __init reserve_e820_ram(struct e820map *map, uint64_t s, uint64_t e)
 {
-    return e820_change_range_type(map, s, e, E820_RAM, E820_RESERVED);
+    int res = e820_change_range_type(map, s, e, E820_RAM, E820_RESERVED);
+
+    if ( !res )
+        printk("Failed to convert E820 RAM %"PRIx64"-%"PRIx64" to RESERVED\n",
+               s, e);
+
+    return res;
 }
 
 unsigned long __init init_e820(const char *str, struct e820map *raw)
diff --git a/xen/arch/x86/include/asm/e820.h b/xen/arch/x86/include/asm/e820.h
index 8e7644f887..55395f8d8a 100644
--- a/xen/arch/x86/include/asm/e820.h
+++ b/xen/arch/x86/include/asm/e820.h
@@ -25,7 +25,8 @@ struct e820map {
 
 extern int sanitize_e820_map(struct e820entry *biosmap, unsigned int *pnr_map);
 extern int e820_all_mapped(u64 start, u64 end, unsigned type);
-extern int reserve_e820_ram(struct e820map *map, uint64_t s, uint64_t e);
+extern int __must_check reserve_e820_ram(
+    struct e820map *map, uint64_t s, uint64_t e);
 extern int e820_change_range_type(
     struct e820map *map, uint64_t s, uint64_t e,
     uint32_t orig_type, uint32_t new_type);
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index 7d71fea6c0..23d14aa718 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -1648,7 +1648,8 @@ void asmlinkage __init noreturn __start_xen(void)
     {
         uint64_t s = bi->mods[i].start, l = bi->mods[i].size;
 
-        reserve_e820_ram(&boot_e820, s, s + PAGE_ALIGN(l));
+        if ( !reserve_e820_ram(&boot_e820, s, s + PAGE_ALIGN(l)) )
+            panic("Failed to reserve boot module %u in E820\n", i);
     }
 
     if ( !xen_phys_start )
@@ -1661,11 +1662,13 @@ void asmlinkage __init noreturn __start_xen(void)
     /* This needs to remain in sync with remove_xen_ranges(). */
     if ( efi_boot_mem_unused(&eb_start, &eb_end) )
     {
-        reserve_e820_ram(&boot_e820, __pa(_stext), __pa(eb_start));
-        reserve_e820_ram(&boot_e820, __pa(eb_end), __pa(__2M_rwdata_end));
+        if ( !reserve_e820_ram(&boot_e820, __pa(_stext), __pa(eb_start)) ||
+             !reserve_e820_ram(&boot_e820, __pa(eb_end), 
__pa(__2M_rwdata_end)) )
+            panic("Failed to reserve Xen in E820\n");
     }
     else
-        reserve_e820_ram(&boot_e820, __pa(_stext), __pa(__2M_rwdata_end));
+        if ( !reserve_e820_ram(&boot_e820, __pa(_stext), 
__pa(__2M_rwdata_end)) )
+            panic("Failed to reserve Xen in E820\n");
 
     /* Late kexec reservation (dynamic start address). */
     kexec_reserve_area();

Reply via email to