$NetBSD: patch-CVE-2012-5511_1,v 1.1 2012/12/05 19:16:27 drochner Exp $

see http://lists.xen.org/archives/html/xen-announce/2012-12/msg00006.html

fix for CVE-2012-5512 is also here, see
http://lists.xen.org/archives/html/xen-announce/2012-12/msg00003.html

--- xen/arch/x86/hvm/hvm.c.orig	2012-08-10 13:51:44.000000000 +0000
+++ xen/arch/x86/hvm/hvm.c
@@ -3446,6 +3446,9 @@ long do_hvm_op(unsigned long op, XEN_GUE
         if ( !is_hvm_domain(d) )
             goto param_fail2;
 
+        if ( a.nr > GB(1) >> PAGE_SHIFT )
+            goto param_fail2;
+
         rc = xsm_hvm_param(d, op);
         if ( rc )
             goto param_fail2;
@@ -3473,7 +3476,6 @@ long do_hvm_op(unsigned long op, XEN_GUE
         struct xen_hvm_modified_memory a;
         struct domain *d;
         struct p2m_domain *p2m;
-        unsigned long pfn;
 
         if ( copy_from_guest(&a, arg, 1) )
             return -EFAULT;
@@ -3501,8 +3503,9 @@ long do_hvm_op(unsigned long op, XEN_GUE
             goto param_fail3;
 
         p2m = p2m_get_hostp2m(d);
-        for ( pfn = a.first_pfn; pfn < a.first_pfn + a.nr; pfn++ )
+        while ( a.nr > 0 )
         {
+            unsigned long pfn = a.first_pfn;
             p2m_type_t t;
             mfn_t mfn = gfn_to_mfn(p2m, pfn, &t);
             if ( p2m_is_paging(t) )
@@ -3523,6 +3526,19 @@ long do_hvm_op(unsigned long op, XEN_GUE
                 /* don't take a long time and don't die either */
                 sh_remove_shadows(d->vcpu[0], mfn, 1, 0);
             }
+
+            a.first_pfn++;
+            a.nr--;
+
+            /* Check for continuation if it's not the last interation */
+            if ( a.nr > 0 && hypercall_preempt_check() )
+            {
+                if ( copy_to_guest(arg, &a, 1) )
+                    rc = -EFAULT;
+                else
+                    rc = -EAGAIN;
+                break;
+            }
         }
 
     param_fail3:
@@ -3566,7 +3582,6 @@ long do_hvm_op(unsigned long op, XEN_GUE
         struct xen_hvm_set_mem_type a;
         struct domain *d;
         struct p2m_domain *p2m;
-        unsigned long pfn;
         
         /* Interface types to internal p2m types */
         p2m_type_t memtype[] = {
@@ -3596,8 +3611,9 @@ long do_hvm_op(unsigned long op, XEN_GUE
             goto param_fail4;
 
         p2m = p2m_get_hostp2m(d);
-        for ( pfn = a.first_pfn; pfn < a.first_pfn + a.nr; pfn++ )
+        while ( a.nr > 0 )
         {
+            unsigned long pfn = a.first_pfn;
             p2m_type_t t;
             p2m_type_t nt;
             mfn_t mfn;
@@ -3633,6 +3649,19 @@ long do_hvm_op(unsigned long op, XEN_GUE
                     goto param_fail4;
                 }
             }
+
+            a.first_pfn++;
+            a.nr--;
+
+            /* Check for continuation if it's not the last interation */
+            if ( a.nr > 0 && hypercall_preempt_check() )
+            {
+                if ( copy_to_guest(arg, &a, 1) )
+                    rc = -EFAULT;
+                else
+                    rc = -EAGAIN;
+                goto param_fail4;
+            }
         }
 
         rc = 0;
@@ -3670,7 +3699,7 @@ long do_hvm_op(unsigned long op, XEN_GUE
             return rc;
 
         rc = -EINVAL;
-        if ( !is_hvm_domain(d) )
+        if ( !is_hvm_domain(d)  || a.hvmmem_access >= ARRAY_SIZE(memaccess) )
             goto param_fail5;
 
         p2m = p2m_get_hostp2m(d);
@@ -3690,9 +3719,6 @@ long do_hvm_op(unsigned long op, XEN_GUE
              ((a.first_pfn + a.nr - 1) > domain_get_maximum_gpfn(d)) )
             goto param_fail5;
             
-        if ( a.hvmmem_access >= ARRAY_SIZE(memaccess) )
-            goto param_fail5;
-
         for ( pfn = a.first_pfn; pfn < a.first_pfn + a.nr; pfn++ )
         {
             p2m_type_t t;
