This is a part of https://reviews.llvm.org/D95835.
The design is based on MSan origin chains.
An 4-byte origin is a hash of an origin chain. An origin chain is a
pair of a stack hash id and a hash to its previous origin chain. 0 means
no previous origin chains exist. We limit the length of a chain to be
16. With origin_history_size = 0, the limit is removed.
The change does not have any test cases yet. The following change
will be adding test cases when the APIs are used.
Reviewed-by: morehouse
Differential Revision: https://reviews.llvm.org/D96160
This is a part of https://reviews.llvm.org/D95835.
This change is to address two problems
1) When recording stacks in origin tracking, libunwind is not async signal safe. Inside signal callbacks, we need
to use fast unwind. Fast unwind needs threads
2) StackDepot used by origin tracking is not async signal safe, we set a flag per thread inside
a signal callback to prevent from using it.
The thread registration is similar to ASan and MSan.
Related MSan changes are
* 98f5ea0dba
* f653cda269
* 5a7c364343
Some changes in the diff are used in the next diffs
1) The test case pthread.c is not very interesting for now. It will be
extended to test origin tracking later.
2) DFsanThread::InSignalHandler will be used by origin tracking later.
Reviewed-by: morehouse
Differential Revision: https://reviews.llvm.org/D95963
DFSan uses TLS to pass metadata of arguments and return values. When an
instrumented function accesses the TLS, if a signal callback happens, and
the callback calls other instrumented functions with updating the same TLS,
the TLS is in an inconsistent state after the callback ends. This may cause
either under-tainting or over-tainting.
This fix follows MSan's workaround.
cb22c67a21
It simply resets TLS at restore. This prevents from over-tainting. Although
under-tainting may still happen, a taint flow can be found eventually if we
run a DFSan-instrumented program multiple times. The alternative option is
saving the entire TLS. However the TLS storage takes 2k bytes, and signal calls
could be nested. So it does not seem worth.
This diff fixes sigaction. A following diff will be fixing signal.
Reviewed-by: morehouse
Differential Revision: https://reviews.llvm.org/D95642
This is a child diff of D92261.
It extended TLS arg/ret to work with aggregate types.
For a function
t foo(t1 a1, t2 a2, ... tn an)
Its arguments shadow are saved in TLS args like
a1_s, a2_s, ..., an_s
TLS ret simply includes r_s. By calculating the type size of each shadow
value, we can get their offset.
This is similar to what MSan does. See __msan_retval_tls and __msan_param_tls
from llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp.
Note that this change does not add test cases for overflowed TLS
arg/ret because this is hard to test w/o supporting aggregate shdow
types. We will be adding them after supporting that.
Reviewed-by: morehouse
Differential Revision: https://reviews.llvm.org/D92440
It turned out that at dynamic shared library mode, the memory access
pattern can increase memory footprint significantly on OS when transparent
hugepages (THP) are enabled. This could cause >70x memory overhead than
running a static linked binary. For example, a static binary with RSS
overhead 300M can use > 23G RSS if it is built dynamically.
/proc/../smaps shows in 6204552 kB RSS 6141952 kB relates to
AnonHugePages.
Also such a high RSS happens in some rate: around 25% runs may use > 23G RSS, the
rest uses in between 6-23G. I guess this may relate to how user memory
is allocated and distributted across huge pages.
THP is a trade-off between time and space. We have a flag
no_huge_pages_for_shadow for sanitizer. It is true by default but DFSan
did not follow this. Depending on if a target is built statically or
dynamically, maybe Clang can set no_huge_pages_for_shadow accordingly
after this change. But it still seems fine to follow the default setting of
no_huge_pages_for_shadow. If time is an issue, and users are fine with
high RSS, this flag can be set to false selectively.
This is a follow up patch of https://reviews.llvm.org/D88755.
When set 0 label for an address range, we can release pages within the
corresponding shadow address range to OS, and set only addresses outside
the pages to be 0.
Reviewed-by: morehouse, eugenis
Differential Revision: https://reviews.llvm.org/D89199
While the instrumentation never calls dfsan_union in fast16labels mode,
the custom wrappers do. We detect fast16labels mode by checking whether
any labels have been created. If not, we must be using fast16labels
mode.
Reviewed By: vitalybuka
Differential Revision: https://reviews.llvm.org/D86012
Unmapping and remapping is dangerous since another thread could touch
the shadow memory while it is unmapped. But there is really no need to
unmap anyway, since mmap(MAP_FIXED) will happily clobber the existing
mapping with zeroes. This is thread-safe since the mmap() is done under
the same kernel lock as page faults are done.
Reviewed By: vitalybuka
Differential Revision: https://reviews.llvm.org/D85947
Adds the -fast-16-labels flag, which enables efficient instrumentation
for DFSan when the user needs <=16 labels. The instrumentation
eliminates most branches and most calls to __dfsan_union or
__dfsan_union_load.
Reviewed By: vitalybuka
Differential Revision: https://reviews.llvm.org/D84371
Support fast16labels in `dfsan_has_label`, and print an error for all
other API functions. For `dfsan_dump_labels` we return silently rather
than crashing since it is also called from the atexit handler where it
is undefined behavior to call exit() again.
Reviewed By: kcc
Differential Revision: https://reviews.llvm.org/D84215
Summary:
Support fast16labels in `dfsan_has_label`, and print an error for all
other API functions.
Reviewers: kcc, vitalybuka, pcc
Reviewed By: kcc
Subscribers: jfb, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D84215