Historically, alignment and size weren't taken into account when freeing
allocations since `free` just takes a pointer. With `free_sized` and
`free_aligned_sized`, we can do these size and alignment checks in asan
now. This adds a new report type specifically for these functions.
Checking is hidden behind a new env flag `free_size_mismatch` which is
enabled by default, but downstream users can opt out of it.
The bulk of this PR was generated by gemini but thoroughly reviewed and
edited by me to the best of my ability.
This is a follow up to #155943
On Windows, ASan's allocator internally upgrades zero-size allocation
requests to size 1 (since malloc(0) must return a unique non-NULL
pointer). However, when the user queries the allocation size through
Windows heap APIs (RtlSizeHeap, HeapSize, \_msize, GlobalSize,
LocalSize), ASan reports the internal size (1) instead of the originally
requested size (0).
This causes false positive heap-buffer-overflow errors in a common
pattern:
```c++
void *buf = HeapAlloc(GetProcessHeap(), 0, 0);
SIZE_T size = HeapSize(GetProcessHeap(), 0, buf); // Returns 1, should be 0
if(size > 0) // could remove this and still be correct
memset(buf, 0, size); // ASan reports heap-buffer-overflow
```
The change adds a `from_zero_alloc` bit to `ChunkHeader` that tracks
whether an allocation was originally zero-size. This bit fits in the
existing spare capacity of the header's bitfield byte, so the 16-byte
ChunkHeader size is unchanged, but it also isn't the most elegant.
The 1-byte user region of a zero-size allocation is still poisoned, so
any actual access to it is correctly reported as an overflow.
On AIX, when both the `__VEC__` and `_ALL_SOURCE` macros are defined
(they are defined by default), the malloc and calloc system calls are
mapped to vec_malloc and vec_calloc respectively, so we need the
following vec_malloc and vec_calloc interceptors.
Issue: #138916
When a zero-byte allocation is requested, ASan actually allocates 1-byte
for compatibility. This change poisons that byte, to detect
dereferences.
Also updates the test from #155933
Do some refactoring to allocation/deallocation interceptors. Expose
explicit per-alloc_type functions and stop accepting explicit AllocType.
This ensures we do not accidentally mix.
NOTE: This change rejects attempts to call `operator new(<some_size>,
static_cast<std::align_val_t>(0))`.
For https://github.com/llvm/llvm-project/issues/144435
Signed-off-by: Justin King <jcking@google.com>
**Related to:** https://github.com/llvm/llvm-project/issues/117925
**Follow up to:** https://github.com/llvm/llvm-project/pull/117929
**Context:**
As noted in the linked issue, some ASan configuration flags are not
honored on Windows when set through the `__asan_default_options` user
function. The reason for this is that `__asan_default_options` is not
available by the time `AsanInitInternal` executes, which is responsible
for applying the ASan flags.
To fix this properly, we'll probably need a deep re-design of ASan
initialization so that it is consistent across OS'es.
In the meantime, this PR offers a practical workaround.
**This PR:** refactors part of `AsanInitInternal` so that **idempotent**
flag-applying steps are extracted into a new function `ApplyOptions`.
This function is **also** invoked in the "weak function callback" on
Windows (which gets called when `__asan_default_options` is available)
so that, if any flags were set through the user-function, they are
safely applied _then_.
Today, `ApplyOptions` contains only a subset of flags. My hope is that
`ApplyOptions` will over time, through incremental refactorings
`AsanInitInternal` so that **all** flags are eventually honored.
Other minor changes:
* The introduction of a `ApplyAllocatorOptions` helper method, needed to
implement `ApplyOptions` for allocator options without re-initializing
the entire allocator. Reinitializing the entire allocator is expensive,
as it may do a whole pass over all the marked memory. To my knowledge,
this isn't needed for the options captured in `ApplyAllocatorOptions`.
* Rename `ProcessFlags` to `ValidateFlags`, which seems like a more
accurate name to what that function does, and prevents confusion when
compared to the new `ApplyOptions` function.
The nullness check is unreachable.
* For the main thead and pthread_create created threads, the `*Allocate` functions must be called after `*_current_thread` is set.
set.
* For threads created by Linux's `clone`, static TLS is either reused or
set to a new value (CLONE_SETTLS).
Make this change for asan/msan and possibly extend the change to other
sanitizers. (asan supports many platforms and I am not 100% certain that
all platforms have the property.)
Pull Request: https://github.com/llvm/llvm-project/pull/102828
This change adds a new weak API function which makes the sanitizer
ignore the call to free(), and implements the
functionality in ASan and HWAsan. The runtime that implements this hook
can then call free() at a later point again on the same pointer (and
making sure the hook returns zero so that the memory will actually be
freed) when it's actually ready for the memory to be cleaned up.
This is needed in order to implement an sanitizer-compatible version
of Chrome's BackupRefPtr algorithm, since process-wide double-shimming
of malloc/free does not work on some platforms.
Requested and designed by @c01db33f (Mark) from Project Zero.
---------
Co-authored-by: Mark Brand <markbrand@google.com>
Sanitizers allocate shadow and memory as MAP_NORESERVE.
User memory can stay this way and do not increase RSS as long as we
don't store there.
The shadow unpoisoning also can avoid RSS increase for zeroed pages.
However as soon we poison the shadow, we need the page in RSS.
To avoid unnececary RSS increase we should not poison memory just before
unpoisoning them.
Depends on D153497.
Reviewed By: thurston
Differential Revision: https://reviews.llvm.org/D153500
For the secondary allocation we don't need poison and fill memory if we
skip quarantine, and we don't need to poison after quarantine. In both
cases the secondary allocator will unmap memory and unpoison the shadow
from get_allocator().Deallocate().
Depends on D153496.
Reviewed By: thurston
Differential Revision: https://reviews.llvm.org/D153497
The primary motivation for this change is to allow FreeHooks to obtain
the allocated size of the pointer being freed in a fast, efficient manner.
Differential Revision: https://reviews.llvm.org/D151360
D147005 introduced __sanitizer_get_allocated_begin, with a return
value of void*. This involved a few naughty casts that dropped the
const. This patch adds back the const qualifier.
Differential Revision: https://reviews.llvm.org/D147489
For HWASAN this would be the tagged address. It is the same pointer when pointer tagging is not used. Coincidently this also fixes some test which rely on comparing pointers.
Reviewed By: vitalybuka
Differential Revision: https://reviews.llvm.org/D143121
Main goal is to remove thread registry dependency from the interface because HWASAN is using its own code to manage threads.
Reviewed By: vitalybuka, kstoimenov
Differential Revision: https://reviews.llvm.org/D140039
Breaks bots.
Also it's missing changes we discussed on review.
This reverts commit f001e50f955c3cdf2deb79e38a9fd19c9a781882.
This reverts commit 2924189233fdb724453ead4b94595107b1ce9cfa.
Main goal is to remove thread registry dependency from the interface because HWASAN is using its own code to manage threads.
Reviewed By: vitalybuka, kstoimenov
Differential Revision: https://reviews.llvm.org/D140039
Currently we use very common names for macros like ACQUIRE/RELEASE,
which cause conflicts with system headers.
Prefix all macros with SANITIZER_ to avoid conflicts.
Reviewed By: vitalybuka
Differential Revision: https://reviews.llvm.org/D116652
According comments on D44404, something like that was the goal.
Reviewed By: morehouse, kstoimenov
Differential Revision: https://reviews.llvm.org/D114991
Enable clang Thread Safety Analysis for sanitizers:
https://clang.llvm.org/docs/ThreadSafetyAnalysis.html
Thread Safety Analysis can detect inconsistent locking,
deadlocks and data races. Without GUARDED_BY annotations
it has limited value. But this does all the heavy lifting
to enable analysis and allows to add GUARDED_BY incrementally.
Reviewed By: melver
Differential Revision: https://reviews.llvm.org/D105716
Currently we have a bit of a mess related to tids:
- sanitizers re-declare kInvalidTid multiple times
- some call it kUnknownTid
- implicit assumptions that main tid is 0
- asan/memprof claim their tids need to fit into 24 bits,
but this does not seem to be true anymore
- inconsistent use of u32/int to store tids
Introduce kInvalidTid/kMainTid in sanitizer_common
and use them consistently.
Reviewed By: vitalybuka
Differential Revision: https://reviews.llvm.org/D101428
Previously in ASan's `pthread_create` interceptor we would block in the
`pthread_create` interceptor waiting for the child thread to start.
Unfortunately this has bad performance characteristics because the OS
scheduler doesn't know the relationship between the parent and child
thread (i.e. the parent thread cannot make progress until the child
thread makes progress) and may make the wrong scheduling decision which
stalls progress.
It turns out that ASan didn't use to block in this interceptor but was
changed to do so to try to address
http://llvm.org/bugs/show_bug.cgi?id=21621/.
In that bug the problem being addressed was a LeakSanitizer false
positive. That bug concerns a heap object being passed
as `arg` to `pthread_create`. If:
* The calling thread loses a live reference to the object (e.g.
`pthread_create` finishes and the thread no longer has a live
reference to the object).
* Leak checking is triggered.
* The child thread has not yet started (once it starts it will have a
live reference).
then the heap object will incorrectly appear to be leaked.
This bug is covered by the `lsan/TestCases/leak_check_before_thread_started.cpp` test case.
In b029c5101fb49b3577a1c322f42ef9fc616f25bf ASan was changed to block
in `pthread_create()` until the child thread starts so that `arg` is
kept alive for the purposes of leaking check.
While this change "works" its problematic due to the performance
problems it causes. The change is also completely unnecessary if leak
checking is disabled (via detect_leaks runtime option or
CAN_SANITIZE_LEAKS compile time config).
This patch does two things:
1. Takes a different approach to solving the leak false positive by
making LSan's leak checking mechanism treat the `arg` pointer of
created but not started threads as reachable. This is done by
implementing the `ForEachRegisteredThreadContextCb` callback for
ASan.
2. Removes the blocking behaviour in the ASan `pthread_create`
interceptor.
rdar://problem/63537240
Differential Revision: https://reviews.llvm.org/D95184
This mechanism is intended to provide a way to treat the `arg` pointer
of a created (but not yet started) thread as reachable. In future
patches this will be implemented in `GetAdditionalThreadContextPtrs`.
A separate implementation of `GetAdditionalThreadContextPtrs` exists
for ASan and LSan runtimes because they need to be implemented
differently in future patches.
rdar://problem/63537240
Differential Revision: https://reviews.llvm.org/D95183
Additional investigated confirmed that issue is not about
AddrIsInside, but missing registers.
This reverts commit 9d01612db48fa27d18c6320974b8d711572e5c67.
kAllocBegMagic should be enough.
kAllocBegMagic is already set for the Secondary allocations.
kAllocBegMagic is good enough for the Primary, but it's even safer for
the Secondary allocator as all allocated block are from mmap.
Depends on D87646.
Reviewed By: morehouse
Differential Revision: https://reviews.llvm.org/D87647