//===- FuzzerUtilPosix.cpp - Misc utils for Posix. ------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // Misc utils implementation using Posix API. //===----------------------------------------------------------------------===// #include "FuzzerDefs.h" #if LIBFUZZER_POSIX #include "FuzzerIO.h" #include "FuzzerInternal.h" #include #include #include #include #include #include #include #include #include #include #include #include #include namespace fuzzer { static void AlarmHandler(int, siginfo_t *, void *) { Fuzzer::StaticAlarmCallback(); } static void CrashHandler(int, siginfo_t *, void *) { Fuzzer::StaticCrashSignalCallback(); } static void InterruptHandler(int, siginfo_t *, void *) { Fuzzer::StaticInterruptCallback(); } static void GracefulExitHandler(int, siginfo_t *, void *) { Fuzzer::StaticGracefulExitCallback(); } static void FileSizeExceedHandler(int, siginfo_t *, void *) { Fuzzer::StaticFileSizeExceedCallback(); } static void SetSigaction(int signum, void (*callback)(int, siginfo_t *, void *)) { struct sigaction sigact = {}; if (sigaction(signum, nullptr, &sigact)) { Printf("libFuzzer: sigaction failed with %d\n", errno); exit(1); } if (sigact.sa_flags & SA_SIGINFO) { if (sigact.sa_sigaction) return; } else { if (sigact.sa_handler != SIG_DFL && sigact.sa_handler != SIG_IGN && sigact.sa_handler != SIG_ERR) return; } sigact = {}; sigact.sa_sigaction = callback; if (sigaction(signum, &sigact, 0)) { Printf("libFuzzer: sigaction failed with %d\n", errno); exit(1); } } void SetTimer(int Seconds) { struct itimerval T { {Seconds, 0}, { Seconds, 0 } }; if (setitimer(ITIMER_REAL, &T, nullptr)) { Printf("libFuzzer: setitimer failed with %d\n", errno); exit(1); } SetSigaction(SIGALRM, AlarmHandler); } void SetSignalHandler(const FuzzingOptions& Options) { if (Options.UnitTimeoutSec > 0) SetTimer(Options.UnitTimeoutSec / 2 + 1); if (Options.HandleInt) SetSigaction(SIGINT, InterruptHandler); if (Options.HandleTerm) SetSigaction(SIGTERM, InterruptHandler); if (Options.HandleSegv) SetSigaction(SIGSEGV, CrashHandler); if (Options.HandleBus) SetSigaction(SIGBUS, CrashHandler); if (Options.HandleAbrt) SetSigaction(SIGABRT, CrashHandler); if (Options.HandleIll) SetSigaction(SIGILL, CrashHandler); if (Options.HandleFpe) SetSigaction(SIGFPE, CrashHandler); if (Options.HandleXfsz) SetSigaction(SIGXFSZ, FileSizeExceedHandler); if (Options.HandleUsr1) SetSigaction(SIGUSR1, GracefulExitHandler); if (Options.HandleUsr2) SetSigaction(SIGUSR2, GracefulExitHandler); } void SleepSeconds(int Seconds) { sleep(Seconds); // Use C API to avoid coverage from instrumented libc++. } unsigned long GetPid() { return (unsigned long)getpid(); } size_t GetPeakRSSMb() { struct rusage usage; if (getrusage(RUSAGE_SELF, &usage)) return 0; if (LIBFUZZER_LINUX || LIBFUZZER_FREEBSD || LIBFUZZER_NETBSD || LIBFUZZER_OPENBSD) { // ru_maxrss is in KiB return usage.ru_maxrss >> 10; } else if (LIBFUZZER_APPLE) { // ru_maxrss is in bytes return usage.ru_maxrss >> 20; } assert(0 && "GetPeakRSSMb() is not implemented for your platform"); return 0; } FILE *OpenProcessPipe(const char *Command, const char *Mode) { return popen(Command, Mode); } const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt, size_t PattLen) { return memmem(Data, DataLen, Patt, PattLen); } std::string DisassembleCmd(const std::string &FileName) { return "objdump -d " + FileName; } std::string SearchRegexCmd(const std::string &Regex) { return "grep '" + Regex + "'"; } } // namespace fuzzer #endif // LIBFUZZER_POSIX