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 if (Options.UnitTimeoutSec > 0) 102 SetTimer(Options.UnitTimeoutSec / 2 + 1); 103 if (Options.HandleInt) 104 SetSigaction(SIGINT, InterruptHandler); 105 if (Options.HandleTerm) 106 SetSigaction(SIGTERM, InterruptHandler); 107 if (Options.HandleSegv) 108 SetSigaction(SIGSEGV, SegvHandler); 109 if (Options.HandleBus) 110 SetSigaction(SIGBUS, CrashHandler); 111 if (Options.HandleAbrt) 112 SetSigaction(SIGABRT, CrashHandler); 113 if (Options.HandleIll) 114 SetSigaction(SIGILL, CrashHandler); 115 if (Options.HandleFpe) 116 SetSigaction(SIGFPE, CrashHandler); 117 if (Options.HandleXfsz) 118 SetSigaction(SIGXFSZ, FileSizeExceedHandler); 119 if (Options.HandleUsr1) 120 SetSigaction(SIGUSR1, GracefulExitHandler); 121 if (Options.HandleUsr2) 122 SetSigaction(SIGUSR2, GracefulExitHandler); 123 } 124 125 void SleepSeconds(int Seconds) { 126 sleep(Seconds); // Use C API to avoid coverage from instrumented libc++. 127 } 128 129 unsigned long GetPid() { return (unsigned long)getpid(); } 130 131 size_t GetPeakRSSMb() { 132 struct rusage usage; 133 if (getrusage(RUSAGE_SELF, &usage)) 134 return 0; 135 if (LIBFUZZER_LINUX || LIBFUZZER_FREEBSD || LIBFUZZER_NETBSD || 136 LIBFUZZER_OPENBSD) { 137 // ru_maxrss is in KiB 138 return usage.ru_maxrss >> 10; 139 } else if (LIBFUZZER_APPLE) { 140 // ru_maxrss is in bytes 141 return usage.ru_maxrss >> 20; 142 } 143 assert(0 && "GetPeakRSSMb() is not implemented for your platform"); 144 return 0; 145 } 146 147 FILE *OpenProcessPipe(const char *Command, const char *Mode) { 148 return popen(Command, Mode); 149 } 150 151 const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt, 152 size_t PattLen) { 153 return memmem(Data, DataLen, Patt, PattLen); 154 } 155 156 std::string DisassembleCmd(const std::string &FileName) { 157 return "objdump -d " + FileName; 158 } 159 160 std::string SearchRegexCmd(const std::string &Regex) { 161 return "grep '" + Regex + "'"; 162 } 163 164 } // namespace fuzzer 165 166 #endif // LIBFUZZER_POSIX 167