[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 4.0-testing 03/10] hvm: Limit the size of large HVM op batches



From: Tim Deegan <tim@xxxxxxx>

Doing large p2m updates for HVMOP_track_dirty_vram without preemption
ties up the physical processor. Integrating preemption into the p2m
updates is hard so simply limit to 1GB which is sufficient for a 15000
* 15000 * 32bpp framebuffer.

For HVMOP_modified_memory and HVMOP_set_mem_type preemptible add the
necessary machinery to handle preemption.

This is CVE-2012-5511 / XSA-27.

Signed-off-by: Tim Deegan <tim@xxxxxxx>
Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
Acked-by: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
Committed-by: Ian Jackson <ian.jackson.citrix.com>

x86/paging: Don't allocate user-controlled amounts of stack memory.

This is XSA-27 / CVE-2012-5511.

Signed-off-by: Tim Deegan <tim@xxxxxxx>
Acked-by: Jan Beulich <jbeulich@xxxxxxxx>
v2: Provide definition of GB to fix x86-32 compile.

Signed-off-by: Jan Beulich <JBeulich@xxxxxxxx>
Acked-by: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
---
 xen/arch/x86/hvm/hvm.c       |   37 +++++++++++++++++++++++++++++++++----
 xen/arch/x86/mm/paging.c     |   17 +++++++++++------
 xen/include/asm-x86/config.h |    4 +++-
 3 files changed, 47 insertions(+), 11 deletions(-)

diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 640969b..1ab0ec6 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -2943,6 +2943,9 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) 
arg)
         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;
@@ -2969,7 +2972,6 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) 
arg)
     {
         struct xen_hvm_modified_memory a;
         struct domain *d;
-        unsigned long pfn;
 
         if ( copy_from_guest(&a, arg, 1) )
             return -EFAULT;
@@ -2996,8 +2998,9 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) 
arg)
         if ( !paging_mode_log_dirty(d) )
             goto param_fail3;
 
-        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(d, pfn, &t);
             if ( p2m_is_paging(t) )
@@ -3018,6 +3021,19 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) 
arg)
                 /* 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:
@@ -3029,7 +3045,6 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) 
arg)
     {
         struct xen_hvm_set_mem_type a;
         struct domain *d;
-        unsigned long pfn;
         
         /* Interface types to internal p2m types */
         p2m_type_t memtype[] = {
@@ -3062,8 +3077,9 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) 
arg)
         if ( a.hvmmem_type >= ARRAY_SIZE(memtype) )
             goto param_fail4;
 
-        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;
@@ -3099,6 +3115,19 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) 
arg)
                     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;
diff --git a/xen/arch/x86/mm/paging.c b/xen/arch/x86/mm/paging.c
index b11577a..bba747e 100644
--- a/xen/arch/x86/mm/paging.c
+++ b/xen/arch/x86/mm/paging.c
@@ -486,13 +486,18 @@ int paging_log_dirty_range(struct domain *d,
 
     if ( !d->arch.paging.log_dirty.fault_count &&
          !d->arch.paging.log_dirty.dirty_count ) {
-        int size = (nr + BITS_PER_LONG - 1) / BITS_PER_LONG;
-        unsigned long zeroes[size];
-        memset(zeroes, 0x00, size * BYTES_PER_LONG);
+        static uint8_t zeroes[PAGE_SIZE];
+        int off, size;
+
+        size = ((nr + BITS_PER_LONG - 1) / BITS_PER_LONG) * sizeof (long);
         rv = 0;
-        if ( copy_to_guest_offset(dirty_bitmap, 0, (uint8_t *) zeroes,
-                                  size * BYTES_PER_LONG) != 0 )
-            rv = -EFAULT;
+        for ( off = 0; !rv && off < size; off += sizeof zeroes )
+        {
+            int todo = min(size - off, (int) PAGE_SIZE);
+            if ( copy_to_guest_offset(dirty_bitmap, off, zeroes, todo) )
+                rv = -EFAULT;
+            off += todo;
+        }
         goto out;
     }
     d->arch.paging.log_dirty.fault_count = 0;
diff --git a/xen/include/asm-x86/config.h b/xen/include/asm-x86/config.h
index c9e6057..462df51 100644
--- a/xen/include/asm-x86/config.h
+++ b/xen/include/asm-x86/config.h
@@ -108,6 +108,9 @@ extern unsigned int trampoline_xen_phys_start;
 extern unsigned char trampoline_cpu_started;
 extern char wakeup_start[];
 extern unsigned int video_mode, video_flags;
+
+#define GB(_gb) (_gb ## UL << 30)
+
 #endif
 
 #define asmlinkage
@@ -123,7 +126,6 @@ extern unsigned int video_mode, video_flags;
 #define PML4_ADDR(_slot)                             \
     ((((_slot ## UL) >> 8) * 0xffff000000000000UL) | \
      (_slot ## UL << PML4_ENTRY_BITS))
-#define GB(_gb) (_gb ## UL << 30)
 #else
 #define PML4_ENTRY_BYTES (1 << PML4_ENTRY_BITS)
 #define PML4_ADDR(_slot)                             \
-- 
1.7.2.5


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.