Previous a mallocation was marked as 'reachable' when any other
mallocation or memory region had a pointer to that mallocation. However
there could be the situation that two mallocations have pointers to each
other while still being unreachable from anywhere else. They would be
marked as 'reachable' regardless.
This patch replaces the old way of detemining whether a mallocation is
reachable by analyzing the dependencies of the different mallocations
using a graph-approach. Now mallocations are only reachable if pointed
to by other reachable mallocations or other memory regions.
A nice bonus is that this gets rid of a nested for_each_mallocation, so
the complexity of leak finding becomes linear instead of quadratic.
According to the Single UNIX Specification, Version 2 that's where
those macros should be defined. This fixes the libiconv port.
This also fixes some (but not all) build errors for the diffutils and nano ports.
Otherwise it'll have some random value from the stack, and the kernel
will not bother setting it to zero.
Also add a debug print and tweak the FIXME message.
Old behavior: Crash due to VERIFY, unless we're completely and entirely out of
memory (m_available_ranges being empty), in which case it would return -ENOMEM.
New behavior: Return ENOMEM (and don't crash). In the case of nullptr,
also emit a helpful diagnostic.
Note that MAP_FIXED with nullptr is technically okay, but tends to be a sign
that something went wrong.
Also, this should improve mmap performance marginally, as it pulls the check out
of a loop that does not modify any parts of the check.
UE is now self-hosting! Fixes#5709.
However, this still needs some love: "ue UserspaceEmulator true" spits out tons
of error messages, probably false-positives, and takes about 229 seconds to run.
Then again, true-in-ue-in-ue-in-Qemu is three levels of emulation, so no wonder
it takes a long time! :D
Since there is usually no correlation between guest memory-layout and UE memory-layout,
this option does not make any sense. Especially since we provide nullptr.
The auditing code always starts by checking if we're in one of the
ignored code ranges (malloc, free, realloc, syscall, etc.)
To reduce the number of checks needed, we can cache the bounds of
the LibC text segment. This allows us to fast-reject addresses that
cannot possibly be a LibC function.
Accesses in the header (or trailing padding) of a malloc block should
not be associated with any mallocation since only the chunk-sized slots
actually get returned by malloc.
Basically, allow address-to-chunk lookup to fail, and handle such
failures gracefully at call sites.
Fixes#5706.
We don't want to audit accesses into the region *while* we're setting
up malloc tracking for it. Fetching the chunk size from the header
was tripping up the auditing code.
This returns ENOSYS if you are running in the real kernel, and some
other result if you are running in UserspaceEmulator.
There are other ways we could check if we're inside an emulator, but
it seemed easier to just ask. :^)
This is basically just for consistency, it's quite strange to see
multiple AK container types next to each other, some with and some
without the namespace prefix - we're 'using AK::Foo;' a lot and should
leverage that. :^)
(...and ASSERT_NOT_REACHED => VERIFY_NOT_REACHED)
Since all of these checks are done in release builds as well,
let's rename them to VERIFY to prevent confusion, as everyone is
used to assertions being compiled out in release.
We can introduce a new ASSERT macro that is specifically for debug
checks, but I'm doing this wholesale conversion first since we've
accumulated thousands of these already, and it's not immediately
obvious which ones are suitable for ASSERT.