1 //===- FuzzerUtilPosix.cpp - Misc utils for Posix. ------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // Misc utils implementation using Posix API. 10 //===----------------------------------------------------------------------===// 11 #include "FuzzerDefs.h" 12 #if LIBFUZZER_POSIX 13 #include "FuzzerIO.h" 14 #include "FuzzerInternal.h" 15 #include <cassert> 16 #include <chrono> 17 #include <cstring> 18 #include <errno.h> 19 #include <iomanip> 20 #include <signal.h> 21 #include <sstream> 22 #include <stdio.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 CrashHandler(int, siginfo_t *, void *) { 37 Fuzzer::StaticCrashSignalCallback(); 38 } 39 40 static void InterruptHandler(int, siginfo_t *, void *) { 41 Fuzzer::StaticInterruptCallback(); 42 } 43 44 static void FileSizeExceedHandler(int, siginfo_t *, void *) { 45 Fuzzer::StaticFileSizeExceedCallback(); 46 } 47 48 static void SetSigaction(int signum, 49 void (*callback)(int, siginfo_t *, void *)) { 50 struct sigaction sigact = {}; 51 if (sigaction(signum, nullptr, &sigact)) { 52 Printf("libFuzzer: sigaction failed with %d\n", errno); 53 exit(1); 54 } 55 if (sigact.sa_flags & SA_SIGINFO) { 56 if (sigact.sa_sigaction) 57 return; 58 } else { 59 if (sigact.sa_handler != SIG_DFL && sigact.sa_handler != SIG_IGN && 60 sigact.sa_handler != SIG_ERR) 61 return; 62 } 63 64 sigact = {}; 65 sigact.sa_sigaction = callback; 66 if (sigaction(signum, &sigact, 0)) { 67 Printf("libFuzzer: sigaction failed with %d\n", errno); 68 exit(1); 69 } 70 } 71 72 void SetTimer(int Seconds) { 73 struct itimerval T { 74 {Seconds, 0}, { Seconds, 0 } 75 }; 76 if (setitimer(ITIMER_REAL, &T, nullptr)) { 77 Printf("libFuzzer: setitimer failed with %d\n", errno); 78 exit(1); 79 } 80 SetSigaction(SIGALRM, AlarmHandler); 81 } 82 83 void SetSignalHandler(const FuzzingOptions& Options) { 84 if (Options.UnitTimeoutSec > 0) 85 SetTimer(Options.UnitTimeoutSec / 2 + 1); 86 if (Options.HandleInt) 87 SetSigaction(SIGINT, InterruptHandler); 88 if (Options.HandleTerm) 89 SetSigaction(SIGTERM, InterruptHandler); 90 if (Options.HandleSegv) 91 SetSigaction(SIGSEGV, CrashHandler); 92 if (Options.HandleBus) 93 SetSigaction(SIGBUS, CrashHandler); 94 if (Options.HandleAbrt) 95 SetSigaction(SIGABRT, CrashHandler); 96 if (Options.HandleIll) 97 SetSigaction(SIGILL, CrashHandler); 98 if (Options.HandleFpe) 99 SetSigaction(SIGFPE, CrashHandler); 100 if (Options.HandleXfsz) 101 SetSigaction(SIGXFSZ, FileSizeExceedHandler); 102 } 103 104 void SleepSeconds(int Seconds) { 105 sleep(Seconds); // Use C API to avoid coverage from instrumented libc++. 106 } 107 108 unsigned long GetPid() { return (unsigned long)getpid(); } 109 110 size_t GetPeakRSSMb() { 111 struct rusage usage; 112 if (getrusage(RUSAGE_SELF, &usage)) 113 return 0; 114 if (LIBFUZZER_LINUX) { 115 // ru_maxrss is in KiB 116 return usage.ru_maxrss >> 10; 117 } else if (LIBFUZZER_APPLE) { 118 // ru_maxrss is in bytes 119 return usage.ru_maxrss >> 20; 120 } 121 assert(0 && "GetPeakRSSMb() is not implemented for your platform"); 122 return 0; 123 } 124 125 FILE *OpenProcessPipe(const char *Command, const char *Mode) { 126 return popen(Command, Mode); 127 } 128 129 const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt, 130 size_t PattLen) { 131 return memmem(Data, DataLen, Patt, PattLen); 132 } 133 134 std::string DisassembleCmd(const std::string &FileName) { 135 return "objdump -d " + FileName; 136 } 137 138 std::string SearchRegexCmd(const std::string &Regex) { 139 return "grep '" + Regex + "'"; 140 } 141 142 } // namespace fuzzer 143 144 #endif // LIBFUZZER_POSIX 145