Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions compiler-rt/lib/fuzzer/FuzzerDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,11 @@ static int RunInMultipleProcesses(const std::vector<std::string> &Args,
return HasErrors ? 1 : 0;
}

static void StartRssThread(Fuzzer *F, size_t RssLimitMb);

// Fuchsia needs to do some book checking before starting the RssThread,
// so it has its own implementation.
#if !LIBFUZZER_FUCHSIA
static void RssThread(Fuzzer *F, size_t RssLimitMb) {
while (true) {
SleepSeconds(1);
Expand All @@ -321,6 +326,7 @@ static void StartRssThread(Fuzzer *F, size_t RssLimitMb) {
std::thread T(RssThread, F, RssLimitMb);
T.detach();
}
#endif

int RunOneTest(Fuzzer *F, const char *InputFilePath, size_t MaxLen) {
Unit U = FileToVector(InputFilePath);
Expand Down
60 changes: 57 additions & 3 deletions compiler-rt/lib/fuzzer/FuzzerUtilFuchsia.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ void ExitOnErr(zx_status_t Status, const char *Syscall) {
}

void AlarmHandler(int Seconds) {
// Signal the alarm thread started.
ExitOnErr(_zx_object_signal(SignalHandlerEvent, 0, ZX_USER_SIGNAL_0),
"_zx_object_signal alarm");
while (true) {
SleepSeconds(Seconds);
Fuzzer::StaticAlarmCallback();
Expand Down Expand Up @@ -282,6 +285,7 @@ void CrashHandler() {
Self, ZX_EXCEPTION_CHANNEL_DEBUGGER, &Channel.Handle),
"_zx_task_create_exception_channel");

// Signal the crash thread started.
ExitOnErr(_zx_object_signal(SignalHandlerEvent, 0, ZX_USER_SIGNAL_0),
"_zx_object_signal");

Expand Down Expand Up @@ -385,10 +389,49 @@ void StopSignalHandler() {
_zx_handle_close(SignalHandlerEvent);
}

void RssThread(Fuzzer *F, size_t RssLimitMb) {
// Signal the rss thread started.
//
// We must wait for this thread to start because we could accidentally suspend
// it while the crash handler is attempting to handle the
// ZX_EXCP_THREAD_STARTING exception. If the crash handler is suspended by the
// lsan machinery, then there's no way for this thread to indicate it's
// suspended because it's blocked on waiting for the exception to be handled.
ExitOnErr(_zx_object_signal(SignalHandlerEvent, 0, ZX_USER_SIGNAL_0),
"_zx_object_signal rss");
while (true) {
SleepSeconds(1);
size_t Peak = GetPeakRSSMb();
if (Peak > RssLimitMb)
F->RssLimitCallback();
}
}

} // namespace

void StartRssThread(Fuzzer *F, size_t RssLimitMb) {
// Set up the crash handler and wait until it is ready before proceeding.
assert(SignalHandlerEvent == ZX_HANDLE_INVALID);
ExitOnErr(_zx_event_create(0, &SignalHandlerEvent), "_zx_event_create");

if (!RssLimitMb)
return;
std::thread T(RssThread, F, RssLimitMb);
T.detach();

// Wait for the rss thread to start.
ExitOnErr(_zx_object_wait_one(SignalHandlerEvent, ZX_USER_SIGNAL_0,
ZX_TIME_INFINITE, nullptr),
"_zx_object_wait_one rss");
ExitOnErr(_zx_object_signal(SignalHandlerEvent, ZX_USER_SIGNAL_0, 0),
"_zx_object_signal rss clear");
}

// Platform specific functions.
void SetSignalHandler(const FuzzingOptions &Options) {
assert(SignalHandlerEvent != ZX_HANDLE_INVALID &&
"This should've been setup by StartRssThread.");

// Make sure information from libFuzzer and the sanitizers are easy to
// reassemble. `__sanitizer_log_write` has the added benefit of ensuring the
// DSO map is always available for the symbolizer.
Expand All @@ -404,6 +447,20 @@ void SetSignalHandler(const FuzzingOptions &Options) {
if (Options.HandleAlrm && Options.UnitTimeoutSec > 0) {
std::thread T(AlarmHandler, Options.UnitTimeoutSec / 2 + 1);
T.detach();

// Wait for the alarm thread to start.
//
// We must wait for this thread to start because we could accidentally
// suspend it while the crash handler is attempting to handle the
// ZX_EXCP_THREAD_STARTING exception. If the crash handler is suspended by
// the lsan machinery, then there's no way for this thread to indicate it's
// suspended because it's blocked on waiting for the exception to be
// handled.
ExitOnErr(_zx_object_wait_one(SignalHandlerEvent, ZX_USER_SIGNAL_0,
ZX_TIME_INFINITE, nullptr),
"_zx_object_wait_one alarm");
ExitOnErr(_zx_object_signal(SignalHandlerEvent, ZX_USER_SIGNAL_0, 0),
"_zx_object_signal alarm clear");
}

// Options.HandleInt and Options.HandleTerm are not supported on Fuchsia
Expand All @@ -413,9 +470,6 @@ void SetSignalHandler(const FuzzingOptions &Options) {
!Options.HandleFpe && !Options.HandleAbrt && !Options.HandleTrap)
return;

// Set up the crash handler and wait until it is ready before proceeding.
ExitOnErr(_zx_event_create(0, &SignalHandlerEvent), "_zx_event_create");

SignalHandler = std::thread(CrashHandler);
zx_status_t Status = _zx_object_wait_one(SignalHandlerEvent, ZX_USER_SIGNAL_0,
ZX_TIME_INFINITE, nullptr);
Expand Down
Loading