On Tue, Apr 25, 2017 at 4:26 AM, PaX Team <pageexec@xxxxxxxxxxx> wrote: > On 25 Apr 2017 at 0:01, Peter Zijlstra wrote: >> How is the below not useful fodder for an exploit? It might be a less >> common bug, and perhaps a bit more fiddly to make work, but afaict its >> still a full use-after-free and therefore useful. >> >> --- >> >> Thread-A Thread-B >> >> if(dec_and_test(&obj->ref)) { // true, ref==0 >> >> inc(&obj->ref) // ref: 0->1 >> >> kfree(obj); >> } > > ... and tell me why an attacker would let Thread-B do that increment > (that you're trying to detect) *before* the underlying memory gets > reused and thus the 0 changed to something else? hint: he'll do everything > in his power to prevent that, either by winning the race or if there's > no race (no refcount users outside his control), he'll win every time. > IOW, checking for 0 is pointless and you kinda proved it yourself now. Right, having a deterministic protection (checking for overflow) is best since it stops all exploits using that path. Hoping that an attacker is unlucky and hits a notification after they've already landed their corruption is not a very useful defense. It certainly has a non-zero value, but stopping overflow 100% is better. Especially when we can do it with no meaningful change in performance which lets us actually do the atomic_t -> refcount_t conversion everywhere. -Kees -- Kees Cook Pixel Security