//===- FuzzerUtilPosix.cpp - Misc utils for Posix. ------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // Misc utils implementation using Posix API. //===----------------------------------------------------------------------===// #include "FuzzerDefs.h" #if LIBFUZZER_POSIX #include "FuzzerIO.h" #include "FuzzerInternal.h" #include "FuzzerTracePC.h" #include #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 (*upstream_segv_handler)(int, siginfo_t *, void *); static void SegvHandler(int sig, siginfo_t *si, void *ucontext) { assert(si->si_signo == SIGSEGV); if (TPC.UnprotectLazyCounters(si->si_addr)) return; if (upstream_segv_handler) return upstream_segv_handler(sig, si, ucontext); Fuzzer::StaticCrashSignalCallback(); } 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) { if (signum != SIGSEGV) return; upstream_segv_handler = sigact.sa_sigaction; } } else { if (sigact.sa_handler != SIG_DFL && sigact.sa_handler != SIG_IGN && sigact.sa_handler != SIG_ERR) return; } sigact = {}; sigact.sa_flags = SA_SIGINFO; 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); } bool Mprotect(void *Ptr, size_t Size, bool AllowReadWrite) { return 0 == mprotect(Ptr, Size, AllowReadWrite ? (PROT_READ | PROT_WRITE) : PROT_NONE); } 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, SegvHandler); 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