// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/sys/fuzzing/realmfuzzer/target/process.h"

#include <lib/backtrace-request/backtrace-request.h>
#include <lib/syslog/cpp/macros.h>
#include <stddef.h>
#include <stdlib.h>
#include <zircon/status.h>

#include <iomanip>
#include <iostream>

#include "src/sys/fuzzing/common/module.h"
#include "src/sys/fuzzing/common/options.h"
#include "src/sys/fuzzing/realmfuzzer/target/weak-symbols.h"

namespace fuzzing {
namespace {

using fuchsia::fuzzer::InstrumentedProcess;

// Maximum number of LLVM modules per process. This limit matches libFuzzer.
constexpr size_t kMaxModules = 4096;

// Memory profile parameters; see compiler-rt/lib/asan/asan_memory_profile.cpp.
constexpr size_t kTopPercentChunks = 95;
constexpr size_t kMaxUniqueContexts = 8;

// Static context; used to store module info until the process singleton is created and to find the
// singleton from the static hook functions. This structure is NOT thread-safe, and should only be
// accessed from the main thread. More precisely, do not load multiple shared libraries concurrently
// from different threads.
struct {
  CountersInfo counters[kMaxModules];
  size_t num_counters = 0;
  PCsInfo pcs[kMaxModules];
  size_t num_pcs = 0;
  Process* process = nullptr;
} gContext;

// Hook functions that simply forward to the singleton.
void MallocHook(const volatile void* ptr, size_t size) { gContext.process->OnMalloc(ptr, size); }

void FreeHook(const volatile void* ptr) { gContext.process->OnFree(ptr); }

void DeathHook() { gContext.process->OnDeath(); }

void ExitHook() { gContext.process->OnExit(); }

}  // namespace
}  // namespace fuzzing

extern "C" {

// NOLINTNEXTLINE(readability-non-const-parameter)
void __sanitizer_cov_8bit_counters_init(uint8_t* start, uint8_t* stop) {
  if (start >= stop) {
    return;
  }
  fuzzing::CountersInfo counters;
  counters.data = start;
  counters.len = stop - start;
  // Safe: |gProcess.process| is only modified while the process is single-threaded.
  using fuzzing::gContext;
  if (gContext.process) {
    gContext.process->AddCounters(std::move(counters));
    return;
  }
  // Safe: no threads are created before |gProcess| is constructed.
  if (gContext.num_counters < fuzzing::kMaxModules) {
    gContext.counters[gContext.num_counters++] = std::move(counters);
  }
}

void __sanitizer_cov_pcs_init(const uintptr_t* start, const uintptr_t* stop) {
  if (start >= stop) {
    return;
  }
  fuzzing::PCsInfo pcs;
  pcs.data = start;
  pcs.len = stop - start;
  // Safe: |gProcess.process| is only modified while the process is single-threaded.
  using fuzzing::gContext;
  if (gContext.process) {
    gContext.process->AddPCs(std::move(pcs));
    return;
  }
  // Safe: no threads are created before |gProcess| is constructed.
  if (gContext.num_pcs < fuzzing::kMaxModules) {
    gContext.pcs[gContext.num_pcs++] = std::move(pcs);
  }
}

// TODO(fxbug.dev/85308): Add value-profile support.
void __sanitizer_cov_trace_pc_indir(uintptr_t Callee) {}
void __sanitizer_cov_trace_const_cmp1(uint8_t Arg1, uint8_t Arg2) {}
void __sanitizer_cov_trace_const_cmp2(uint16_t Arg1, uint16_t Arg2) {}
void __sanitizer_cov_trace_const_cmp4(uint32_t Arg1, uint32_t Arg2) {}
void __sanitizer_cov_trace_const_cmp8(uint64_t Arg1, uint64_t Arg2) {}
void __sanitizer_cov_trace_cmp1(uint8_t Arg1, uint8_t Arg2) {}
void __sanitizer_cov_trace_cmp2(uint16_t Arg1, uint16_t Arg2) {}
void __sanitizer_cov_trace_cmp4(uint32_t Arg1, uint32_t Arg2) {}
void __sanitizer_cov_trace_cmp8(uint64_t Arg1, uint64_t Arg2) {}
void __sanitizer_cov_trace_switch(uint64_t Val, uint64_t* Cases) {}
void __sanitizer_cov_trace_div4(uint32_t Val) {}
void __sanitizer_cov_trace_div8(uint64_t Val) {}
void __sanitizer_cov_trace_gep(uintptr_t Idx) {}

}  // extern "C"

namespace fuzzing {

Process::Process(ExecutorPtr executor)
    : executor_(executor), eventpair_(executor), next_purge_(zx::time::infinite()) {
  FX_CHECK(!gContext.process);
  // The AsyncDeques must be created on the dispatcher thread.
  auto task = fpromise::make_promise([this]() -> Result<> {
                counters_ = AsyncDeque<CountersInfo>::MakePtr();
                pcs_ = AsyncDeque<PCsInfo>::MakePtr();
                return fpromise::ok();
              })
                  .wrap_with(scope_)
                  .wrap_with(sequencer_);
  executor_->schedule_task(std::move(task));
  // Forward coverage for modules added up to this point.
  FX_CHECK(gContext.num_counters == gContext.num_pcs);
  for (size_t i = 0; i < gContext.num_counters; ++i) {
    AddCounters(std::move(gContext.counters[i]));
    AddPCs(std::move(gContext.pcs[i]));
  }
  AddDefaults(&options_);
  gContext.process = this;
}

Process::~Process() { memset(&gContext, 0, sizeof(gContext)); }

void Process::AddDefaults(Options* options) {
  if (!options->has_detect_leaks()) {
    options->set_detect_leaks(kDefaultDetectLeaks);
  }
  if (!options->has_malloc_limit()) {
    options->set_malloc_limit(kDefaultMallocLimit);
  }
  if (!options->has_oom_limit()) {
    options->set_oom_limit(kDefaultOomLimit);
  }
  if (!options->has_purge_interval()) {
    options->set_purge_interval(kDefaultPurgeInterval);
  }
  if (!options->has_malloc_exitcode()) {
    options->set_malloc_exitcode(kDefaultMallocExitcode);
  }
  if (!options->has_death_exitcode()) {
    options->set_death_exitcode(kDefaultDeathExitcode);
  }
  if (!options->has_leak_exitcode()) {
    options->set_leak_exitcode(kDefaultLeakExitcode);
  }
  if (!options->has_oom_exitcode()) {
    options->set_oom_exitcode(kDefaultOomExitcode);
  }
}

void Process::AddCounters(CountersInfo counters) {
  // Ensure the AsyncDeque is only accessed from the dispatcher thread.
  auto task =
      fpromise::make_promise([this, counters = std::move(counters)]() mutable -> ZxResult<> {
        if (auto status = counters_->Send(std::move(counters)); status != ZX_OK) {
          FX_LOGS(WARNING) << "Failed to send counters to engine: " << zx_status_get_string(status);
          return fpromise::error(status);
        }
        return fpromise::ok();
      })
          .wrap_with(scope_)
          .wrap_with(sequencer_);
  executor_->schedule_task(std::move(task));
}

void Process::AddPCs(PCsInfo pcs) {
  // Ensure the AsyncDeque is only accessed from the dispatcher thread.
  auto task = fpromise::make_promise([this, pcs = std::move(pcs)]() mutable -> ZxResult<> {
                if (auto status = pcs_->Send(std::move(pcs)); status != ZX_OK) {
                  FX_LOGS(WARNING)
                      << "Failed to send PCs to engine: " << zx_status_get_string(status);
                  return fpromise::error(status);
                }
                return fpromise::ok();
              })
                  .wrap_with(scope_)
                  .wrap_with(sequencer_);
  executor_->schedule_task(std::move(task));
}

void Process::OnMalloc(const volatile void* ptr, size_t size) {
  ++num_mallocs_;
  if (size > malloc_limit_ && AcquireCrashState()) {
    backtrace_request();
    _Exit(options_.malloc_exitcode());
  }
}

void Process::OnFree(const volatile void* ptr) { ++num_frees_; }

void Process::OnDeath() { _Exit(options_.death_exitcode()); }

void Process::OnExit() {
  // Exits may not be fatal, e.g. if detect_exits=false. Make sure the process publishes all its
  // coverage before it ends as the engine will keep fuzzing.
  for (auto& module : modules_) {
    module.Update();
  }
}

void Process::InstallHooks() {
  // This method can only be called once.
  static bool first = true;
  FX_CHECK(first) << "InstallHooks called more than once!";
  first = false;

  // Warn about missing symbols.
  if (!__sanitizer_acquire_crash_state) {
    FX_LOGS(WARNING) << "Missing '__sanitizer_acquire_crash_state'.";
  }
  if (!__sanitizer_set_death_callback) {
    FX_LOGS(WARNING) << "Missing '__sanitizer_set_death_callback'.";
  }

  // Install hooks.
  if (__sanitizer_set_death_callback) {
    __sanitizer_set_death_callback(DeathHook);
  }
  if (__sanitizer_install_malloc_and_free_hooks) {
    __sanitizer_install_malloc_and_free_hooks(MallocHook, FreeHook);
  }
  std::atexit([]() { ExitHook(); });
}

ZxPromise<> Process::Connect(fidl::InterfaceHandle<CoverageDataCollector> collector,
                             zx::eventpair eventpair) {
  Bridge<Options> bridge;
  return fpromise::make_promise([this, collector = std::move(collector)]() mutable -> ZxResult<> {
           // Connect the `fuchsia.fuzzer.CoverageDataCollector`.
           if (auto status = collector_.Bind(collector.TakeChannel()); status != ZX_OK) {
             FX_LOGS(WARNING) << "Failed to bind `fuchsia.fuzzer.CoverageDataCollector`: "
                              << zx_status_get_string(status);
             return fpromise::error(status);
           }
           return fpromise::ok();
         })
      .and_then([]() -> ZxResult<zx::process> {
        // Duplicate this process.
        auto self = zx::process::self();
        zx::process process;
        if (auto status = self->duplicate(ZX_RIGHT_SAME_RIGHTS, &process); status != ZX_OK) {
          FX_LOGS(WARNING) << "Failed to duplicate process handle: "
                           << zx_status_get_string(status);
          return fpromise::error(status);
        }
        return fpromise::ok(std::move(process));
      })
      .and_then([this](zx::process& process) -> ZxResult<zx::process> {
        // Next, determine this process's target id, which is just its koid. The process will
        // annotate all modules it shares with this id to allow the engine to clean up the module
        // pool if this process exits.
        zx_info_handle_basic_t info;
        if (auto status =
                process.get_info(ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr);
            status != ZX_OK) {
          FX_LOGS(WARNING) << "Failed to set target id: " << zx_status_get_string(status);
          return fpromise::error(status);
        }
        target_id_ = info.koid;
        return fpromise::ok(std::move(process));
      })
      .and_then([this, completer = std::move(bridge.completer)](
                    zx::process& process) mutable -> ZxResult<> {
        // Now create an |InstrumentedProcess| for this process and send it to the collector.
        InstrumentedProcess instrumented{
            .eventpair = eventpair_.Create(),
            .process = std::move(process),
        };
        collector_->Initialize(std::move(instrumented), completer.bind());
        return fpromise::ok();
      })
      .and_then([this, connect = Future<Options>(bridge.consumer.promise_or(fpromise::error()))](
                    Context& context) mutable -> ZxResult<> {
        // Wait for the collector to respond with options, and use them to configure this process.
        if (!connect(context)) {
          return fpromise::pending();
        }
        if (connect.is_error()) {
          return fpromise::error(ZX_ERR_CANCELED);
        }
        Configure(connect.take_value());
        return fpromise::ok();
      })
      .and_then([this, eventpair = std::move(eventpair), add = ZxFuture<>(),
                 run = ZxFuture<>()](Context& context) mutable -> ZxResult<> {
        // Now execute both the |AddModules| and |Run| futures. These only complete on error, and
        // need to be executed concurrently.
        if (!add) {
          add = AddModules(std::move(eventpair));
        }
        if (!run) {
          run = Run();
        }
        if (add(context)) {
          return add.take_result();
        }
        if (run(context)) {
          return run.take_result();
        }
        return fpromise::pending();
      })
      .wrap_with(scope_);
}

void Process::Configure(Options options) {
  AddDefaults(&options);
  options_ = std::move(options);

  // Configure allocator purging.
  // TODO(fxbug.dev/85284): Add integration tests that produce these and following logs.
  auto purge_interval = options_.purge_interval();
  if (purge_interval && !__sanitizer_purge_allocator) {
    FX_LOGS(WARNING) << "Missing '__sanitizer_purge_allocator'.";
    FX_LOGS(WARNING) << "Allocator purging disabled.";
    purge_interval = 0;
  }
  next_purge_ =
      purge_interval ? zx::deadline_after(zx::duration(purge_interval)) : zx::time::infinite();

  // Check if leak detection is possible.
  if (options_.detect_leaks()) {
    can_detect_leaks_ = false;
    if (!__lsan_enable) {
      FX_LOGS(WARNING) << "Missing '__lsan_enable'.";
    } else if (!__lsan_disable) {
      FX_LOGS(WARNING) << "Missing '__lsan_disable'.";
    } else if (!__lsan_do_recoverable_leak_check) {
      FX_LOGS(WARNING) << "Missing '__lsan_do_recoverable_leak_check'.";
    } else if (!__sanitizer_install_malloc_and_free_hooks) {
      FX_LOGS(WARNING) << "Missing '__sanitizer_install_malloc_and_free_hooks'.";
    } else {
      can_detect_leaks_ = true;
    }
    if (!can_detect_leaks_) {
      FX_LOGS(WARNING) << "Leak detection disabled.";
    }
  }

  // Check if bad malloc detection is possible.
  auto malloc_limit = options_.malloc_limit();
  if (malloc_limit && !__sanitizer_install_malloc_and_free_hooks) {
    FX_LOGS(WARNING) << "Missing '__sanitizer_install_malloc_and_free_hooks'.";
    FX_LOGS(WARNING) << "Large allocation detection disabled.";
  }
  malloc_limit_ = malloc_limit ? malloc_limit : std::numeric_limits<size_t>::max();
}

ZxPromise<> Process::AddModules(zx::eventpair eventpair) {
  return fpromise::make_promise([this, eventpair = std::move(eventpair), num_modules = 0ULL,
                                 add_module =
                                     ZxFuture<>()](Context& context) mutable -> ZxResult<> {
    while (true) {
      // Notify the engine when initial modules have all been sent and acknowledged.
      if (!add_module) {
        if (num_modules == gContext.num_pcs) {
          if (auto status = eventpair.signal_peer(0, kSync); status != ZX_OK) {
            FX_LOGS(WARNING) << "Failed to acknowledge module: " << zx_status_get_string(status);
          }
        }
        add_module = AddModule();
      }
      if (!add_module(context)) {
        return fpromise::pending();
      }
      auto result = add_module.take_result();
      if (result.is_error()) {
        FX_LOGS(ERROR) << "Failed to add module: " << zx_status_get_string(result.error());
      }
      ++num_modules;
    }
  });
}

ZxPromise<> Process::AddModule() {
  Bridge<> bridge;
  return fpromise::make_promise([recv = Future<CountersInfo>(counters_->Receive())](
                                    Context& context) mutable -> ZxResult<CountersInfo> {
           // Get the next |CountersInfo|.
           if (!recv(context)) {
             return fpromise::pending();
           }
           if (recv.is_error()) {
             FX_LOGS(WARNING) << "Missing expected inline 8-bit counters.";
             return fpromise::error(ZX_ERR_BAD_STATE);
           }
           return fpromise::ok(recv.take_value());
         })
      .and_then([recv = Future<PCsInfo>(pcs_->Receive())](
                    Context& context, CountersInfo& counters) mutable -> ZxResult<Module> {
        // Get the next |PCsInfo|.
        if (!recv(context)) {
          return fpromise::pending();
        }
        if (recv.is_error()) {
          FX_LOGS(WARNING) << "Missing expected PC table.";
          return fpromise::error(ZX_ERR_BAD_STATE);
        }
        // Combine into a |Module|.
        auto pcs = recv.take_value();
        if (counters.len != pcs.len * sizeof(uintptr_t) / sizeof(ModulePC)) {
          FX_LOGS(WARNING) << "Length mismatch: counters=" << counters.len << ", pcs=" << pcs.len;
          return fpromise::error(ZX_ERR_BAD_STATE);
        }
        Module module;
        if (auto status = module.Import(counters.data, pcs.data, counters.len); status != ZX_OK) {
          FX_LOGS(WARNING) << "Failed to import module data: " << zx_status_get_string(status);
          return fpromise::error(status);
        }
        module.Clear();
        return fpromise::ok(std::move(module));
      })
      .and_then(
          [this, completer = std::move(bridge.completer)](Module& module) mutable -> ZxResult<> {
            zx::vmo inline_8bit_counters;
            if (auto status = module.Share(target_id_, &inline_8bit_counters); status != ZX_OK) {
              FX_LOGS(WARNING) << "Failed to share inline 8-bit counters: "
                               << zx_status_get_string(status);
              return fpromise::error(status);
            }
            modules_.emplace_back(std::move(module));
            collector_->AddLlvmModule(std::move(inline_8bit_counters), completer.bind());
            return fpromise::ok();
          })
      .and_then([this, wait = Future<>(bridge.consumer.promise_or(fpromise::error()))](
                    Context& context) mutable -> ZxResult<> {
        if (!wait(context)) {
          return fpromise::pending();
        }
        if (wait.is_error()) {
          return fpromise::error(ZX_ERR_CANCELED);
        }
        if (awaiting_ && modules_.size() >= gContext.num_pcs) {
          awaiting_.resume_task();
        }
        return fpromise::ok();
      });
}

ZxPromise<> Process::Run() {
  // Processes typically connect during a fuzzing run, but may connect between runs as well. As a
  // result, the first wait is for any run-related signal.
  auto expected = kStart | kStartLeakCheck | kFinish;
  return fpromise::make_promise([this, expected, wait = ZxFuture<zx_signals_t>()](
                                    Context& context) mutable -> ZxResult<> {
           while (true) {
             if (!wait) {
               wait = eventpair_.WaitFor(expected);
             }
             if (!wait(context)) {
               return fpromise::pending();
             }
             if (wait.is_error()) {
               return fpromise::error(wait.error());
             }
             auto observed = wait.take_value();
             if (auto status = eventpair_.SignalSelf(observed, 0); status != ZX_OK) {
               return fpromise::error(status);
             }
             zx_signals_t reply = 0;
             switch (observed) {
               case kStartLeakCheck:
                 ConfigureLeakDetection();
                 [[fallthrough]];
               case kStart:
                 // Reset coverage data and leak detection.
                 for (auto& module : modules_) {
                   module.Clear();
                 }
                 num_mallocs_ = 0;
                 num_frees_ = 0;
                 reply = kStart;
                 expected = kFinish;
                 break;
               case kFinish:
                 // Forward coverage data to engine, and respond with leak status.
                 for (auto& module : modules_) {
                   module.Update();
                 }
                 reply = DetectLeak() ? kFinishWithLeaks : kFinish;
                 expected = kStart | kStartLeakCheck;
                 break;
               default:
                 FX_NOTREACHED();
                 break;
             }
             if (auto status = eventpair_.SignalPeer(0, reply); status != ZX_OK) {
               return fpromise::error(status);
             }
           }
         })
      .or_else([](const zx_status_t& status) -> ZxResult<> {
        if (status != ZX_ERR_PEER_CLOSED) {
          FX_LOGS(WARNING) << "Failed to exchange signals with engine: "
                           << zx_status_get_string(status);
          return fpromise::error(status);
        }
        return fpromise::ok();
      });
}

void Process::ConfigureLeakDetection() {
  if (can_detect_leaks_ && !detecting_leaks_) {
    detecting_leaks_ = true;
    __lsan_disable();
  }
}

bool Process::DetectLeak() {
  // As described in the header, full leak detection is expensive. Realmfuzzer imitates libfuzzer
  // and performs a two-pass process:
  //   1a. Upon starting a fuzzing iteration,i.e. |OnSignal(kStart)|, it tracks |num_mallocs| and
  //       |num_frees|.
  //   1b. Upon finishing an iteration, i.e. |OnSignal(kFinish)|, it checks if |num_mallocs| equals
  //       |num_frees| and returns |kFinish| or |kFinishWithLeaks|, as appropriate.
  //   2a. Returning |kFinishWithLeaks| will cause the engine to repeat the input with leak
  //       detection, i.e. |OnSignal(kStartLeakCheck)|. It will disable LSan for this run to avoid
  //       eventually reporting the same error twice.
  //   2b. Upon finishing the second iteration, i.e. |OnSignal(kFinish)| again, it re-enables LSan.
  //       If |num_mallocs| still does not match |num_frees|, it performs the (expensive) leak
  //       check. If a true leak, it will report it using info from the first iteration and exit.
  bool has_leak = num_mallocs_.exchange(0) != num_frees_.exchange(0);
  if (detecting_leaks_) {
    __lsan_enable();
    detecting_leaks_ = false;
    if (has_leak && __lsan_do_recoverable_leak_check() && AcquireCrashState()) {
      if (__sanitizer_print_memory_profile) {
        __sanitizer_print_memory_profile(kTopPercentChunks, kMaxUniqueContexts);
      }
      _Exit(options_.leak_exitcode());
    }
  }
  // TODO(fxbug.dev/84368): The check for OOM is missing!
  if (next_purge_ < zx::clock::get_monotonic()) {
    __sanitizer_purge_allocator();
    next_purge_ = zx::deadline_after(zx::duration(options_.purge_interval()));
  }
  return has_leak;
}

bool Process::AcquireCrashState() {
  return __sanitizer_acquire_crash_state && __sanitizer_acquire_crash_state();
}

}  // namespace fuzzing
