Skip to content

Commit 607292c

Browse files
committed
[compiler-rt] Change GetMaxUserVirtualAddress to invoke syscall
LSan was recently refactored to call GetMaxUserVirtualAddress for diagnostic purposes. This leads to failures for some of our downstream tests which only run with lsan. This occurs because GetMaxUserVirtualAddress depends on setting up shadow via a call to __sanitizer_shadow_bounds, but shadow bounds aren't set for standalone lsan because it doesn't use shadow. This updates the function to invoke the same syscall used by __sanitizer_shadow_bounds calls for getting the memory limit. Ideally this function would only be called once since we only need to get the bounds once. More context in https://fxbug.dev/437346226.
1 parent 04a44fe commit 607292c

File tree

2 files changed

+33
-6
lines changed

2 files changed

+33
-6
lines changed

compiler-rt/lib/asan/asan_fuchsia.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@ void EarlySanitizerInit() {}
3232

3333
namespace __asan {
3434

35-
// The system already set up the shadow memory for us.
36-
// __sanitizer::GetMaxUserVirtualAddress has already been called by
37-
// AsanInitInternal->InitializeHighMemEnd (asan_rtl.cpp).
38-
// Just do some additional sanity checks here.
3935
void InitializeShadowMemory() {
36+
// Explicitly setup shadow here right beforer any of the ShadowBounds members
37+
// are used.
38+
InitShadowBounds();
39+
4040
if (Verbosity())
4141
PrintAddressSpaceLayout();
4242

compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "sanitizer_fuchsia.h"
1515
#if SANITIZER_FUCHSIA
1616

17+
# include <limits.h>
1718
# include <pthread.h>
1819
# include <stdlib.h>
1920
# include <unistd.h>
@@ -117,11 +118,37 @@ uptr GetMmapGranularity() { return _zx_system_get_page_size(); }
117118

118119
sanitizer_shadow_bounds_t ShadowBounds;
119120

121+
// Any sanitizer that utilizes shadow should explicitly call whenever it's
122+
// appropriate for that sanitizer to reference shadow bounds. For ASan, this is
123+
// done in `InitializeShadowMemory` and for HWASan, this is done in
124+
// `InitShadow`.
120125
void InitShadowBounds() { ShadowBounds = __sanitizer_shadow_bounds(); }
121126

127+
// TODO(leonardchan): It's not immediately clear from a user perspective if
128+
// `GetMaxUserVirtualAddress` should be called exatly once on runtime startup
129+
// or can be called multiple times. Currently it looks like most instances of
130+
// `GetMaxUserVirtualAddress` are meant to be called once, but if someone
131+
// decides to call this multiple times in the future, we should have a separate
132+
// function that's ok to call multiple times. Ideally we would just invoke this
133+
// syscall once. Also for Fuchsia, this syscall technically gets invoked twice
134+
// since `__sanitizer_shadow_bounds` also invokes this syscall under the hood.
122135
uptr GetMaxUserVirtualAddress() {
123-
InitShadowBounds();
124-
return ShadowBounds.memory_limit - 1;
136+
zx_info_vmar_t info;
137+
zx_status_t status = _zx_object_get_info(_zx_vmar_root_self(), ZX_INFO_VMAR,
138+
&info, sizeof(info), NULL, NULL);
139+
CHECK_EQ(status, ZX_OK);
140+
141+
// Find the top of the accessible address space.
142+
uintptr_t top = info.base + info.len;
143+
144+
// Round it up to a power-of-two size. There may be some pages at
145+
// the top that can't actually be mapped, but for purposes of the
146+
// the shadow, we'll pretend they could be.
147+
int bit = (sizeof(uintptr_t) * CHAR_BIT) - __builtin_clzl(top);
148+
if (top != (uintptr_t)1 << bit)
149+
top = (uintptr_t)1 << (bit + 1);
150+
151+
return top - 1;
125152
}
126153

127154
uptr GetMaxVirtualAddress() { return GetMaxUserVirtualAddress(); }

0 commit comments

Comments
 (0)