1326943Sdim//===- FuzzerUtilPosix.cpp - Misc utils for Posix. ------------------------===// 2326943Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6326943Sdim// 7326943Sdim//===----------------------------------------------------------------------===// 8326943Sdim// Misc utils implementation using Posix API. 9326943Sdim//===----------------------------------------------------------------------===// 10326943Sdim#include "FuzzerDefs.h" 11326943Sdim#if LIBFUZZER_POSIX 12326943Sdim#include "FuzzerIO.h" 13326943Sdim#include "FuzzerInternal.h" 14353358Sdim#include "FuzzerTracePC.h" 15326943Sdim#include <cassert> 16326943Sdim#include <chrono> 17326943Sdim#include <cstring> 18326943Sdim#include <errno.h> 19326943Sdim#include <iomanip> 20326943Sdim#include <signal.h> 21326943Sdim#include <stdio.h> 22353358Sdim#include <sys/mman.h> 23326943Sdim#include <sys/resource.h> 24326943Sdim#include <sys/syscall.h> 25326943Sdim#include <sys/time.h> 26326943Sdim#include <sys/types.h> 27326943Sdim#include <thread> 28326943Sdim#include <unistd.h> 29326943Sdim 30326943Sdimnamespace fuzzer { 31326943Sdim 32326943Sdimstatic void AlarmHandler(int, siginfo_t *, void *) { 33326943Sdim Fuzzer::StaticAlarmCallback(); 34326943Sdim} 35326943Sdim 36353358Sdimstatic void (*upstream_segv_handler)(int, siginfo_t *, void *); 37353358Sdim 38353358Sdimstatic void SegvHandler(int sig, siginfo_t *si, void *ucontext) { 39353358Sdim assert(si->si_signo == SIGSEGV); 40353358Sdim if (upstream_segv_handler) 41353358Sdim return upstream_segv_handler(sig, si, ucontext); 42353358Sdim Fuzzer::StaticCrashSignalCallback(); 43353358Sdim} 44353358Sdim 45326943Sdimstatic void CrashHandler(int, siginfo_t *, void *) { 46326943Sdim Fuzzer::StaticCrashSignalCallback(); 47326943Sdim} 48326943Sdim 49326943Sdimstatic void InterruptHandler(int, siginfo_t *, void *) { 50326943Sdim Fuzzer::StaticInterruptCallback(); 51326943Sdim} 52326943Sdim 53326943Sdimstatic void GracefulExitHandler(int, siginfo_t *, void *) { 54326943Sdim Fuzzer::StaticGracefulExitCallback(); 55326943Sdim} 56326943Sdim 57326943Sdimstatic void FileSizeExceedHandler(int, siginfo_t *, void *) { 58326943Sdim Fuzzer::StaticFileSizeExceedCallback(); 59326943Sdim} 60326943Sdim 61326943Sdimstatic void SetSigaction(int signum, 62326943Sdim void (*callback)(int, siginfo_t *, void *)) { 63326943Sdim struct sigaction sigact = {}; 64326943Sdim if (sigaction(signum, nullptr, &sigact)) { 65326943Sdim Printf("libFuzzer: sigaction failed with %d\n", errno); 66326943Sdim exit(1); 67326943Sdim } 68326943Sdim if (sigact.sa_flags & SA_SIGINFO) { 69353358Sdim if (sigact.sa_sigaction) { 70353358Sdim if (signum != SIGSEGV) 71353358Sdim return; 72353358Sdim upstream_segv_handler = sigact.sa_sigaction; 73353358Sdim } 74326943Sdim } else { 75326943Sdim if (sigact.sa_handler != SIG_DFL && sigact.sa_handler != SIG_IGN && 76326943Sdim sigact.sa_handler != SIG_ERR) 77326943Sdim return; 78326943Sdim } 79326943Sdim 80326943Sdim sigact = {}; 81353358Sdim sigact.sa_flags = SA_SIGINFO; 82326943Sdim sigact.sa_sigaction = callback; 83326943Sdim if (sigaction(signum, &sigact, 0)) { 84326943Sdim Printf("libFuzzer: sigaction failed with %d\n", errno); 85326943Sdim exit(1); 86326943Sdim } 87326943Sdim} 88326943Sdim 89326943Sdimvoid SetTimer(int Seconds) { 90326943Sdim struct itimerval T { 91326943Sdim {Seconds, 0}, { Seconds, 0 } 92326943Sdim }; 93326943Sdim if (setitimer(ITIMER_REAL, &T, nullptr)) { 94326943Sdim Printf("libFuzzer: setitimer failed with %d\n", errno); 95326943Sdim exit(1); 96326943Sdim } 97326943Sdim SetSigaction(SIGALRM, AlarmHandler); 98326943Sdim} 99326943Sdim 100326943Sdimvoid SetSignalHandler(const FuzzingOptions& Options) { 101360784Sdim // setitimer is not implemented in emscripten. 102360784Sdim if (Options.UnitTimeoutSec > 0 && !LIBFUZZER_EMSCRIPTEN) 103326943Sdim SetTimer(Options.UnitTimeoutSec / 2 + 1); 104326943Sdim if (Options.HandleInt) 105326943Sdim SetSigaction(SIGINT, InterruptHandler); 106326943Sdim if (Options.HandleTerm) 107326943Sdim SetSigaction(SIGTERM, InterruptHandler); 108326943Sdim if (Options.HandleSegv) 109353358Sdim SetSigaction(SIGSEGV, SegvHandler); 110326943Sdim if (Options.HandleBus) 111326943Sdim SetSigaction(SIGBUS, CrashHandler); 112326943Sdim if (Options.HandleAbrt) 113326943Sdim SetSigaction(SIGABRT, CrashHandler); 114326943Sdim if (Options.HandleIll) 115326943Sdim SetSigaction(SIGILL, CrashHandler); 116326943Sdim if (Options.HandleFpe) 117326943Sdim SetSigaction(SIGFPE, CrashHandler); 118326943Sdim if (Options.HandleXfsz) 119326943Sdim SetSigaction(SIGXFSZ, FileSizeExceedHandler); 120326943Sdim if (Options.HandleUsr1) 121326943Sdim SetSigaction(SIGUSR1, GracefulExitHandler); 122326943Sdim if (Options.HandleUsr2) 123326943Sdim SetSigaction(SIGUSR2, GracefulExitHandler); 124326943Sdim} 125326943Sdim 126326943Sdimvoid SleepSeconds(int Seconds) { 127326943Sdim sleep(Seconds); // Use C API to avoid coverage from instrumented libc++. 128326943Sdim} 129326943Sdim 130326943Sdimunsigned long GetPid() { return (unsigned long)getpid(); } 131326943Sdim 132326943Sdimsize_t GetPeakRSSMb() { 133326943Sdim struct rusage usage; 134326943Sdim if (getrusage(RUSAGE_SELF, &usage)) 135326943Sdim return 0; 136336817Sdim if (LIBFUZZER_LINUX || LIBFUZZER_FREEBSD || LIBFUZZER_NETBSD || 137360784Sdim LIBFUZZER_OPENBSD || LIBFUZZER_EMSCRIPTEN) { 138326943Sdim // ru_maxrss is in KiB 139326943Sdim return usage.ru_maxrss >> 10; 140326943Sdim } else if (LIBFUZZER_APPLE) { 141326943Sdim // ru_maxrss is in bytes 142326943Sdim return usage.ru_maxrss >> 20; 143326943Sdim } 144326943Sdim assert(0 && "GetPeakRSSMb() is not implemented for your platform"); 145326943Sdim return 0; 146326943Sdim} 147326943Sdim 148326943SdimFILE *OpenProcessPipe(const char *Command, const char *Mode) { 149326943Sdim return popen(Command, Mode); 150326943Sdim} 151326943Sdim 152326943Sdimconst void *SearchMemory(const void *Data, size_t DataLen, const void *Patt, 153326943Sdim size_t PattLen) { 154326943Sdim return memmem(Data, DataLen, Patt, PattLen); 155326943Sdim} 156326943Sdim 157326943Sdimstd::string DisassembleCmd(const std::string &FileName) { 158326943Sdim return "objdump -d " + FileName; 159326943Sdim} 160326943Sdim 161326943Sdimstd::string SearchRegexCmd(const std::string &Regex) { 162326943Sdim return "grep '" + Regex + "'"; 163326943Sdim} 164326943Sdim 165326943Sdim} // namespace fuzzer 166326943Sdim 167326943Sdim#endif // LIBFUZZER_POSIX 168