From af440a75f0abd564c08534a5db1d4971059a89f4 Mon Sep 17 00:00:00 2001 From: Norbert Manthey Subject: [PATCH SpectreV1+L1TF 08/13] common/gant_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. This is part of the SpectreV1+L1TF mitigation patch series. Signed-off-by: Norbert Manthey --- xen/common/grant_table.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) 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 #include #include +#include #include #include @@ -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 */ + rmb(); + 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 */ + rmb(); + sha = shared_entry_header(rgt, ref); scombo.word = *(u32 *)&sha->flags; @@ -2239,6 +2247,9 @@ gnttab_transfer( goto unlock_and_copyback; } + /* Make sure the above check is not bypassed speculatively */ + rmb(); + page_list_add_tail(page, &e->page_list); page_set_owner(page, e); @@ -2408,6 +2419,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 */ + rmb(); + act = active_entry_acquire(rgt, gref); shah = shared_entry_header(rgt, gref); if ( rgt->gt_version == 1 ) @@ -2812,6 +2826,9 @@ static int gnttab_copy_buf(const struct gnttab_copy *op, ((op->dest.offset + op->len) > PAGE_SIZE) ) PIN_FAIL(out, GNTST_bad_copy_arg, "copy beyond page area\n"); + /* Make sure the above check is not bypassed speculatively */ + rmb(); + if ( op->source.offset < src->ptr.offset || op->source.offset + op->len > src->ptr.offset + src->len ) PIN_FAIL(out, GNTST_general_error, @@ -3215,6 +3232,9 @@ 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 */ + rmb(); + act_a = active_entry_acquire(gt, ref_a); if ( act_a->pin ) PIN_FAIL(out, GNTST_eagain, "ref a %#x busy\n", ref_a); -- 2.7.4