[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 |