Subject: hypercall_xlat_continuation: Replace BUG_ON with domain_crash
From: Bjoern Doebel <[email-masked]>

Instead of crashing the host in case of unexpected hypercall parameters,
resort to only crashing the calling domain.

This is part of XSA-454 / CVE-2023-46842.

Fixes: b8a7efe8528a ("Enable compatibility mode operation for HYPERVISOR_memory_op")
Reported-by: Manuel Andreas <[email-masked]>
Signed-off-by: Bjoern Doebel <[email-masked]>
Signed-off-by: Jan Beulich <[email-masked]>
Reviewed-by: Roger Pau Monné <[email-masked]>

--- a/xen/arch/x86/hypercall.c
+++ b/xen/arch/x86/hypercall.c
@@ -140,8 +140,10 @@ int hypercall_xlat_continuation(unsigned
                 cval = va_arg(args, unsigned int);
                 if ( cval == nval )
                     mask &= ~1U;
-                else
-                    BUG_ON(nval == (unsigned int)nval);
+                else if ( nval == (unsigned int)nval )
+                    domain_crash(current->domain,
+                                 "multicall (op %lu) bogus continuation arg%u (%#lx)\n",
+                                 mcs->call.op, i, nval);
             }
             else if ( id && *id == i )
             {
@@ -153,8 +155,10 @@ int hypercall_xlat_continuation(unsigned
                 mcs->call.args[i] = cval;
                 ++rc;
             }
-            else
-                BUG_ON(mcs->call.args[i] != (unsigned int)mcs->call.args[i]);
+            else if ( mcs->call.args[i] != (unsigned int)mcs->call.args[i] )
+                domain_crash(current->domain,
+                             "multicall (op %lu) bad continuation arg%u (%#lx)\n",
+                             mcs->call.op, i, mcs->call.args[i]);
         }
     }
     else
@@ -180,8 +184,10 @@ int hypercall_xlat_continuation(unsigned
                 cval = va_arg(args, unsigned int);
                 if ( cval == nval )
                     mask &= ~1U;
-                else
-                    BUG_ON(nval == (unsigned int)nval);
+                else if ( nval == (unsigned int)nval )
+                    domain_crash(current->domain,
+                                 "hypercall (op %u) bogus continuation arg%u (%#lx)\n",
+                                 regs->eax, i, nval);
             }
             else if ( id && *id == i )
             {
@@ -193,8 +199,10 @@ int hypercall_xlat_continuation(unsigned
                 *reg = cval;
                 ++rc;
             }
-            else
-                BUG_ON(*reg != (unsigned int)*reg);
+            else if ( *reg != (unsigned int)*reg )
+                domain_crash(current->domain,
+                             "hypercall (op %u) bad continuation arg%u (%#lx)\n",
+                             regs->eax, i, *reg);
         }
     }