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

[Xen-devel] [PATCH RFC v2 4/4] HVM x86 deprivileged mode: Watchdog for DoS prevention



A watchdog timer is used to prevent the deprivileged mode running for too long,
aimed at handling a bug or attempted DoS. If the watchdog has occurred more than
once whilst we have been in the same deprivileged mode context, then we crash
the domain. This can be adjusted for longer running times in future.

Signed-off-by: Ben Catterall <Ben.Catterall@xxxxxxxxxx>
---
 xen/arch/x86/hvm/deprivileged.c    | 17 +++++++++++++----
 xen/arch/x86/nmi.c                 | 17 +++++++++++++++++
 xen/include/xen/hvm/deprivileged.h |  1 +
 3 files changed, 31 insertions(+), 4 deletions(-)

diff --git a/xen/arch/x86/hvm/deprivileged.c b/xen/arch/x86/hvm/deprivileged.c
index 01efbe1..85701c0 100644
--- a/xen/arch/x86/hvm/deprivileged.c
+++ b/xen/arch/x86/hvm/deprivileged.c
@@ -4,10 +4,11 @@
  */
 #include <xen/lib.h>
 #include <xen/mm.h>
+#include <xen/sched.h>
 #include <xen/domain_page.h>
 #include <xen/config.h>
 #include <xen/types.h>
-#include <xen/sched.h>
+#include <xen/watchdog.h>
 #include <asm/paging.h>
 #include <xen/compiler.h>
 #include <asm/hap.h>
@@ -17,6 +18,7 @@
 #include <xen/domain_page.h>
 #include <asm/hvm/vmx/vmx.h>
 #include <xen/hvm/deprivileged.h>
+#include <xen/shutdown.h>
 
 void hvm_deprivileged_init(struct domain *d, l4_pgentry_t *l4t_base)
 {
@@ -219,7 +221,6 @@ int hvm_deprivileged_map_l4(struct domain *d,
              * we preserve the access bits of any supervisor entries that are
              * used in the leaf case.
              */
-
             l3t_base = map_l3t_from_l4e(l4t_base[i]);
 
             hvm_deprivileged_map_l3(d, l3t_base, src_start, dst_start,
@@ -309,7 +310,6 @@ int hvm_deprivileged_map_l3(struct domain *d,
              * we preserve the access bits of any supervisor entries that are
              * used in the leaf case.
              */
-
             l2t_base = map_l2t_from_l3e(l3t_base[i]);
 
             hvm_deprivileged_map_l2(d, l2t_base, src_start, dst_start,
@@ -389,7 +389,6 @@ int hvm_deprivileged_map_l2(struct domain *d,
             {
                 panic("HVM: L2 Leaf page is already mapped\n");
             }
-
             /*
              * We can try recursing on this and see if where we want to put our
              * new pages is empty.
@@ -552,6 +551,16 @@ void hvm_deprivileged_user_mode(void)
 
     vcpu->arch.hvm_vcpu.depriv_user_mode = 0;
     vcpu->arch.hvm_vcpu.depriv_rsp = 0;
+    vcpu->arch.hvm_vcpu.depriv_watchdog_count = 0;
+
+    /*
+     * If we need to crash the domain at this point. We will return up the call
+     * stack, undoing any allocations and then the event testers in the exit
+     * assembly stubs will test for the SOFTIRQ_TIMER event generated by a
+     * domain_crash and will crash the domain for us.
+     */
+    if( vcpu->arch.hvm_vcpu.depriv_destroy )
+        domain_crash(vcpu->domain);
 }
 
 /*
diff --git a/xen/arch/x86/nmi.c b/xen/arch/x86/nmi.c
index 2ab97a0..25817d2 100644
--- a/xen/arch/x86/nmi.c
+++ b/xen/arch/x86/nmi.c
@@ -26,6 +26,7 @@
 #include <xen/smp.h>
 #include <xen/keyhandler.h>
 #include <xen/cpu.h>
+#include <xen/hvm/deprivileged.h>
 #include <asm/current.h>
 #include <asm/mc146818rtc.h>
 #include <asm/msr.h>
@@ -463,9 +464,25 @@ int __init watchdog_setup(void)
 /* Returns false if this was not a watchdog NMI, true otherwise */
 bool_t nmi_watchdog_tick(const struct cpu_user_regs *regs)
 {
+    struct vcpu *vcpu = current;
     bool_t watchdog_tick = 1;
     unsigned int sum = this_cpu(nmi_timer_ticks);
 
+    /*
+     * If the domain has been running in deprivileged mode for two watchdog
+     * ticks, then we kill it to prevent a DoS. We use two ticks as a coarse
+     * measure as this ensures that at least a full watchdog tick duration has
+     * occurred. This means that we do not need to track entry time and do
+     * time calculations.
+     */
+    if( is_hvm_deprivileged_vcpu() )
+    {
+        if( vcpu->arch.hvm_vcpu.depriv_watchdog_count )
+            hvm_deprivileged_crash_domain("HVM Deprivileged domain: Domain 
exceeded running time.");
+        else
+            vcpu->arch.hvm_vcpu.depriv_watchdog_count = 1;
+    }
+
     if ( (this_cpu(last_irq_sums) == sum) && watchdog_enabled() )
     {
         /*
diff --git a/xen/include/xen/hvm/deprivileged.h 
b/xen/include/xen/hvm/deprivileged.h
index 9c08adf..9a7f109 100644
--- a/xen/include/xen/hvm/deprivileged.h
+++ b/xen/include/xen/hvm/deprivileged.h
@@ -74,6 +74,7 @@ int hvm_deprivileged_map_l1(struct domain *d,
                             unsigned int l1_flags,
                             unsigned int op);
 
+
 /* Used to allocate a page for the deprivileged mode */
 struct page_info *hvm_deprivileged_alloc_page(struct domain *d);
 
-- 
2.1.4


_______________________________________________
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®.