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