This is an archive of the discontinued LLVM Phabricator instance.

[dfsan] Use the sanitizer allocator to reduce memory cost
ClosedPublic

Authored by stephan.yichao.zhao on Apr 23 2021, 3:56 PM.

Details

Summary

dfsan does not use sanitizer allocator as others. In practice,
we let it use glibc's allocator since tcmalloc needs more work
to be working with dfsan well. With glibc, we observe large
memory leakage. This could relate to two things:

  1. glibc allocator has limitation: for example, tcmalloc can reduce memory footprint 2x easily
  1. glibc may call unmmap directly as an internal system call by using system call number. so DFSan has no way to release shadow spaces for those unmmap.

Using sanitizer allocator addresses the above issues

  1. its memory management is close to tcmalloc
  1. we can register callback when sanitizer allocator calls unmmap, so dfsan can release shadow spaces correctly.

Our experiment with internal server-based application proved that with the change, in a-few-day run, memory usage leakage is close to what tcmalloc does w/o dfsan.

This change mainly follows MSan's code.

  1. define allocator callbacks at dfsan_allocator.h|cpp
  1. mark allocator APIs to be discard
  1. intercept allocator APIs
  1. make dfsan_set_label consistent with MSan's SetShadow when setting 0 labels, define dfsan_release_meta_memory when unmap is called
  1. add flags about whether zeroing memory after malloc/free. dfsan works at byte-level, so bit-level oparations can cause reading undefined shadow. See D96842. zeroing memory after malloc helps this. About zeroing after free, reading after free is definitely UB, but if user code does so, it is hard to debug an overtainting caused by this w/o running MSan. So we add the flag to help debugging.

This change will be split to small changes for review. Before that, a question is
"this code shares a lot of with MSan, for example, dfsan_allocator.* and dfsan_new_delete.*.
Does it make sense to unify the code at sanitizer_common? will that introduce some
maintenance issue?"

Diff Detail

Event Timeline

stephan.yichao.zhao requested review of this revision.Apr 23 2021, 3:56 PM
Herald added a project: Restricted Project. · View Herald TranscriptApr 23 2021, 3:56 PM
Herald added a subscriber: Restricted Project. · View Herald Transcript
stephan.yichao.zhao edited the summary of this revision. (Show Details)Apr 23 2021, 3:59 PM
stephan.yichao.zhao edited the summary of this revision. (Show Details)
stephan.yichao.zhao edited the summary of this revision. (Show Details)
eugenis edited reviewers, added: eugenis; removed: evghenii.Apr 23 2021, 4:18 PM

If there is a clean way to share code, I would be in favor of doing that. Otherwise we can have some duplication like all the other sanitizers.

stephan.yichao.zhao planned changes to this revision.Apr 26 2021, 3:22 PM

If there is a clean way to share code, I would be in favor of doing that. Otherwise we can have some duplication like all the other sanitizers.

I will try make a change to demo if this possible.

Demo-ed a potential code reuse change at https://reviews.llvm.org/D101599, planned to have a separate allocator to DFSan to reduce code impact.

stephan.yichao.zhao edited the summary of this revision. (Show Details)

update

stephan.yichao.zhao planned changes to this revision.Apr 30 2021, 10:00 PM
morehouse added inline comments.May 12 2021, 10:51 AM
compiler-rt/lib/dfsan/dfsan_interceptors.cpp
167

ctx doesn't appear to be meaningfully used. Can we remove it along with DFSanInterceptorContext?

170

This macro seems more confusing than just using !__dfsan::dfsan_inited.

compiler-rt/lib/dfsan/dfsan_new_delete.cpp
80
83
95
101
stephan.yichao.zhao marked 2 inline comments as done.

update

compiler-rt/lib/dfsan/dfsan_new_delete.cpp
80

The arc linter enforced the format in this file. Will try fix them at git push.

This revision is now accepted and ready to land.May 12 2021, 3:52 PM

added a missing test case