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-04-29 19:17:56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/xen (Old) and /work/SRC/openSUSE:Factory/.xen.new.30200 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "xen" Wed Apr 29 19:17:56 2026 rev:373 rq:1349848 version:4.21.1_04 Changes: -------- --- /work/SRC/openSUSE:Factory/xen/xen.changes 2026-03-28 20:14:38.488618340 +0100 +++ /work/SRC/openSUSE:Factory/.xen.new.30200/xen.changes 2026-04-29 19:18:55.747748900 +0200 @@ -1,0 +2,21 @@ +Tue Apr 28 09:33:12 MDT 2026 - [email protected] + +- bsc#1262178 - VUL-0: CVE-2026-23557: xen: Xenstored DoS via + XS_RESET_WATCHES command (XSA-484) + 69f0ab36-xenstored-make-conn_delete_all_transactions-idempotent.patch +- bsc#1262180 - VUL-0: CVE-2026-23558: xen: grant table v2 race in + status page mapping (XSA-486) + 69f0ab36-gnttab-split-gnttab_map_frame.patch + +------------------------------------------------------------------- +Mon Apr 20 15:25:00 CEST 2026 - [email protected] + +- Upstream bug fixes (bsc#1027519) + 69d4ab43-EFI-avoid-OOB-config-file-reads.patch + 69d8ed8e-x86-time-dont-kill-calibration-timer-on-S3.patch + 69e0e400-x86-use-native-TSC-scaling-factors-when-.patch + 69e0e401-CPU-round-cpu_khz-calculations.patch + 69e26ac9-x86-mkelf32-actually-pad-segment-to-2Mb.patch + 69e26aca-x86-mitigate-AMD-SN-7053-FP-DSS.patch + +------------------------------------------------------------------- New: ---- 69d4ab43-EFI-avoid-OOB-config-file-reads.patch 69d8ed8e-x86-time-dont-kill-calibration-timer-on-S3.patch 69e0e400-x86-use-native-TSC-scaling-factors-when-.patch 69e0e401-CPU-round-cpu_khz-calculations.patch 69e26ac9-x86-mkelf32-actually-pad-segment-to-2Mb.patch 69e26aca-x86-mitigate-AMD-SN-7053-FP-DSS.patch 69f0ab36-gnttab-split-gnttab_map_frame.patch 69f0ab36-xenstored-make-conn_delete_all_transactions-idempotent.patch ----------(New B)---------- New:- Upstream bug fixes (bsc#1027519) 69d4ab43-EFI-avoid-OOB-config-file-reads.patch 69d8ed8e-x86-time-dont-kill-calibration-timer-on-S3.patch New: 69d4ab43-EFI-avoid-OOB-config-file-reads.patch 69d8ed8e-x86-time-dont-kill-calibration-timer-on-S3.patch 69e0e400-x86-use-native-TSC-scaling-factors-when-.patch New: 69d8ed8e-x86-time-dont-kill-calibration-timer-on-S3.patch 69e0e400-x86-use-native-TSC-scaling-factors-when-.patch 69e0e401-CPU-round-cpu_khz-calculations.patch New: 69e0e400-x86-use-native-TSC-scaling-factors-when-.patch 69e0e401-CPU-round-cpu_khz-calculations.patch 69e26ac9-x86-mkelf32-actually-pad-segment-to-2Mb.patch New: 69e0e401-CPU-round-cpu_khz-calculations.patch 69e26ac9-x86-mkelf32-actually-pad-segment-to-2Mb.patch 69e26aca-x86-mitigate-AMD-SN-7053-FP-DSS.patch New: 69e26ac9-x86-mkelf32-actually-pad-segment-to-2Mb.patch 69e26aca-x86-mitigate-AMD-SN-7053-FP-DSS.patch New: status page mapping (XSA-486) 69f0ab36-gnttab-split-gnttab_map_frame.patch New: XS_RESET_WATCHES command (XSA-484) 69f0ab36-xenstored-make-conn_delete_all_transactions-idempotent.patch - bsc#1262180 - VUL-0: CVE-2026-23558: xen: grant table v2 race in ----------(New E)---------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ xen.spec ++++++ --- /var/tmp/diff_new_pack.96gf2q/_old 2026-04-29 19:18:57.035801667 +0200 +++ /var/tmp/diff_new_pack.96gf2q/_new 2026-04-29 19:18:57.039801831 +0200 @@ -125,7 +125,7 @@ BuildRequires: python-rpm-macros Provides: installhint(reboot-needed) -Version: 4.21.1_02 +Version: 4.21.1_04 Release: 0 Summary: Xen Virtualization: Hypervisor (aka VMM aka Microkernel) License: GPL-2.0-only @@ -160,7 +160,14 @@ # For xen-libs Source99: baselibs.conf # Upstream patches -# EMBARGOED security fixes +Patch1: 69d4ab43-EFI-avoid-OOB-config-file-reads.patch +Patch2: 69d8ed8e-x86-time-dont-kill-calibration-timer-on-S3.patch +Patch3: 69e0e400-x86-use-native-TSC-scaling-factors-when-.patch +Patch4: 69e0e401-CPU-round-cpu_khz-calculations.patch +Patch5: 69e26ac9-x86-mkelf32-actually-pad-segment-to-2Mb.patch +Patch6: 69e26aca-x86-mitigate-AMD-SN-7053-FP-DSS.patch +Patch7: 69f0ab36-gnttab-split-gnttab_map_frame.patch +Patch8: 69f0ab36-xenstored-make-conn_delete_all_transactions-idempotent.patch # Our platform specific patches Patch400: xen-destdir.patch Patch401: vif-bridge-no-iptables.patch ++++++ 69d4ab43-EFI-avoid-OOB-config-file-reads.patch ++++++ # Commit df75f77092c1cc47f3ed5be86cf6c04e732f3f80 # Date 2026-04-07 08:59:15 +0200 # Author Jan Beulich <[email protected]> # Committer Jan Beulich <[email protected]> EFI: avoid OOB config file reads The message emitted by pre_parse() pretty clearly states the original intention. Yet what it said wasn't done, and would have been unfriendly to the user. Hence accesses past the allocated buffer were possible. Insert a terminating NUL immediately past the data read, to then drop the no longer applicable message. NB: The iscntrl() check of just the last byte is more strict than what pre_parse() would accept without issuing its prior message, yet I'd like to keep the new logic reasonably simple. Config files shouldn't be huge, and we shouldn't be _that_ short of memory (or we'd fail elsewhere pretty soon). Fixes: bf6501a62e80 ("x86-64: EFI boot code") Reported-by: Kamil Frankowicz <[email protected]> Signed-off-by: Jan Beulich <[email protected]> Acked-by: Marek Marczykowski-Górecki <[email protected]> --- a/xen/common/efi/boot.c +++ b/xen/common/efi/boot.c @@ -833,8 +833,9 @@ static bool __init read_file(EFI_FILE_HA what = L"Allocation"; file->addr = min(1UL << (32 + PAGE_SHIFT), HYPERVISOR_VIRT_END - DIRECTMAP_VIRT_START); + /* For config files allocate an extra byte to put a NUL there. */ ret = efi_bs->AllocatePages(AllocateMaxAddress, EfiLoaderData, - PFN_UP(size), &file->addr); + PFN_UP(size + (file == &cfg)), &file->addr); if ( EFI_ERROR(ret) ) goto fail; @@ -853,6 +854,9 @@ static bool __init read_file(EFI_FILE_HA efi_arch_flush_dcache_area(file->ptr, file->size); + if ( file == &cfg ) + file->str[file->size] = 0; + return true; fail: @@ -878,6 +882,23 @@ static bool __init read_section(const EF file->ptr = ptr; + /* For cfg file, if necessary allocate space to put an extra NUL there. */ + if ( file == &cfg && file->size && !iscntrl(file->str[file->size - 1]) ) + { + EFI_PHYSICAL_ADDRESS addr; + EFI_STATUS ret = efi_bs->AllocatePages(AllocateMaxAddress, + EfiLoaderData, + PFN_UP(file->size + 1), &addr); + + if ( EFI_ERROR(ret) ) + return false; + + memcpy((void *)addr, ptr, file->size); + file->addr = addr; + file->need_to_free = true; + file->str[file->size] = 0; + } + handle_file_info(name, file, options); return true; @@ -906,9 +927,6 @@ static void __init pre_parse(const struc else start = 0; } - if ( file->size && end[-1] ) - PrintStr(L"No newline at end of config file," - " last line will be ignored.\r\n"); } static void __init init_secure_boot_mode(void) ++++++ 69d8ed8e-x86-time-dont-kill-calibration-timer-on-S3.patch ++++++ # Commit 2d670d258b2e592d44deb5ee12e7c2ba1d79d8a9 # Date 2026-04-10 14:31:10 +0200 # Author Roger Pau Monne <[email protected]> # Committer Roger Pau Monne <[email protected]> x86/time: do not kill calibration timer on suspend A killed timer will ignore further set_timer() calls, and hence won't be re-armed unless it's initialized again. Use stop_timer() instead of kill_timer() in time_suspend(), so that the set_timer() call in time_resume() successfully re-arms the timer. Otherwise time calibration is no longer scheduled (and executed) after resuming from S3 suspend. Fixes: 6d90db1a2ca1 ("x86: rendezvous-based local time calibration") Reported-by: Marek Marczykowski-Górecki <[email protected]> Signed-off-by: Roger Pau Monné <[email protected]> Reviewed-by: Andrew Cooper <[email protected]> Tested-by: Marek Marczykowski-Górecki <[email protected]> --- a/xen/arch/x86/time.c +++ b/xen/arch/x86/time.c @@ -2720,7 +2720,7 @@ int time_suspend(void) { cmos_utc_offset = -get_wallclock_time(); cmos_utc_offset += get_sec(); - kill_timer(&calibration_timer); + stop_timer(&calibration_timer); /* Sync platform timer stamps. */ platform_time_calibration(); ++++++ 69e0e400-x86-use-native-TSC-scaling-factors-when-.patch ++++++ # Commit 305c6b901a44aa6e16d3bf7d104d7c08331d1731 # Date 2026-04-16 15:28:32 +0200 # Author Roger Pau Monne <[email protected]> # Committer Roger Pau Monne <[email protected]> x86/time: use native TSC scaling factors when TSC is not scaled When running HVM guest in native TSC mode avoid using the recalculated vTSC scaling factors based on the cpu_khz value. Using the kHz based frequency leads to the TSC scaling values possibly not being the same as the ones used by the per CPU cpu_time->tsc_scale field, which introduces skew between the guest and Xen's calculations of the system time. On a 2gHz system, where the frequency is possibly detected as 1999999999Hz (note this is a worse-case scenario), the cpu_khz variable will be set to 1999999kHz, and hence 999Hz cycles will be not accounted for per second. Over a second (the time synchronization period), this leads to a skew of: cycles * 1 / (Hz freq) = 999 / 1999999999 = 499,5ns So far this has gone unnoticed because the time synchronization rendezvous forces the update of the tsc_timestamp and system_time fields in the vCPU time info area, and hence the skew only accumulates up to the rendezvous period. Attempting to remove the rendezvous causes the skew to grow unbounded. Fix by using the native TSC scaling values (as used by Xen) when the guest TSC is not scaled. Fixes: eab8a90be723 ("x86/time: scale host TSC in pvclock properly") Signed-off-by: Roger Pau Monné <[email protected]> Reviewed-by: Jan Beulich <[email protected]> --- a/xen/arch/x86/time.c +++ b/xen/arch/x86/time.c @@ -1702,17 +1702,25 @@ static void collect_time_info(const stru else { if ( is_hvm_domain(d) && hvm_tsc_scaling_supported ) - { tsc_stamp = hvm_scale_tsc(d, t->stamp.local_tsc); - u->tsc_to_system_mul = d->arch.vtsc_to_ns.mul_frac; - u->tsc_shift = d->arch.vtsc_to_ns.shift; - } else - { tsc_stamp = t->stamp.local_tsc; + + /* + * HVM guests using the native TSC ratio should use the same per-CPU + * scaling factors as Xen. This ensures time keeping is always in sync + * between Xen and the guest. + */ + if ( tsc_stamp == t->stamp.local_tsc ) + { u->tsc_to_system_mul = t->tsc_scale.mul_frac; u->tsc_shift = t->tsc_scale.shift; } + else + { + u->tsc_to_system_mul = d->arch.vtsc_to_ns.mul_frac; + u->tsc_shift = d->arch.vtsc_to_ns.shift; + } } u->tsc_timestamp = tsc_stamp; ++++++ 69e0e401-CPU-round-cpu_khz-calculations.patch ++++++ # Commit 986707b461eb56d75f55581dd1c8e2633f814795 # Date 2026-04-16 15:28:32 +0200 # Author Roger Pau Monne <[email protected]> # Committer Roger Pau Monne <[email protected]> xen/cpu: round cpu_khz calculations All arches truncate the cpu_khz without taking into account the less significant digits. Instead use DIV_ROUND() when scaling from Hz to kHz to get as more accurate kHz value. Signed-off-by: Roger Pau Monné <[email protected]> Reviewed-by: Jan Beulich <[email protected]> --- a/xen/arch/arm/time.c +++ b/xen/arch/arm/time.c @@ -128,7 +128,7 @@ static void __init preinit_dt_xen_time(v res = dt_property_read_u32(timer, "clock-frequency", &rate); if ( res ) { - cpu_khz = rate / 1000; + cpu_khz = DIV_ROUND(rate, 1000); validate_timer_frequency(); timer_dt_clock_frequency = rate; } @@ -146,7 +146,7 @@ void __init preinit_xen_time(void) if ( !cpu_khz ) { - cpu_khz = (READ_SYSREG(CNTFRQ_EL0) & CNTFRQ_MASK) / 1000; + cpu_khz = DIV_ROUND(READ_SYSREG(CNTFRQ_EL0) & CNTFRQ_MASK, 1000); validate_timer_frequency(); } --- a/xen/arch/riscv/time.c +++ b/xen/arch/riscv/time.c @@ -36,7 +36,7 @@ static void __init preinit_dt_xen_time(v if ( !dt_property_read_u32(timer, "timebase-frequency", &rate) ) panic("Unable to find clock frequency\n"); - cpu_khz = rate / 1000; + cpu_khz = DIV_ROUND(rate, 1000); } void __init preinit_xen_time(void) --- a/xen/arch/x86/time.c +++ b/xen/arch/x86/time.c @@ -2634,7 +2634,7 @@ void __init early_time_init(void) set_time_scale(&t->tsc_scale, tmp); t->stamp.local_tsc = boot_tsc_stamp; - cpu_khz = tmp / 1000; + cpu_khz = DIV_ROUND(tmp, 1000); printk("Detected %lu.%03lu MHz processor.\n", cpu_khz / 1000, cpu_khz % 1000); ++++++ 69e26ac9-x86-mkelf32-actually-pad-segment-to-2Mb.patch ++++++ # Commit 5416c455f656af9ff3ed7f26dcd5cbf70b254f23 # Date 2026-04-17 18:15:54 +0100 # Author Ross Lagerwall <[email protected]> # Committer Andrew Cooper <[email protected]> x86/mkelf32: Actually pad load segment to 2 MiB boundary Fix the code which tries to pad the load segment to 2 MiB but only pads it to a 1 MiB boundary. This manifests as a page fault while scrubbing RAM during boot on certain systems. Xen fails to mark itself as reserved in the E820 (due to spanning multiple regions), but does restrict the permissions in the directmap. The region of RAM containing Xen is handed to physical memory manager as available for use, and scrubbing hit the directmap protections. Fixes: 4fb075201f54 ("x86/mkelf32: pad load segment to 2Mb boundary") Signed-off-by: Ross Lagerwall <[email protected]> Reviewed-by: Andrew Cooper <[email protected]> --- a/xen/arch/x86/boot/mkelf32.c +++ b/xen/arch/x86/boot/mkelf32.c @@ -345,7 +345,7 @@ int main(int argc, char **argv) * the Xen image using 2M pages. To avoid running into adjacent non-RAM * regions, pad the segment to the next 2M boundary. */ - mem_siz = ((uint32_t)in64_phdr.p_memsz + (1U << 20) - 1) & (-1U << 20); + mem_siz = ((uint32_t)in64_phdr.p_memsz + (1U << 21) - 1) & (-1U << 21); note_sz = note_base = offset = 0; if ( num_phdrs > 1 ) ++++++ 69e26aca-x86-mitigate-AMD-SN-7053-FP-DSS.patch ++++++ # Commit 99912d346009fda1e7fb1510c9501fbab17e92a0 # Date 2026-04-17 18:15:54 +0100 # Author Andrew Cooper <[email protected]> # Committer Andrew Cooper <[email protected]> x86/amd: Mitigate AMD-SN-7053 / FP-DSS This is XSA-488 / CVE-2025-54505 Signed-off-by: Andrew Cooper <[email protected]> Reviewed-by: Roger Pau Monné <[email protected]> --- a/xen/arch/x86/cpu/amd.c +++ b/xen/arch/x86/cpu/amd.c @@ -1048,6 +1048,42 @@ void amd_init_de_cfg(const struct cpuinf wrmsrl(MSR_AMD64_DE_CFG, val | new); } +static void amd_init_fp_cfg(const struct cpuinfo_x86 *c) +{ + uint64_t val, new = 0; + + /* If virtualised, we won't have mutable access even if we can read it. */ + if ( cpu_has_hypervisor ) + return; + + /* + * On Zen1, mitigate SB-7053 / FP-DSS Floating Point Divider State + * Sampling by setting bit 9 as instructed. + */ + if ( c->family == 0x17 && is_zen1_uarch() ) + new |= 1 << 9; + + /* + * Avoid reading FP_CFG if we don't intend to change anything. The + * register doesn't exist on all families. + */ + if ( !new ) + return; + + val = rdmsr(MSR_AMD64_FP_CFG); + + if ( (val & new) == new ) + return; + + /* + * FP_CFG is a Core-scoped MSR, and this write is racy. However, both + * threads calculate the new value from state which expected to be + * consistent across CPUs and unrelated to the old value, so the result + * should be consistent. + */ + wrmsr(MSR_AMD64_FP_CFG, val | new); +} + void __init amd_init_lfence_dispatch(void) { struct cpuinfo_x86 *c = &boot_cpu_data; @@ -1120,6 +1156,7 @@ static void cf_check init_amd(struct cpu uint64_t value; amd_init_de_cfg(c); + amd_init_fp_cfg(c); if (c == &boot_cpu_data) amd_init_lfence_dispatch(); /* Needs amd_init_de_cfg() */ --- a/xen/arch/x86/include/asm/msr-index.h +++ b/xen/arch/x86/include/asm/msr-index.h @@ -428,6 +428,7 @@ #define MSR_AMD64_LS_CFG 0xc0011020U #define MSR_AMD64_IC_CFG 0xc0011021U #define MSR_AMD64_DC_CFG 0xc0011022U +#define MSR_AMD64_FP_CFG 0xc0011028U #define MSR_AMD64_DE_CFG 0xc0011029U #define AMD64_DE_CFG_LFENCE_SERIALISE (_AC(1, ULL) << 1) #define MSR_AMD64_EX_CFG 0xc001102cU ++++++ 69f0ab36-gnttab-split-gnttab_map_frame.patch ++++++ Subject: gnttab: split gnttab_map_frame() From: Jan Beulich [email protected] Tue Apr 28 13:41:28 2026 +0100 Date: Tue Apr 28 13:42:30 2026 +0100: Git: 0d8b25d1fc17fbd1b3b82b318a8e8a8236b151b7 If a domain tries to map status frames in parallel to switching grant table version from 2 to 1, the mapping operation may put in place P2M entries referencing MFNs which gnttab_unpopulate_status_frames() is in the process of freeing. Ideally we would refcount pages when entered into P2M tables, but that's a significant change. Extend the grant-table-locked region instead in xenmem_add_to_physmap_one() (being the sole caller of gnttab_map_frame()), such that a race with gnttab_unpopulate_status_frames() is no longer possible. This is XSA-486 / CVE-2026-23558. Fixes: 5ce8fafa947c ("Dynamic grant-table sizing") Fixes: a98dc13703e0 ("Introduce a grant_entry_v2 structure") Reported-by: Rafal Wojtczuk <[email protected]> Signed-off-by: Jan Beulich <[email protected]> Reviewed-by: Roger Pau Monné <[email protected]> (cherry picked from commit 02708d3b51b04aeeaa4b127637d7fec8d8c5b1d8) diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c index 3b05b46ee0..9281dc8330 100644 --- a/xen/arch/arm/mm.c +++ b/xen/arch/arm/mm.c @@ -129,12 +129,10 @@ int xenmem_add_to_physmap_one( switch ( space ) { case XENMAPSPACE_grant_table: - rc = gnttab_map_frame(d, idx, gfn, &mfn); + rc = gnttab_map_frame_begin(d, idx, gfn, &mfn); if ( rc ) return rc; - /* Need to take care of the reference obtained in gnttab_map_frame(). */ - page = mfn_to_page(mfn); t = p2m_ram_rw; break; @@ -236,10 +234,23 @@ int xenmem_add_to_physmap_one( * to drop the reference we took earlier. In all other cases we need to * drop any reference we took earlier (perhaps indirectly). */ - if ( space == XENMAPSPACE_gmfn_foreign ? rc : page != NULL ) + switch ( space ) { + default: + if ( page ) + put_page(page); + break; + + case XENMAPSPACE_grant_table: + gnttab_map_frame_end(d, mfn); + break; + + case XENMAPSPACE_gmfn_foreign: + if ( !rc ) + break; ASSERT(page != NULL); put_page(page); + break; } return rc; diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c index 743eb02e00..484bb83c41 100644 --- a/xen/arch/x86/mm/p2m.c +++ b/xen/arch/x86/mm/p2m.c @@ -2004,11 +2004,9 @@ int xenmem_add_to_physmap_one( break; case XENMAPSPACE_grant_table: - rc = gnttab_map_frame(d, idx, gfn, &mfn); + rc = gnttab_map_frame_begin(d, idx, gfn, &mfn); if ( rc ) return rc; - /* Need to take care of the reference obtained in gnttab_map_frame(). */ - page = mfn_to_page(mfn); break; case XENMAPSPACE_gmfn: @@ -2090,19 +2088,28 @@ int xenmem_add_to_physmap_one( put_gfn(d, gfn_x(gfn)); put_both: - /* - * In the XENMAPSPACE_gmfn case, we took a ref of the gfn at the top. - * We also may need to transfer ownership of the page reference to our - * caller. - */ - if ( space == XENMAPSPACE_gmfn ) + switch ( space ) { + case XENMAPSPACE_gmfn: + /* + * We took a ref of the gfn at the top. We also may need to transfer + * ownership of the page reference to our caller. + */ put_gfn(d, gmfn); if ( !rc && extra.ppage ) { *extra.ppage = page; page = NULL; } + break; + + case XENMAPSPACE_grant_table: + /* + * We (gnttab_map_frame_begin()) acquired a lock and took a ref of the + * page underlying the MFN at the top. + */ + gnttab_map_frame_end(d, mfn); + break; } if ( page ) diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c index cf131c43a1..f9e4bffdb1 100644 --- a/xen/common/grant_table.c +++ b/xen/common/grant_table.c @@ -4248,7 +4248,8 @@ int gnttab_acquire_resource( return rc; } -int gnttab_map_frame(struct domain *d, unsigned long idx, gfn_t gfn, mfn_t *mfn) +int gnttab_map_frame_begin( + struct domain *d, unsigned long idx, gfn_t gfn, mfn_t *mfn) { int rc = 0; struct grant_table *gt = d->grant_table; @@ -4286,11 +4287,19 @@ int gnttab_map_frame(struct domain *d, unsigned long idx, gfn_t gfn, mfn_t *mfn) put_page(pg); } - grant_write_unlock(gt); + if ( rc ) + grant_write_unlock(d->grant_table); return rc; } +void gnttab_map_frame_end(struct domain *d, mfn_t mfn) +{ + put_page(mfn_to_page(mfn)); + + grant_write_unlock(d->grant_table); +} + static void gnttab_usage_print(struct domain *rd) { int first = 1; diff --git a/xen/include/xen/grant_table.h b/xen/include/xen/grant_table.h index 297d7669e9..afdba2045c 100644 --- a/xen/include/xen/grant_table.h +++ b/xen/include/xen/grant_table.h @@ -60,8 +60,13 @@ int gnttab_release_mappings(struct domain *d); int mem_sharing_gref_to_gfn(struct grant_table *gt, grant_ref_t ref, gfn_t *gfn, uint16_t *status); -int gnttab_map_frame(struct domain *d, unsigned long idx, gfn_t gfn, - mfn_t *mfn); +/* + * These need to be used as a pair, as the first (in the success case) returns + * with a lock and page reference held which the second needs to drop. + */ +int gnttab_map_frame_begin(struct domain *d, unsigned long idx, gfn_t gfn, + mfn_t *mfn); +void gnttab_map_frame_end(struct domain *d, mfn_t mfn); unsigned int gnttab_resource_max_frames(const struct domain *d, unsigned int id); @@ -100,12 +105,14 @@ static inline int mem_sharing_gref_to_gfn(struct grant_table *gt, return -EINVAL; } -static inline int gnttab_map_frame(struct domain *d, unsigned long idx, - gfn_t gfn, mfn_t *mfn) +static inline int gnttab_map_frame_begin(struct domain *d, unsigned long idx, + gfn_t gfn, mfn_t *mfn) { return -EINVAL; } +static inline void gnttab_map_frame_end(struct domain *d, mfn_t mfn) {} + static inline unsigned int gnttab_resource_max_frames( const struct domain *d, unsigned int id) { ++++++ 69f0ab36-xenstored-make-conn_delete_all_transactions-idempotent.patch ++++++ Subject: tools/xenstored: make conn_delete_all_transactions() idempotent From: Juergen Gross [email protected] Mon Mar 16 15:06:11 2026 +0100 Date: Tue Apr 28 13:42:30 2026 +0100: Git: 43e32ae4f92899b6ebd6730d944f51ba55dd88ae conn_delete_all_transactions() should be callable in any context, resetting ALL transaction related data. This includes number of active transactions and the transaction pointer in struct connection. So reset conn->trans to NULL in conn_delete_all_transactions() and do the cleanup for each transaction in destroy_transaction(). This avoids triggering the assert() in conn_delete_all_transactions() in case e.g. ignore_connection() was called while an operation inside a transaction was performed, or XS_RESET_WATCHES was called in a transaction. This is XSA-484 / CVE-2026-23557. Reported-by: Andrii Sultanov <[email protected]> Fixes: 1f9d04fb021c ("xenstored: allow guest to shutdown all its watches/transactions") Signed-off-by: Juergen Gross <[email protected]> (cherry picked from commit e88031d1fe5f5bbacc31b838c2a544de58c9bf45) diff --git a/tools/xenstored/transaction.c b/tools/xenstored/transaction.c index 167cd597fd..0825c48859 100644 --- a/tools/xenstored/transaction.c +++ b/tools/xenstored/transaction.c @@ -432,17 +432,23 @@ static int finalize_transaction(struct connection *conn, static int destroy_transaction(void *_transaction) { struct transaction *trans = _transaction; + struct connection *conn = trans->conn; struct accessed_node *i; wrl_ntransactions--; trace_destroy(trans, "transaction"); while ((i = list_top(&trans->accessed, struct accessed_node, list))) { if (i->ta_node) - db_delete(trans->conn, i->trans_name, NULL); + db_delete(conn, i->trans_name, NULL); list_del(&i->list); talloc_free(i); } + list_del(&trans->list); + domain_transaction_dec(conn); + if (list_empty(&conn->transaction_list)) + conn->ta_start_time = 0; + return 0; } @@ -523,10 +529,6 @@ int do_transaction_end(const void *ctx, struct connection *conn, return ENOENT; conn->transaction = NULL; - list_del(&trans->list); - domain_transaction_dec(conn); - if (list_empty(&conn->transaction_list)) - conn->ta_start_time = 0; chk_quota = trans->node_created && domain_is_unprivileged(conn); @@ -572,14 +574,10 @@ void conn_delete_all_transactions(struct connection *conn) struct transaction *trans; while ((trans = list_top(&conn->transaction_list, - struct transaction, list))) { - list_del(&trans->list); + struct transaction, list))) talloc_free(trans); - } - - assert(conn->transaction == NULL); - conn->ta_start_time = 0; + conn->transaction = NULL; } int check_transactions(struct hashtable *hash)
