Similar to __asan_set_error_report_callback, pass the entire report to a
user provided callback function.
Differential Revision: https://reviews.llvm.org/D91825
HwasanThreadList::DontNeedThread clobbers Thread::next_,
Breaking the freelist. As a result, only the top of the freelist ever
gets reused, and the rest of it is lost.
Since the Thread object with its associated ring buffer is only 8Kb, this is
typically only noticable in long running processes, such as fuzzers.
Fix the problem by switching from an intrusive linked list to a vector.
Differential Revision: https://reviews.llvm.org/D91392
In `GetGlobalSizeFromDescriptor` we use `dladdr` to get info on the the
current address. `dladdr` returns 0 if it failed.
During testing on Linux this returned 0 to indicate failure, and
populated the `info` structure with a NULL pointer which was
dereferenced later.
This patch checks for `dladdr` returning 0, and in that case returns 0
from `GetGlobalSizeFromDescriptor` to indicate failure of identifying
the address.
This occurs when `GetModuleNameAndOffsetForPC` succeeds for some address
not in a dynamically loaded library. One example is when the found
"module" is '[stack]' having come from parsing /proc/self/maps.
Differential Revision: https://reviews.llvm.org/D91344
HwasanThreadList::DontNeedThread clobbers Thread::next_, breaking the
freelist. As a result, only the top of the freelist ever gets reused,
and the rest of it is lost.
Since the Thread object its associated ring buffer is only 8Kb, this is
typically only noticable in long running processes, such as fuzzers.
Fix the problem by switching from an intrusive linked list to a vector.
Differential Revision: https://reviews.llvm.org/D91208
It turns out that we can't remove the operator new and delete
interceptors on Android without breaking ABI, so bring them back
as forwards to the malloc and free functions.
Differential Revision: https://reviews.llvm.org/D91219
While sanitizers don't use C++ standard library, we could still end
up accidentally including or linking it just by the virtue of using
the C++ compiler. Pass -nostdinc++ and -nostdlib++ to avoid these
accidental dependencies.
Differential Revision: https://reviews.llvm.org/D88922
Adds a check to avoid symbolization when printing stack traces if the
stack_trace_format flag does not need it. While there is a symbolize
flag that can be turned off to skip some of the symbolization,
SymbolizePC() still unconditionally looks up the module name and offset.
Avoid invoking SymbolizePC() at all if not needed.
This is an efficiency improvement when dumping all stack traces as part
of the memory profiler in D87120, for large stripped apps where we want
to symbolize as a post pass.
Differential Revision: https://reviews.llvm.org/D88361
D28596 added SANITIZER_INTERFACE_WEAK_DEF which can guarantee `*_default_options` are always defined.
The weak attributes on the `__{asan,lsan,msan,ubsan}_default_options` declarations can thus be removed.
`MaybeCall*DefaultOptions` no longer need nullptr checks, so their call sites can just be replaced by `__*_default_options`.
Reviewed By: #sanitizers, vitalybuka
Differential Revision: https://reviews.llvm.org/D87175
Summary:
This refactors some common support related to shadow memory setup from
asan and hwasan into sanitizer_common. This should not only reduce code
duplication but also make these facilities available for new compiler-rt
uses (e.g. heap profiling).
In most cases the separate copies of the code were either identical, or
at least functionally identical. A few notes:
In ProtectGap, the asan version checked the address against an upper
bound (kZeroBaseMaxShadowStart, which is (2^18). I have created a copy
of kZeroBaseMaxShadowStart in hwasan_mapping.h, with the same value, as
it isn't clear why that code should not do the same check. If it
shouldn't, I can remove this and guard this check so that it only
happens for asan.
In asan's InitializeShadowMemory, in the dynamic shadow case it was
setting __asan_shadow_memory_dynamic_address to 0 (which then sets both
macro SHADOW_OFFSET as well as macro kLowShadowBeg to 0) before calling
FindDynamicShadowStart(). AFAICT this is only needed because
FindDynamicShadowStart utilizes kHighShadowEnd to
get the shadow size, and kHighShadowEnd is a macro invoking
MEM_TO_SHADOW(kHighMemEnd) which in turn invokes:
(((kHighMemEnd) >> SHADOW_SCALE) + (SHADOW_OFFSET))
I.e. it computes the shadow space needed by kHighMemEnd (the shift), and
adds the offset. Since we only want the shadow space here, the earlier
setting of SHADOW_OFFSET to 0 via __asan_shadow_memory_dynamic_address
accomplishes this. In the hwasan version, it simply gets the shadow
space via "MemToShadowSize(kHighMemEnd)", where MemToShadowSize just
does the shift. I've simplified the asan handling to do the same
thing, and therefore was able to remove the setting of the SHADOW_OFFSET
via __asan_shadow_memory_dynamic_address to 0.
Reviewers: vitalybuka, kcc, eugenis
Subscribers: dberris, #sanitizers, llvm-commits, davidxl
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D83247
Summary: Refactor the current global header iteration to be callback-based, and add a feature that reports the size of the global variable during reporting. This allows binaries without symbols to still report the size of the global variable, which is always available in the HWASan globals PT_NOTE metadata.
Reviewers: eugenis, pcc
Reviewed By: pcc
Subscribers: mgorny, llvm-commits, #sanitizers
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D80599
Summary: Non-zero malloc fill is causing way too many hard to debug issues.
Reviewers: kcc, pcc, hctim
Subscribers: #sanitizers, llvm-commits
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D81284
Summary:
This is necessary to handle calls to free() after __hwasan_thread_exit,
which is possible in glibc.
Also, add a null check to GetCurrentThread, otherwise the logic in
GetThreadByBufferAddress turns it into a non-null value. This means that
all of the checks for GetCurrentThread() != nullptr do not have any
effect at all right now!
Reviewers: pcc, hctim
Subscribers: #sanitizers, llvm-commits
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D79608
Summary:
Fix parsing of mangled stack trace lines where the address has been
replaced with "0x", literally.
Reviewers: vitalybuka
Subscribers: #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D73823
Summary:
A script to symbolize hwasan reports after the fact using unstripped
binaries. Supports stack-based reports. Requires llvm-symbolizer
(addr2line is not an option).
Reviewers: pcc, hctim
Subscribers: mgorny, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D71148
Shadow memory (and short granules) are not prepended with memory
address and arrow at the end of line is removed.
Differential Revision: https://reviews.llvm.org/D70707
This was an experiment made possible by a non-standard feature of the
Android dynamic loader.
It required introducing a flag to tell the compiler which ABI was being
targeted.
This flag is no longer needed, since the generated code now works for
both ABI's.
We leave that flag untouched for backwards compatibility. This also
means that if we need to distinguish between targeted ABI's again
we can do that without disturbing any existing workflows.
We leave a comment in the source code and mention in the help text to
explain this for any confused person reading the code in the future.
Patch by Matthew Malcomson
Differential Revision: https://reviews.llvm.org/D69574
Summary:
The hwasan interceptor ABI doesn't have interceptors for longjmp and setjmp.
This patch introduces them.
We require the size of the jmp_buf on the platform to be at least as large as
the jmp_buf in our implementation. To enforce this we compile
hwasan_type_test.cpp that ensures a compile time failure if this is not true.
Tested on both GCC and clang using an AArch64 virtual machine.
Reviewers: eugenis, kcc, pcc, Sanatizers
Reviewed By: eugenis, Sanatizers
Tags: #sanatizers, #llvm
Differential Revision: https://reviews.llvm.org/D69045
Patch By: Matthew Malcomson <matthew.malcomson@arm.com>
Summary:
GCC would like to emit a function call to report a tag mismatch
rather than hard-code the `brk` instruction directly.
__hwasan_tag_mismatch_stub contains most of the functionality to do
this already, but requires exposure in the dynamic library.
This patch moves __hwasan_tag_mismatch_stub outside of the anonymous
namespace that it was defined in and declares it in
hwasan_interface_internal.h.
We also add the ability to pass sizes larger than 16 bytes to this
reporting function by providing a fourth parameter that is only looked
at when the size provided is not in the original accepted range.
This does not change the behaviour where it is already being called,
since the previous definition only accepted sizes up to 16 bytes and
hence the change in behaviour is not seen by existing users.
The change in declaration does not matter, since the only existing use
is in the __hwasan_tag_mismatch function written in assembly.
Reviewers: eugenis, kcc, pcc, #sanitizers
Reviewed By: eugenis, #sanitizers
Subscribers: kristof.beyls, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D69113
Patch by Matthew Malcomson <matthew.malcomson@arm.com>
Summary:
GCC would like to emit a function call to report a tag mismatch
rather than hard-code the `brk` instruction directly.
__hwasan_tag_mismatch_stub contains most of the functionality to do
this already, but requires exposure in the dynamic library.
This patch moves __hwasan_tag_mismatch_stub outside of the anonymous
namespace that it was defined in and declares it in
hwasan_interface_internal.h.
We also add the ability to pass sizes larger than 16 bytes to this
reporting function by providing a fourth parameter that is only looked
at when the size provided is not in the original accepted range.
This does not change the behaviour where it is already being called,
since the previous definition only accepted sizes up to 16 bytes and
hence the change in behaviour is not seen by existing users.
The change in declaration does not matter, since the only existing use
is in the __hwasan_tag_mismatch function written in assembly.
Tested with gcc and clang on an AArch64 vm.
Reviewers: eugenis, kcc, pcc, #sanitizers
Reviewed By: eugenis, #sanitizers
Subscribers: kristof.beyls, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D69113
Summary:
This has been an experiment with late malloc interposition, made
possible by a non-standard feature of the Android dynamic loader.
Reviewers: pcc, mmalcomson
Subscribers: srhines, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D69199
llvm-svn: 375296
Summary:
Until now AArch64 development has been on patched kernels that have an always
on relaxed syscall ABI where tagged pointers are accepted.
The patches that have gone into the mainline kernel rely on each process opting
in to this relaxed ABI.
This commit adds code to choose that ABI into __hwasan_init.
The idea has already been agreed with one of the hwasan developers
(http://lists.llvm.org/pipermail/llvm-dev/2019-September/135328.html).
The patch ignores failures of `EINVAL` for Android, since there are older versions of the Android kernel that don't require this `prctl` or even have the relevant values. Avoiding EINVAL will let the library run on them.
I've tested this on an AArch64 VM running a kernel that requires this
prctl, having compiled both with clang and gcc.
Patch by Matthew Malcomson.
Reviewers: eugenis, kcc, pcc
Reviewed By: eugenis
Subscribers: srhines, kristof.beyls, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D68794
llvm-svn: 375166
We can't use short granules with stack instrumentation when targeting older
API levels because the rest of the system won't understand the short granule
tags stored in shadow memory.
Moreover, we need to be able to let old binaries (which won't understand
short granule tags) run on a new system that supports short granule
tags. Such binaries will call the __hwasan_tag_mismatch function when their
outlined checks fail. We can compensate for the binary's lack of support
for short granules by implementing the short granule part of the check in
the __hwasan_tag_mismatch function. Unfortunately we can't do anything about
inline checks, but I don't believe that we can generate these by default on
aarch64, nor did we do so when the ABI was fixed.
A new function, __hwasan_tag_mismatch_v2, is introduced that lets code
targeting the new runtime avoid redoing the short granule check. Because tag
mismatches are rare this isn't important from a performance perspective; the
main benefit is that it introduces a symbol dependency that prevents binaries
targeting the new runtime from running on older (i.e. incompatible) runtimes.
Differential Revision: https://reviews.llvm.org/D68059
llvm-svn: 373035
There is no requirement for the producer of a note to include the note
alignment in these fields. As a result we can end up missing the HWASAN note
if one of the other notes in the binary has the alignment missing.
Differential Revision: https://reviews.llvm.org/D66692
llvm-svn: 369826
One problem with untagging memory in landing pads is that it only works
correctly if the function that catches the exception is instrumented.
If the function is uninstrumented, we have no opportunity to untag the
memory.
To address this, replace landing pad instrumentation with personality function
wrapping. Each function with an instrumented stack has its personality function
replaced with a wrapper provided by the runtime. Functions that did not have
a personality function to begin with also get wrappers if they may be unwound
past. As the unwinder calls personality functions during stack unwinding,
the original personality function is called and the function's stack frame is
untagged by the wrapper if the personality function instructs the unwinder
to keep unwinding. If unwinding stops at a landing pad, the function is
still responsible for untagging its stack frame if it resumes unwinding.
The old landing pad mechanism is preserved for compatibility with old runtimes.
Differential Revision: https://reviews.llvm.org/D66377
llvm-svn: 369721
See D65364 for the code model requirements for tagged globals. Because
of the relocations used these requirements cannot be checked at link
time so they must be checked at runtime.
Differential Revision: https://reviews.llvm.org/D65968
llvm-svn: 368351
Globals are instrumented by adding a pointer tag to their symbol values
and emitting metadata into a special section that allows the runtime to tag
their memory when the library is loaded.
Due to order of initialization issues explained in more detail in the comments,
shadow initialization cannot happen during regular global initialization.
Instead, the location of the global section is marked using an ELF note,
and we require libc support for calling a function provided by the HWASAN
runtime when libraries are loaded and unloaded.
Based on ideas discussed with @evgeny777 in D56672.
Differential Revision: https://reviews.llvm.org/D65770
llvm-svn: 368102
A short granule is a granule of size between 1 and `TG-1` bytes. The size
of a short granule is stored at the location in shadow memory where the
granule's tag is normally stored, while the granule's actual tag is stored
in the last byte of the granule. This means that in order to verify that a
pointer tag matches a memory tag, HWASAN must check for two possibilities:
* the pointer tag is equal to the memory tag in shadow memory, or
* the shadow memory tag is actually a short granule size, the value being loaded
is in bounds of the granule and the pointer tag is equal to the last byte of
the granule.
Pointer tags between 1 to `TG-1` are possible and are as likely as any other
tag. This means that these tags in memory have two interpretations: the full
tag interpretation (where the pointer tag is between 1 and `TG-1` and the
last byte of the granule is ordinary data) and the short tag interpretation
(where the pointer tag is stored in the granule).
When HWASAN detects an error near a memory tag between 1 and `TG-1`, it
will show both the memory tag and the last byte of the granule. Currently,
it is up to the user to disambiguate the two possibilities.
Because this functionality obsoletes the right aligned heap feature of
the HWASAN memory allocator (and because we can no longer easily test
it), the feature is removed.
Also update the documentation to cover both short granule tags and
outlined checks.
Differential Revision: https://reviews.llvm.org/D63908
llvm-svn: 365551