On 5/23/19 16:17, Jan Beulich wrote:
>>>> On 21.05.19 at 09:45, <nmant...@amazon.de> wrote:
>> Guests can issue grant table operations and provide guest controlled
>> data to them. This data is used as index for memory loads after bound
>> checks have been done. To avoid speculative out-of-bound accesses, we
>> use the array_index_nospec macro where applicable, or the macro
>> block_speculation. Note, that the block_speculation is always used in
> s/always/already/ ?
They both work, but the 'always' underlines that a caller can rely on
the fact that this will happen on all execution path of that function.
Hence, I like to stick to 'always' here.
>
>> the calls to shared_entry_header and nr_grant_entries, so that no
>> additional protection is required once these functions have been
>> called.
> Isn't this too broad a statement? There's some protection, but not
> for just anything that follows.
You are right, to given protection is that any bound check that could
have been bypassed speculatively is enforced after calling one of the
two functions. I will rephrase the commit message accordingly.
>
>> --- a/xen/common/grant_table.c
>> +++ b/xen/common/grant_table.c
>> @@ -988,9 +988,10 @@ map_grant_ref(
>>          PIN_FAIL(unlock_out, GNTST_bad_gntref, "Bad ref %#x for d%d\n",
>>                   op->ref, rgt->domain->domain_id);
>>  
>> -    act = active_entry_acquire(rgt, op->ref);
>> +    /* This call also ensures the above check cannot be passed 
>> speculatively */
>>      shah = shared_entry_header(rgt, op->ref);
>>      status = rgt->gt_version == 1 ? &shah->flags : &status_entry(rgt, 
>> op->ref);
>> +    act = active_entry_acquire(rgt, op->ref);
> I know we've been there before, but what guarantees that the
> compiler won't reload op->ref from memory for either of the
> latter two accesses? In fact afaict it always will, due to the
> memory clobber in alternative().
The compiler can reload op->ref from memory, that is fine here, as the
bound check happens above, and the shared_entry call comes with an
lfence() by now, so that we will not continue executing speculatively
with op->ref being out-of-bounds, independently of whether it's from
memory or registers.
>
>> @@ -3863,6 +3883,9 @@ static int gnttab_get_status_frame_mfn(struct domain 
>> *d,
>>              return -EINVAL;
>>      }
>>  
>> +    /* Make sure idx is bounded wrt nr_status_frames */
>> +    block_speculation();
>> +
>>      *mfn = _mfn(virt_to_mfn(gt->status[idx]));
>>      return 0;
>>  }
> Why don't you use array_index_nospec() here? And how come
There is no specific reason. I will swap.
> speculation into gnttab_grow_table() is fine a few lines above?
I do not see a reason why it would be bad to enter that function
speculatively. There are no accesses that would have to be protected by
extra checks, afaict. Otherwise, that function should be protected by
its own.
> And what about the similar code in gnttab_get_shared_frame_mfn()?
I will add an array_nospec_index there as well.
>
> Jan
>
>




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@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

Reply via email to