On 31/01/2019 16:19, Jan Beulich wrote: > >> @@ -4104,6 +4108,12 @@ static int hvmop_set_param( >> if ( a.index >= HVM_NR_PARAMS ) >> return -EINVAL; >> >> + /* >> + * Make sure the guest controlled value a.index is bounded even during >> + * speculative execution. >> + */ >> + a.index = array_index_nospec(a.index, HVM_NR_PARAMS); > I'd like to come back to this model of updating local variables: > Is this really safe to do? If such a variable lives in memory > (which here it quite likely does), does speculation always > recognize the update to the value? Wouldn't it rather read > what's currently in that slot, and re-do the calculation in case > a subsequent write happens? (I know I did suggest doing so > earlier on, so I apologize if this results in you having to go > back to some earlier used model.)
I'm afraid that is a very complicated set of questions to answer. The processor needs to track write=>read dependencies to avoid wasting a large quantity of time doing erroneous speculation, therefore it does. Pending writes which have happened under speculation are forwarded to dependant instructions. This behaviour is what gives rise to Bounds Check Bypass Store - a half spectre-v1 gadget but with a store rather than a write. You can e.g. speculatively modify the return address on the stack, and hijack speculation to an attacker controlled address for a brief period of time. If the speculation window is long enough, the processor first follows the RSB/RAS (correctly), then later notices that the real value on the stack was different, discards the speculation from the RSB/RAS and uses the attacker controlled value instead, then eventually notices that all of this was bogus and rewinds back to the original branch. Another corner case is Speculative Store Bypass, where memory disambiguation speculation can miss the fact that there is a real write=>read dependency, and cause speculation using the older stale value for a period of time. As to overall safety, array_index_nospec() only works as intended when the index remains in a register between the cmp/sbb which bounds it under speculation, and the array access. There is no way to guarantee this property, as the compiler can spill any value if it thinks it needs to. The general safety of the construct relies on the fact that an optimising compiler will do its very best to avoid spilling variable to the stack. As with all of these issues, you can only confirm whether you are no longer vulnerable by inspecting the eventual compiled code. ~Andrew _______________________________________________ Xen-devel mailing list Xen-devel@lists.xenproject.org https://lists.xenproject.org/mailman/listinfo/xen-devel