This is an archive of the discontinued LLVM Phabricator instance.

[scudo] Fix race condition in deallocation path when Quarantine is bypassed
ClosedPublic

Authored by cryptoad on Aug 13 2018, 11:37 AM.

Details

Summary

There is a race window in the deallocation path when the Quarantine is bypassed.
Initially we would just erase the header of a chunk if we were not to use the
Quarantine, as opposed to using a compare-exchange primitive, to make things
faster.

It turned out to be a poor decision, as 2 threads (or more) could simultaneously
deallocate the same pointer, and if the checks were to done before the header
got erased, this would result in the pointer being added twice (or more) to
distinct thread caches, and eventually be reused.

Winning the race is not trivial but can happen with enough control over the
allocation primitives. The repro added attempts to trigger the bug, with a
moderate success rate, but it should be enough to notice if the bug ever make
its way back into the code.

Since I am changing things in this file, there are 2 smaller changes tagging
along, marking a variable const, and improving the Quarantine bypass test at
runtime.

Diff Detail

Event Timeline

cryptoad created this revision.Aug 13 2018, 11:37 AM
Herald added subscribers: Restricted Project, delcypher. · View Herald TranscriptAug 13 2018, 11:37 AM
cryptoad updated this revision to Diff 160443.Aug 13 2018, 1:53 PM

Account for 0 size, which is more common than one would expect.

eugenis accepted this revision.Aug 13 2018, 2:00 PM
eugenis added reviewers: kcc, vitalybuka.

I'm not very familiar with this code, but the change kind of makes sense.

lib/scudo/scudo_allocator.cpp
392

why are you removing this condition?

(Quarantine.GetCacheSize() == 0)

This revision is now accepted and ready to land.Aug 13 2018, 2:00 PM
vitalybuka accepted this revision.Aug 13 2018, 2:05 PM
cryptoad added inline comments.Aug 13 2018, 2:29 PM
lib/scudo/scudo_allocator.cpp
392

So I moved (Quarantine.GetCacheSize() == 0) higher (in init), effectively setting QuarantineChunksUpToSize to 0 in that case.
It was something I intended to do before to consolidate the conditions into a single memory read.

cryptoad updated this revision to Diff 160462.Aug 13 2018, 3:06 PM

Grammar/punctuation corrections in comments.

cryptoad added inline comments.Aug 14 2018, 11:09 AM
lib/scudo/scudo_allocator.cpp
392

Does the answer address your concerns?

eugenis accepted this revision.Aug 14 2018, 11:32 AM

LGTM

lib/scudo/scudo_allocator.cpp
392

Yes it does!
Sorry I missed it.

This revision was automatically updated to reflect the committed changes.