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 30 namespace fuzzer { 31 32 static void AlarmHandler(int, siginfo_t *, void *) { 33 Fuzzer::StaticAlarmCallback(); 34 } 35 36 static void (*upstream_segv_handler)(int, siginfo_t *, void *); 37 38 static void SegvHandler(int sig, siginfo_t *si, void *ucontext) { 39 assert(si->si_signo == SIGSEGV); 40 if (upstream_segv_handler) 41 return upstream_segv_handler(sig, si, ucontext); 42 Fuzzer::StaticCrashSignalCallback(); 43 } 44 45 static void CrashHandler(int, siginfo_t *, void *) { 46 Fuzzer::StaticCrashSignalCallback(); 47 } 48 49 static void InterruptHandler(int, siginfo_t *, void *) { 50 Fuzzer::StaticInterruptCallback(); 51 } 52 53 static void GracefulExitHandler(int, siginfo_t *, void *) { 54 Fuzzer::StaticGracefulExitCallback(); 55 } 56 57 static void FileSizeExceedHandler(int, siginfo_t *, void *) { 58 Fuzzer::StaticFileSizeExceedCallback(); 59 } 60 61 static void SetSigaction(int signum, 62 void (*callback)(int, siginfo_t *, void *)) { 63 struct sigaction sigact = {}; 64 if (sigaction(signum, nullptr, &sigact)) { 65 Printf("libFuzzer: sigaction failed with %d\n", errno); 66 exit(1); 67 } 68 if (sigact.sa_flags & SA_SIGINFO) { 69 if (sigact.sa_sigaction) { 70 if (signum != SIGSEGV) 71 return; 72 upstream_segv_handler = sigact.sa_sigaction; 73 } 74 } else { 75 if (sigact.sa_handler != SIG_DFL && sigact.sa_handler != SIG_IGN && 76 sigact.sa_handler != SIG_ERR) 77 return; 78 } 79 80 sigact = {}; 81 sigact.sa_flags = SA_SIGINFO; 82 sigact.sa_sigaction = callback; 83 if (sigaction(signum, &sigact, 0)) { 84 Printf("libFuzzer: sigaction failed with %d\n", errno); 85 exit(1); 86 } 87 } 88 89 // Return true on success, false otherwise. 90 bool ExecuteCommand(const Command &Cmd, std::string *CmdOutput) { 91 FILE *Pipe = popen(Cmd.toString().c_str(), "r"); 92 if (!Pipe) 93 return false; 94 95 if (CmdOutput) { 96 char TmpBuffer[128]; 97 while (fgets(TmpBuffer, sizeof(TmpBuffer), Pipe)) 98 CmdOutput->append(TmpBuffer); 99 } 100 return pclose(Pipe) == 0; 101 } 102 103 void SetTimer(int Seconds) { 104 struct itimerval T { 105 {Seconds, 0}, { Seconds, 0 } 106 }; 107 if (setitimer(ITIMER_REAL, &T, nullptr)) { 108 Printf("libFuzzer: setitimer failed with %d\n", errno); 109 exit(1); 110 } 111 SetSigaction(SIGALRM, AlarmHandler); 112 } 113 114 void SetSignalHandler(const FuzzingOptions& Options) { 115 // setitimer is not implemented in emscripten. 116 if (Options.HandleAlrm && Options.UnitTimeoutSec > 0 && !LIBFUZZER_EMSCRIPTEN) 117 SetTimer(Options.UnitTimeoutSec / 2 + 1); 118 if (Options.HandleInt) 119 SetSigaction(SIGINT, InterruptHandler); 120 if (Options.HandleTerm) 121 SetSigaction(SIGTERM, InterruptHandler); 122 if (Options.HandleSegv) 123 SetSigaction(SIGSEGV, SegvHandler); 124 if (Options.HandleBus) 125 SetSigaction(SIGBUS, CrashHandler); 126 if (Options.HandleAbrt) 127 SetSigaction(SIGABRT, CrashHandler); 128 if (Options.HandleIll) 129 SetSigaction(SIGILL, CrashHandler); 130 if (Options.HandleFpe) 131 SetSigaction(SIGFPE, CrashHandler); 132 if (Options.HandleXfsz) 133 SetSigaction(SIGXFSZ, FileSizeExceedHandler); 134 if (Options.HandleUsr1) 135 SetSigaction(SIGUSR1, GracefulExitHandler); 136 if (Options.HandleUsr2) 137 SetSigaction(SIGUSR2, GracefulExitHandler); 138 } 139 140 void SleepSeconds(int Seconds) { 141 sleep(Seconds); // Use C API to avoid coverage from instrumented libc++. 142 } 143 144 unsigned long GetPid() { return (unsigned long)getpid(); } 145 146 size_t GetPeakRSSMb() { 147 struct rusage usage; 148 if (getrusage(RUSAGE_SELF, &usage)) 149 return 0; 150 if (LIBFUZZER_LINUX || LIBFUZZER_FREEBSD || LIBFUZZER_NETBSD || 151 LIBFUZZER_EMSCRIPTEN) { 152 // ru_maxrss is in KiB 153 return usage.ru_maxrss >> 10; 154 } else if (LIBFUZZER_APPLE) { 155 // ru_maxrss is in bytes 156 return usage.ru_maxrss >> 20; 157 } 158 assert(0 && "GetPeakRSSMb() is not implemented for your platform"); 159 return 0; 160 } 161 162 FILE *OpenProcessPipe(const char *Command, const char *Mode) { 163 return popen(Command, Mode); 164 } 165 166 int CloseProcessPipe(FILE *F) { 167 return pclose(F); 168 } 169 170 const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt, 171 size_t PattLen) { 172 return memmem(Data, DataLen, Patt, PattLen); 173 } 174 175 std::string DisassembleCmd(const std::string &FileName) { 176 return "objdump -d " + FileName; 177 } 178 179 std::string SearchRegexCmd(const std::string &Regex) { 180 return "grep '" + Regex + "'"; 181 } 182 183 } // namespace fuzzer 184 185 #endif // LIBFUZZER_POSIX 186