From 26452e289eb6f64e85d630c06a9f3de7d0188cd7 Mon Sep 17 00:00:00 2001
From: Roger Pau Monne <roger.pau@citrix.com>
Date: Wed, 15 Jul 2026 12:44:37 +0200
Subject: x86/vrtc: fix race in CMOS index checking
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

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: 34bef0e6d5f4 ("hvm: Add locking to platform timers.")
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
 xen/arch/x86/hvm/rtc.c | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/xen/arch/x86/hvm/rtc.c b/xen/arch/x86/hvm/rtc.c
index 483937435205..ad15825a1f20 100644
--- a/xen/arch/x86/hvm/rtc.c
+++ b/xen/arch/x86/hvm/rtc.c
@@ -647,16 +647,24 @@ static int update_in_progress(RTCState *s)
     return 0;
 }
 
-static uint32_t rtc_ioport_read(RTCState *s, uint32_t addr)
+static bool rtc_ioport_read(RTCState *s, uint32_t addr, uint32_t *val)
 {
     int ret;
     struct domain *d = vrtc_domain(s);
 
+    *val = ~0;
+
     if ( (addr & 1) == 0 )
-        return 0xff;
+        return true;
 
     spin_lock(&s->lock);
 
+    if ( s->hw.cmos_index >= RTC_CMOS_SIZE )
+    {
+        spin_unlock(&s->lock);
+        return false;
+    }
+
     switch ( s->hw.cmos_index )
     {
     case RTC_SECONDS:
@@ -696,7 +704,9 @@ static uint32_t rtc_ioport_read(RTCState *s, uint32_t addr)
 
     spin_unlock(&s->lock);
 
-    return ret;
+    *val = ret;
+
+    return true;
 }
 
 static int cf_check handle_rtc_io(
@@ -716,11 +726,8 @@ static int cf_check handle_rtc_io(
         if ( rtc_ioport_write(vrtc, port, (uint8_t)*val) )
             return X86EMUL_OKAY;
     }
-    else if ( vrtc->hw.cmos_index < RTC_CMOS_SIZE )
-    {
-        *val = rtc_ioport_read(vrtc, port);
+    else if ( rtc_ioport_read(vrtc, port, val) )
         return X86EMUL_OKAY;
-    }
 
     return X86EMUL_UNHANDLEABLE;
 }
-- 
2.53.0

