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 "FuzzerDefs.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 void SetTimer(int Seconds) { 90 struct itimerval T { 91 {Seconds, 0}, { Seconds, 0 } 92 }; 93 if (setitimer(ITIMER_REAL, &T, nullptr)) { 94 Printf("libFuzzer: setitimer failed with %d\n", errno); 95 exit(1); 96 } 97 SetSigaction(SIGALRM, AlarmHandler); 98 } 99 100 void SetSignalHandler(const FuzzingOptions& Options) { 101 // setitimer is not implemented in emscripten. 102 if (Options.UnitTimeoutSec > 0 && !LIBFUZZER_EMSCRIPTEN) 103 SetTimer(Options.UnitTimeoutSec / 2 + 1); 104 if (Options.HandleInt) 105 SetSigaction(SIGINT, InterruptHandler); 106 if (Options.HandleTerm) 107 SetSigaction(SIGTERM, InterruptHandler); 108 if (Options.HandleSegv) 109 SetSigaction(SIGSEGV, SegvHandler); 110 if (Options.HandleBus) 111 SetSigaction(SIGBUS, CrashHandler); 112 if (Options.HandleAbrt) 113 SetSigaction(SIGABRT, CrashHandler); 114 if (Options.HandleIll) 115 SetSigaction(SIGILL, CrashHandler); 116 if (Options.HandleFpe) 117 SetSigaction(SIGFPE, CrashHandler); 118 if (Options.HandleXfsz) 119 SetSigaction(SIGXFSZ, FileSizeExceedHandler); 120 if (Options.HandleUsr1) 121 SetSigaction(SIGUSR1, GracefulExitHandler); 122 if (Options.HandleUsr2) 123 SetSigaction(SIGUSR2, GracefulExitHandler); 124 } 125 126 void SleepSeconds(int Seconds) { 127 sleep(Seconds); // Use C API to avoid coverage from instrumented libc++. 128 } 129 130 unsigned long GetPid() { return (unsigned long)getpid(); } 131 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_OPENBSD || 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 148 FILE *OpenProcessPipe(const char *Command, const char *Mode) { 149 return popen(Command, Mode); 150 } 151 152 const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt, 153 size_t PattLen) { 154 return memmem(Data, DataLen, Patt, PattLen); 155 } 156 157 std::string DisassembleCmd(const std::string &FileName) { 158 return "objdump -d " + FileName; 159 } 160 161 std::string SearchRegexCmd(const std::string &Regex) { 162 return "grep '" + Regex + "'"; 163 } 164 165 } // namespace fuzzer 166 167 #endif // LIBFUZZER_POSIX 168