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

[Xen-changelog] [xen master] x86/hvm/hpet: block speculative out-of-bound accesses



commit 73e1fb1aec437b4ded7e40efeb8e0589bebdad7a
Author:     Norbert Manthey <nmanthey@xxxxxxxxx>
AuthorDate: Mon Jan 28 17:37:20 2019 +0100
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Mon Jan 28 17:37:20 2019 +0100

    x86/hvm/hpet: block speculative out-of-bound accesses
    
    When interacting with hpet, read and write operations can be executed
    during instruction emulation, where the guest controls the data that
    is used. As it is hard to predict the number of instructions that are
    executed speculatively, we prevent out-of-bound accesses by using the
    array_index_nospec function for guest specified addresses that should
    be used for hpet operations.
    
    We introduce another macro that uses the ARRAY_SIZE macro to block
    speculative accesses. For arrays that are statically accessed, this macro
    can be used instead of the usual macro. Using this macro results in more
    readable code, and allows to modify the way this case is handled in a
    single place.
    
    This commit is part of the SpectreV1+L1TF mitigation patch series.
    
    Signed-off-by: Norbert Manthey <nmanthey@xxxxxxxxx>
    Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx>
    Release-acked-by: Juergen Gross <jgross@xxxxxxxx>
---
 xen/arch/x86/hvm/hpet.c  | 17 ++++++++++-------
 xen/include/xen/nospec.h |  6 ++++++
 2 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/xen/arch/x86/hvm/hpet.c b/xen/arch/x86/hvm/hpet.c
index be371ecc0b..a916758106 100644
--- a/xen/arch/x86/hvm/hpet.c
+++ b/xen/arch/x86/hvm/hpet.c
@@ -25,6 +25,7 @@
 #include <xen/sched.h>
 #include <xen/event.h>
 #include <xen/trace.h>
+#include <xen/nospec.h>
 
 #define domain_vhpet(x) (&(x)->arch.hvm.pl_time->vhpet)
 #define vcpu_vhpet(x)   (domain_vhpet((x)->domain))
@@ -124,15 +125,18 @@ static inline uint64_t hpet_read64(HPETState *h, unsigned 
long addr,
     case HPET_Tn_CFG(0):
     case HPET_Tn_CFG(1):
     case HPET_Tn_CFG(2):
-        return h->hpet.timers[HPET_TN(CFG, addr)].config;
+        return array_access_nospec(h->hpet.timers, HPET_TN(CFG, addr)).config;
     case HPET_Tn_CMP(0):
     case HPET_Tn_CMP(1):
     case HPET_Tn_CMP(2):
-        return hpet_get_comparator(h, HPET_TN(CMP, addr), guest_time);
+        return hpet_get_comparator(h,
+                                   array_index_nospec(HPET_TN(CMP, addr),
+                                                      
ARRAY_SIZE(h->hpet.timers)),
+                                   guest_time);
     case HPET_Tn_ROUTE(0):
     case HPET_Tn_ROUTE(1):
     case HPET_Tn_ROUTE(2):
-        return h->hpet.timers[HPET_TN(ROUTE, addr)].fsb;
+        return array_access_nospec(h->hpet.timers, HPET_TN(ROUTE, addr)).fsb;
     }
 
     return 0;
@@ -438,7 +442,7 @@ static int hpet_write(
     case HPET_Tn_CFG(0):
     case HPET_Tn_CFG(1):
     case HPET_Tn_CFG(2):
-        tn = HPET_TN(CFG, addr);
+        tn = array_index_nospec(HPET_TN(CFG, addr), 
ARRAY_SIZE(h->hpet.timers));
 
         h->hpet.timers[tn].config =
             hpet_fixup_reg(new_val, old_val,
@@ -480,7 +484,7 @@ static int hpet_write(
     case HPET_Tn_CMP(0):
     case HPET_Tn_CMP(1):
     case HPET_Tn_CMP(2):
-        tn = HPET_TN(CMP, addr);
+        tn = array_index_nospec(HPET_TN(CMP, addr), 
ARRAY_SIZE(h->hpet.timers));
         if ( timer_is_periodic(h, tn) &&
              !(h->hpet.timers[tn].config & HPET_TN_SETVAL) )
         {
@@ -523,8 +527,7 @@ static int hpet_write(
     case HPET_Tn_ROUTE(0):
     case HPET_Tn_ROUTE(1):
     case HPET_Tn_ROUTE(2):
-        tn = HPET_TN(ROUTE, addr);
-        h->hpet.timers[tn].fsb = new_val;
+        array_access_nospec(h->hpet.timers, HPET_TN(ROUTE, addr)).fsb = 
new_val;
         break;
 
     default:
diff --git a/xen/include/xen/nospec.h b/xen/include/xen/nospec.h
index 48793996e8..8acfa60f1b 100644
--- a/xen/include/xen/nospec.h
+++ b/xen/include/xen/nospec.h
@@ -58,6 +58,12 @@ static inline unsigned long array_index_mask_nospec(unsigned 
long index,
     (typeof(_i)) (_i & _mask);                                          \
 })
 
+/*
+ * array_access_nospec - allow nospec access for static size arrays
+ */
+#define array_access_nospec(array, index)                               \
+    (array)[array_index_nospec(index, ARRAY_SIZE(array))]
+
 #endif /* XEN_NOSPEC_H */
 
 /*
--
generated by git-patchbot for /home/xen/git/xen.git#master

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/xen-changelog

 


Rackspace

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