|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH SpectreV1+L1TF v4 05/11] common/grant_table: block speculative out-of-bound accesses
Guests can issue grant table operations and provide guest controlled
data to them. This data is also used for memory loads. To avoid
speculative out-of-bound accesses, we use the array_index_nospec macro
where applicable. However, there are also memory accesses that cannot
be protected by a single array protection, or multiple accesses in a
row. To protect these, an lfence instruction is placed between the
actual range check and the access via the newly introduced macro
block_speculation.
This commit is part of the SpectreV1+L1TF mitigation patch series.
Signed-off-by: Norbert Manthey <nmanthey@xxxxxxxxx>
---
xen/common/grant_table.c | 23 +++++++++++++++++++++--
xen/include/xen/nospec.h | 9 +++++++++
2 files changed, 30 insertions(+), 2 deletions(-)
diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
--- a/xen/common/grant_table.c
+++ b/xen/common/grant_table.c
@@ -37,6 +37,7 @@
#include <xen/paging.h>
#include <xen/keyhandler.h>
#include <xen/vmap.h>
+#include <xen/nospec.h>
#include <xsm/xsm.h>
#include <asm/flushtlb.h>
@@ -963,6 +964,9 @@ map_grant_ref(
PIN_FAIL(unlock_out, GNTST_bad_gntref, "Bad ref %#x for d%d\n",
op->ref, rgt->domain->domain_id);
+ /* Make sure the above check is not bypassed speculatively */
+ op->ref = array_index_nospec(op->ref, nr_grant_entries(rgt));
+
act = active_entry_acquire(rgt, op->ref);
shah = shared_entry_header(rgt, op->ref);
status = rgt->gt_version == 1 ? &shah->flags : &status_entry(rgt, op->ref);
@@ -1268,7 +1272,8 @@ unmap_common(
}
smp_rmb();
- map = &maptrack_entry(lgt, op->handle);
+ map = &maptrack_entry(lgt, array_index_nospec(op->handle,
+ lgt->maptrack_limit));
if ( unlikely(!read_atomic(&map->flags)) )
{
@@ -2026,6 +2031,9 @@ gnttab_prepare_for_transfer(
goto fail;
}
+ /* Make sure the above check is not bypassed speculatively */
+ ref = array_index_nospec(ref, nr_grant_entries(rgt));
+
sha = shared_entry_header(rgt, ref);
scombo.word = *(u32 *)&sha->flags;
@@ -2223,7 +2231,8 @@ gnttab_transfer(
okay = gnttab_prepare_for_transfer(e, d, gop.ref);
spin_lock(&e->page_alloc_lock);
- if ( unlikely(!okay) || unlikely(e->is_dying) )
+ /* Make sure this check is not bypassed speculatively */
+ if ( evaluate_nospec(unlikely(!okay) || unlikely(e->is_dying)) )
{
bool_t drop_dom_ref = !domain_adjust_tot_pages(e, -1);
@@ -2408,6 +2417,9 @@ acquire_grant_for_copy(
PIN_FAIL(gt_unlock_out, GNTST_bad_gntref,
"Bad grant reference %#x\n", gref);
+ /* Make sure the above check is not bypassed speculatively */
+ gref = array_index_nospec(gref, nr_grant_entries(rgt));
+
act = active_entry_acquire(rgt, gref);
shah = shared_entry_header(rgt, gref);
if ( rgt->gt_version == 1 )
@@ -2826,6 +2838,9 @@ static int gnttab_copy_buf(const struct gnttab_copy *op,
op->dest.offset, dest->ptr.offset,
op->len, dest->len);
+ /* Make sure the above checks are not bypassed speculatively */
+ block_speculation();
+
memcpy(dest->virt + op->dest.offset, src->virt + op->source.offset,
op->len);
gnttab_mark_dirty(dest->domain, dest->mfn);
@@ -3215,6 +3230,10 @@ swap_grant_ref(grant_ref_t ref_a, grant_ref_t ref_b)
if ( ref_a == ref_b )
goto out;
+ /* Make sure the above check is not bypassed speculatively */
+ ref_a = array_index_nospec(ref_a, nr_grant_entries(d->grant_table));
+ ref_b = array_index_nospec(ref_b, nr_grant_entries(d->grant_table));
+
act_a = active_entry_acquire(gt, ref_a);
if ( act_a->pin )
PIN_FAIL(out, GNTST_eagain, "ref a %#x busy\n", ref_a);
diff --git a/xen/include/xen/nospec.h b/xen/include/xen/nospec.h
--- a/xen/include/xen/nospec.h
+++ b/xen/include/xen/nospec.h
@@ -87,6 +87,15 @@ static inline bool lfence_true(void) { return true; }
#define evaluate_nospec(condition) ({ bool res = (condition); rmb(); res; })
#endif
+/*
+ * allow to block speculative execution in generic code
+ */
+#ifdef CONFIG_X86
+#define block_speculation() rmb()
+#else
+#define block_speculation()
+#endif
+
#endif /* XEN_NOSPEC_H */
/*
--
2.7.4
Amazon Development Center Germany GmbH
Krausenstr. 38
10117 Berlin
Geschaeftsfuehrer: Christian Schlaeger, Ralf Herbrich
Ust-ID: DE 289 237 879
Eingetragen am Amtsgericht Charlottenburg HRB 149173 B
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |