On 05/01/18 11:37, Alexander Monakov wrote: > I believe the proposed behavior of the new builtin is over-specialized. > In principle the following snippet may be open to exploitation too: > > if (predicate) > foo = arr[(secret >> untrusted) & 64]; > > assuming the attacker has a means to observe which part of 'arr' is > brought into > cache, but cannot set 'predicate' to true (so has to rely on the speculative > population of the cache); and likewise if a store is predicated-off > rather than > a load. > > So shouldn't, for generality, the new builtin work "as if" by cleansing the > address rather than the result of the load, like the following? It would > also be > applicable to stores then.
This is quite tricky. For ARM we have to have a speculated load. So one way to recast this might be to push 'untrusted' into a stack slot that was then speculatively loaded back by the builtin. To do that you'd need to find a way of expressing predicate as a range check, so something like if (predicate) { foo = arr[(secret >> __builtin_load_no_speculate (&untrusted, predicate_base, predicate_upper, 0, predicate_val)) & 64)]; } You could use similar techniques with stores as well. I'm open to suggestions as to how we might express the conditions better. It's certainly the least pleasant part of this proposal, but the seemingly obvious '_Bool condition' parameter won't work because the compiler will just substitute true in too many situations where it thinks it has proved that it knows the conditions. R. > > On Thu, 4 Jan 2018, Richard Earnshaw wrote: >> inline TYP __builtin_load_no_speculate >> (const volatile TYP *ptr, >> const volatile void *lower, >> const volatile void *upper, >> TYP failval, >> const volatile void *cmpptr) >> { >> TYP result; >> >> if (cmpptr >= lower && cmpptr < upper) >> result = *ptr; >> else >> result = failval; >> return result; >> } > > { > if (!(cmpptr >= lower && cmpptr < upper)) > ptr = NULL; > > return *ptr; > } > > Alexander