ebc4dec
From: Jan Beulich <jbeulich@suse.com>
ebc4dec
Subject: x86/HAP: adjust monitor table related error handling
ebc4dec
ebc4dec
hap_make_monitor_table() will return INVALID_MFN if it encounters an
ebc4dec
error condition, but hap_update_paging_modes() wasn’t handling this
ebc4dec
value, resulting in an inappropriate value being stored in
ebc4dec
monitor_table. This would subsequently misguide at least
ebc4dec
hap_vcpu_teardown(). Avoid this by bailing early.
ebc4dec
ebc4dec
Further, when a domain has/was already crashed or (perhaps less
ebc4dec
important as there's no such path known to lead here) is already dying,
ebc4dec
avoid calling domain_crash() on it again - that's at best confusing.
ebc4dec
ebc4dec
This is part of CVE-2022-33746 / XSA-410.
ebc4dec
ebc4dec
Signed-off-by: Jan Beulich <jbeulich@suse.com>
ebc4dec
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
ebc4dec
ebc4dec
--- a/xen/arch/x86/mm/hap/hap.c
ebc4dec
+++ b/xen/arch/x86/mm/hap/hap.c
ebc4dec
@@ -39,6 +39,7 @@
ebc4dec
 #include <asm/domain.h>
ebc4dec
 #include <xen/numa.h>
ebc4dec
 #include <asm/hvm/nestedhvm.h>
ebc4dec
+#include <public/sched.h>
ebc4dec
 
ebc4dec
 #include "private.h"
ebc4dec
 
ebc4dec
@@ -405,8 +406,13 @@ static mfn_t hap_make_monitor_table(stru
ebc4dec
     return m4mfn;
ebc4dec
 
ebc4dec
  oom:
ebc4dec
-    printk(XENLOG_G_ERR "out of memory building monitor pagetable\n");
ebc4dec
-    domain_crash(d);
ebc4dec
+    if ( !d->is_dying &&
ebc4dec
+         (!d->is_shutting_down || d->shutdown_code != SHUTDOWN_crash) )
ebc4dec
+    {
ebc4dec
+        printk(XENLOG_G_ERR "%pd: out of memory building monitor pagetable\n",
ebc4dec
+               d);
ebc4dec
+        domain_crash(d);
ebc4dec
+    }
ebc4dec
     return INVALID_MFN;
ebc4dec
 }
ebc4dec
 
ebc4dec
@@ -766,6 +772,9 @@ static void hap_update_paging_modes(stru
ebc4dec
     if ( pagetable_is_null(v->arch.hvm.monitor_table) )
ebc4dec
     {
ebc4dec
         mfn_t mmfn = hap_make_monitor_table(v);
ebc4dec
+
ebc4dec
+        if ( mfn_eq(mmfn, INVALID_MFN) )
ebc4dec
+            goto unlock;
ebc4dec
         v->arch.hvm.monitor_table = pagetable_from_mfn(mmfn);
ebc4dec
         make_cr3(v, mmfn);
ebc4dec
         hvm_update_host_cr3(v);
ebc4dec
@@ -774,6 +783,7 @@ static void hap_update_paging_modes(stru
ebc4dec
     /* CR3 is effectively updated by a mode change. Flush ASIDs, etc. */
ebc4dec
     hap_update_cr3(v, 0, false);
ebc4dec
 
ebc4dec
+ unlock:
ebc4dec
     paging_unlock(d);
ebc4dec
     put_gfn(d, cr3_gfn);
ebc4dec
 }