This is an archive of the discontinued LLVM Phabricator instance.

[Asan] Fix false leak report
ClosedPublic

Authored by vitalybuka on Sep 11 2020, 4:51 PM.

Details

Summary

If user thread is in the allocator, the allocator
may have no pointer into future user's part of
the allocated block. AddrIsInside ignores such
pointers and lsan reports a false memory leak.

Diff Detail

Event Timeline

vitalybuka created this revision.Sep 11 2020, 4:51 PM
Herald added a project: Restricted Project. · View Herald TranscriptSep 11 2020, 4:51 PM
Herald added a subscriber: Restricted Project. · View Herald Transcript
vitalybuka requested review of this revision.Sep 11 2020, 4:51 PM

re-word comment

morehouse accepted this revision.Sep 14 2020, 9:32 AM
morehouse added inline comments.
compiler-rt/lib/asan/asan_allocator.cpp
1120–1125
This revision is now accepted and ready to land.Sep 14 2020, 9:32 AM
vitalybuka marked an inline comment as done.

comments

This revision was landed with ongoing or failed builds.Sep 14 2020, 1:32 PM
This revision was automatically updated to reflect the committed changes.
morehouse added inline comments.Sep 15 2020, 3:14 PM
compiler-rt/lib/asan/asan_allocator.cpp
1121

Removing this check seems to introduce some LSan false negatives. Ran into it while playing with libFuzzer:

$ bin/clang++ -fsanitize=address,fuzzer ../compiler-rt/test/fuzzer/LeakTest.cpp -m32 -g
$ rm -rf corpus && mkdir corpus
$ ./a.out -runs=100000 -detect_leaks=1 -entropic=1 -seed=1 corpus/

libFuzzer finds an input H that triggers a leak, but LSan doesn't detect it. Only happens after this patch, and only with -m32.

Still trying to figure out why this check is needed...

morehouse added inline comments.Sep 15 2020, 3:23 PM
compiler-rt/lib/asan/asan_allocator.cpp
1121

Presumably we have some internal pointer to the ASanChunk header that is causing the allocation to be marked reachable.

thanks

compiler-rt/lib/asan/asan_allocator.cpp
1121

I don't know what to do about this.
E.g. vector<> usually keeps end() pointer which can be the first byte of the next chunk. Before the patch is was not an issue.
But now it's going to hold next chunk as reachable.

morehouse added inline comments.Sep 15 2020, 4:19 PM
compiler-rt/lib/asan/asan_allocator.cpp
1121

Shouldn't the acquire-load above be enough to guarantee that we've stored a pointer to the user allocation either on stack or in a register, since we store-release in Allocate()?

vitalybuka added inline comments.Sep 15 2020, 4:53 PM
compiler-rt/lib/asan/asan_allocator.cpp
1121

I think not, memory order only requires that we return same as user_beg calculated before atomic operation.

morehouse added inline comments.Sep 15 2020, 5:12 PM
compiler-rt/lib/asan/asan_allocator.cpp
1121

Can we force the guarantee, for example by storing to a volatile stack variable before store-releasing?

If we can, then the LSan false positive this patch fixed shouldn't come back if we add the AddrIsInside check back.

vitalybuka added inline comments.Sep 15 2020, 5:36 PM
compiler-rt/lib/asan/asan_allocator.cpp
1121

Actually I tried that after landing the patch, and I still see the same bug on that binary. Either my way to pin pointer is too week, or I misdiagnosed the bug. I am trying to add more logs to confirm either way.

However even if pinning pointer is possible we have case when we have small allocations without magic. There is a probability that the primary allocator returns CHUNK_ALLOCATED for uninitialized chunk. It's theoretical but I was able to catch that with CHECK(). I tried to solve that with that patch which always adds magic, the one which extends header from 16 to 24 D87359.
I have idea how to use size bits for additional validation magic, as we need magic only when we have small size and we don't use most of bits. But it's needed only we can have guaranteed user pointer.

vitalybuka added inline comments.Sep 15 2020, 11:28 PM
compiler-rt/lib/asan/asan_allocator.cpp
1121

Compiler puts pointer into FP registers.
I will undo this patch and fix how we read registers.