[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen stable-4.18] x86/viridian: protect concurrent modification of the reference TSC page
commit 2102093e081f0d57e0b92881970d07c6542c969a Author: Roger Pau Monné <roger.pau@xxxxxxxxxx> AuthorDate: Tue Sep 9 14:25:36 2025 +0200 Commit: Jan Beulich <jbeulich@xxxxxxxx> CommitDate: Tue Sep 9 14:25:36 2025 +0200 x86/viridian: protect concurrent modification of the reference TSC page The reference TSC page is shared between all vCPUs, and the data stored in the domain struct. However the handlers to set and clear it are not safe against concurrent accesses. It's possible for two (or more) vCPUs to call HV_X64_MSR_REFERENCE_TSC at the same time and cause the in-use reference TSC page to be freed, while still being on the p2m. This creates a use- after-free bug, where the page can end up mapped in another domain or used by Xen while still being part of the original domain's p2m. It's also possible to underflow the reference counter, as multiple concurrent writes to HV_X64_MSR_REFERENCE_TSC can create an imbalance on the number of put_page_and_type() calls. Introduce a lock to protect the reference TSC domain field, thus serializing concurrent vCPU accesses. This is CVE-2025-58143 / part of XSA-472. Fixes: 386b3365221d ('viridian: use viridian_map/unmap_guest_page() for reference tsc page') Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx> Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx> master commit: 45729a510a352e1a973e4023bd0067cddb1bcaf8 master date: 2025-09-09 14:12:00 +0200 --- xen/arch/x86/hvm/viridian/time.c | 4 ++++ xen/arch/x86/hvm/viridian/viridian.c | 2 ++ xen/arch/x86/include/asm/hvm/viridian.h | 1 + 3 files changed, 7 insertions(+) diff --git a/xen/arch/x86/hvm/viridian/time.c b/xen/arch/x86/hvm/viridian/time.c index ca6d526f46..9311858d63 100644 --- a/xen/arch/x86/hvm/viridian/time.c +++ b/xen/arch/x86/hvm/viridian/time.c @@ -108,8 +108,10 @@ static void time_ref_count_thaw(const struct domain *d) trc->off = (int64_t)trc->val - trc_val(d, 0); + spin_lock(&vd->lock); if ( vd->reference_tsc.msr.enabled ) update_reference_tsc(d, false); + spin_unlock(&vd->lock); } static uint64_t time_ref_count(const struct domain *d) @@ -331,6 +333,7 @@ int viridian_time_wrmsr(struct vcpu *v, uint32_t idx, uint64_t val) if ( !(viridian_feature_mask(d) & HVMPV_reference_tsc) ) return X86EMUL_EXCEPTION; + spin_lock(&vd->lock); viridian_unmap_guest_page(&vd->reference_tsc); vd->reference_tsc.msr.raw = val; viridian_dump_guest_page(v, "REFERENCE_TSC", &vd->reference_tsc); @@ -339,6 +342,7 @@ int viridian_time_wrmsr(struct vcpu *v, uint32_t idx, uint64_t val) viridian_map_guest_page(d, &vd->reference_tsc); update_reference_tsc(d, true); } + spin_unlock(&vd->lock); break; case HV_X64_MSR_TIME_REF_COUNT: diff --git a/xen/arch/x86/hvm/viridian/viridian.c b/xen/arch/x86/hvm/viridian/viridian.c index 25ed454852..a15fe0e9f8 100644 --- a/xen/arch/x86/hvm/viridian/viridian.c +++ b/xen/arch/x86/hvm/viridian/viridian.c @@ -494,6 +494,8 @@ int viridian_domain_init(struct domain *d) if ( !d->arch.hvm.viridian ) return -ENOMEM; + spin_lock_init(&d->arch.hvm.viridian->lock); + rc = viridian_synic_domain_init(d); if ( rc ) goto fail; diff --git a/xen/arch/x86/include/asm/hvm/viridian.h b/xen/arch/x86/include/asm/hvm/viridian.h index 4c8ff6e80b..47c9d13841 100644 --- a/xen/arch/x86/include/asm/hvm/viridian.h +++ b/xen/arch/x86/include/asm/hvm/viridian.h @@ -71,6 +71,7 @@ struct viridian_domain DECLARE_BITMAP(hypercall_flags, _HCALL_nr); struct viridian_time_ref_count time_ref_count; struct viridian_page reference_tsc; + spinlock_t lock; }; void cpuid_viridian_leaves(const struct vcpu *v, uint32_t leaf, -- generated by git-patchbot for /home/xen/git/xen.git#stable-4.18
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |