FuzzerUtilPosix.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. //===- FuzzerUtilPosix.cpp - Misc utils for Posix. ------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. // Misc utils implementation using Posix API.
  9. //===----------------------------------------------------------------------===//
  10. #include "FuzzerPlatform.h"
  11. #if LIBFUZZER_POSIX
  12. #include "FuzzerIO.h"
  13. #include "FuzzerInternal.h"
  14. #include "FuzzerTracePC.h"
  15. #include <cassert>
  16. #include <chrono>
  17. #include <cstring>
  18. #include <errno.h>
  19. #include <iomanip>
  20. #include <signal.h>
  21. #include <stdio.h>
  22. #include <sys/mman.h>
  23. #include <sys/resource.h>
  24. #include <sys/syscall.h>
  25. #include <sys/time.h>
  26. #include <sys/types.h>
  27. #include <thread>
  28. #include <unistd.h>
  29. namespace fuzzer {
  30. static void AlarmHandler(int, siginfo_t *, void *) {
  31. Fuzzer::StaticAlarmCallback();
  32. }
  33. static void (*upstream_segv_handler)(int, siginfo_t *, void *);
  34. static void SegvHandler(int sig, siginfo_t *si, void *ucontext) {
  35. assert(si->si_signo == SIGSEGV);
  36. if (upstream_segv_handler)
  37. return upstream_segv_handler(sig, si, ucontext);
  38. Fuzzer::StaticCrashSignalCallback();
  39. }
  40. static void CrashHandler(int, siginfo_t *, void *) {
  41. Fuzzer::StaticCrashSignalCallback();
  42. }
  43. static void InterruptHandler(int, siginfo_t *, void *) {
  44. Fuzzer::StaticInterruptCallback();
  45. }
  46. static void GracefulExitHandler(int, siginfo_t *, void *) {
  47. Fuzzer::StaticGracefulExitCallback();
  48. }
  49. static void FileSizeExceedHandler(int, siginfo_t *, void *) {
  50. Fuzzer::StaticFileSizeExceedCallback();
  51. }
  52. static void SetSigaction(int signum,
  53. void (*callback)(int, siginfo_t *, void *)) {
  54. struct sigaction sigact = {};
  55. if (sigaction(signum, nullptr, &sigact)) {
  56. Printf("libFuzzer: sigaction failed with %d\n", errno);
  57. exit(1);
  58. }
  59. if (sigact.sa_flags & SA_SIGINFO) {
  60. if (sigact.sa_sigaction) {
  61. if (signum != SIGSEGV)
  62. return;
  63. upstream_segv_handler = sigact.sa_sigaction;
  64. }
  65. } else {
  66. if (sigact.sa_handler != SIG_DFL && sigact.sa_handler != SIG_IGN &&
  67. sigact.sa_handler != SIG_ERR)
  68. return;
  69. }
  70. struct sigaction new_sigact = {};
  71. // Address sanitizer needs SA_ONSTACK (causing the signal handler to run on a
  72. // dedicated stack) in order to be able to detect stack overflows; keep the
  73. // flag if it's set.
  74. new_sigact.sa_flags = SA_SIGINFO | (sigact.sa_flags & SA_ONSTACK);
  75. new_sigact.sa_sigaction = callback;
  76. if (sigaction(signum, &new_sigact, nullptr)) {
  77. Printf("libFuzzer: sigaction failed with %d\n", errno);
  78. exit(1);
  79. }
  80. }
  81. // Return true on success, false otherwise.
  82. bool ExecuteCommand(const Command &Cmd, std::string *CmdOutput) {
  83. FILE *Pipe = popen(Cmd.toString().c_str(), "r");
  84. if (!Pipe)
  85. return false;
  86. if (CmdOutput) {
  87. char TmpBuffer[128];
  88. while (fgets(TmpBuffer, sizeof(TmpBuffer), Pipe))
  89. CmdOutput->append(TmpBuffer);
  90. }
  91. return pclose(Pipe) == 0;
  92. }
  93. void SetTimer(int Seconds) {
  94. struct itimerval T {
  95. {Seconds, 0}, { Seconds, 0 }
  96. };
  97. if (setitimer(ITIMER_REAL, &T, nullptr)) {
  98. Printf("libFuzzer: setitimer failed with %d\n", errno);
  99. exit(1);
  100. }
  101. SetSigaction(SIGALRM, AlarmHandler);
  102. }
  103. void SetSignalHandler(const FuzzingOptions& Options) {
  104. // setitimer is not implemented in emscripten.
  105. if (Options.HandleAlrm && Options.UnitTimeoutSec > 0 && !LIBFUZZER_EMSCRIPTEN)
  106. SetTimer(Options.UnitTimeoutSec / 2 + 1);
  107. if (Options.HandleInt)
  108. SetSigaction(SIGINT, InterruptHandler);
  109. if (Options.HandleTerm)
  110. SetSigaction(SIGTERM, InterruptHandler);
  111. if (Options.HandleSegv)
  112. SetSigaction(SIGSEGV, SegvHandler);
  113. if (Options.HandleBus)
  114. SetSigaction(SIGBUS, CrashHandler);
  115. if (Options.HandleAbrt)
  116. SetSigaction(SIGABRT, CrashHandler);
  117. if (Options.HandleIll)
  118. SetSigaction(SIGILL, CrashHandler);
  119. if (Options.HandleFpe)
  120. SetSigaction(SIGFPE, CrashHandler);
  121. if (Options.HandleXfsz)
  122. SetSigaction(SIGXFSZ, FileSizeExceedHandler);
  123. if (Options.HandleUsr1)
  124. SetSigaction(SIGUSR1, GracefulExitHandler);
  125. if (Options.HandleUsr2)
  126. SetSigaction(SIGUSR2, GracefulExitHandler);
  127. }
  128. void SleepSeconds(int Seconds) {
  129. sleep(Seconds); // Use C API to avoid coverage from instrumented libc++.
  130. }
  131. unsigned long GetPid() { return (unsigned long)getpid(); }
  132. size_t GetPeakRSSMb() {
  133. struct rusage usage;
  134. if (getrusage(RUSAGE_SELF, &usage))
  135. return 0;
  136. if (LIBFUZZER_LINUX || LIBFUZZER_FREEBSD || LIBFUZZER_NETBSD ||
  137. LIBFUZZER_EMSCRIPTEN) {
  138. // ru_maxrss is in KiB
  139. return usage.ru_maxrss >> 10;
  140. } else if (LIBFUZZER_APPLE) {
  141. // ru_maxrss is in bytes
  142. return usage.ru_maxrss >> 20;
  143. }
  144. assert(0 && "GetPeakRSSMb() is not implemented for your platform");
  145. return 0;
  146. }
  147. FILE *OpenProcessPipe(const char *Command, const char *Mode) {
  148. return popen(Command, Mode);
  149. }
  150. int CloseProcessPipe(FILE *F) {
  151. return pclose(F);
  152. }
  153. const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt,
  154. size_t PattLen) {
  155. return memmem(Data, DataLen, Patt, PattLen);
  156. }
  157. std::string DisassembleCmd(const std::string &FileName) {
  158. return "objdump -d " + FileName;
  159. }
  160. std::string SearchRegexCmd(const std::string &Regex) {
  161. return "grep '" + Regex + "'";
  162. }
  163. } // namespace fuzzer
  164. #endif // LIBFUZZER_POSIX