13cab2bb3Spatrick //===- FuzzerUtilPosix.cpp - Misc utils for Posix. ------------------------===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick // Misc utils implementation using Posix API.
93cab2bb3Spatrick //===----------------------------------------------------------------------===//
101f9cb04fSpatrick #include "FuzzerPlatform.h"
113cab2bb3Spatrick #if LIBFUZZER_POSIX
123cab2bb3Spatrick #include "FuzzerIO.h"
133cab2bb3Spatrick #include "FuzzerInternal.h"
143cab2bb3Spatrick #include "FuzzerTracePC.h"
153cab2bb3Spatrick #include <cassert>
163cab2bb3Spatrick #include <chrono>
173cab2bb3Spatrick #include <cstring>
183cab2bb3Spatrick #include <errno.h>
193cab2bb3Spatrick #include <iomanip>
203cab2bb3Spatrick #include <signal.h>
213cab2bb3Spatrick #include <stdio.h>
223cab2bb3Spatrick #include <sys/mman.h>
233cab2bb3Spatrick #include <sys/resource.h>
243cab2bb3Spatrick #include <sys/syscall.h>
253cab2bb3Spatrick #include <sys/time.h>
263cab2bb3Spatrick #include <sys/types.h>
273cab2bb3Spatrick #include <thread>
283cab2bb3Spatrick #include <unistd.h>
293cab2bb3Spatrick 
303cab2bb3Spatrick namespace fuzzer {
313cab2bb3Spatrick 
AlarmHandler(int,siginfo_t *,void *)323cab2bb3Spatrick static void AlarmHandler(int, siginfo_t *, void *) {
333cab2bb3Spatrick   Fuzzer::StaticAlarmCallback();
343cab2bb3Spatrick }
353cab2bb3Spatrick 
363cab2bb3Spatrick static void (*upstream_segv_handler)(int, siginfo_t *, void *);
373cab2bb3Spatrick 
SegvHandler(int sig,siginfo_t * si,void * ucontext)383cab2bb3Spatrick static void SegvHandler(int sig, siginfo_t *si, void *ucontext) {
393cab2bb3Spatrick   assert(si->si_signo == SIGSEGV);
403cab2bb3Spatrick   if (upstream_segv_handler)
413cab2bb3Spatrick     return upstream_segv_handler(sig, si, ucontext);
423cab2bb3Spatrick   Fuzzer::StaticCrashSignalCallback();
433cab2bb3Spatrick }
443cab2bb3Spatrick 
CrashHandler(int,siginfo_t *,void *)453cab2bb3Spatrick static void CrashHandler(int, siginfo_t *, void *) {
463cab2bb3Spatrick   Fuzzer::StaticCrashSignalCallback();
473cab2bb3Spatrick }
483cab2bb3Spatrick 
InterruptHandler(int,siginfo_t *,void *)493cab2bb3Spatrick static void InterruptHandler(int, siginfo_t *, void *) {
503cab2bb3Spatrick   Fuzzer::StaticInterruptCallback();
513cab2bb3Spatrick }
523cab2bb3Spatrick 
GracefulExitHandler(int,siginfo_t *,void *)533cab2bb3Spatrick static void GracefulExitHandler(int, siginfo_t *, void *) {
543cab2bb3Spatrick   Fuzzer::StaticGracefulExitCallback();
553cab2bb3Spatrick }
563cab2bb3Spatrick 
FileSizeExceedHandler(int,siginfo_t *,void *)573cab2bb3Spatrick static void FileSizeExceedHandler(int, siginfo_t *, void *) {
583cab2bb3Spatrick   Fuzzer::StaticFileSizeExceedCallback();
593cab2bb3Spatrick }
603cab2bb3Spatrick 
SetSigaction(int signum,void (* callback)(int,siginfo_t *,void *))613cab2bb3Spatrick static void SetSigaction(int signum,
623cab2bb3Spatrick                          void (*callback)(int, siginfo_t *, void *)) {
633cab2bb3Spatrick   struct sigaction sigact = {};
643cab2bb3Spatrick   if (sigaction(signum, nullptr, &sigact)) {
653cab2bb3Spatrick     Printf("libFuzzer: sigaction failed with %d\n", errno);
663cab2bb3Spatrick     exit(1);
673cab2bb3Spatrick   }
683cab2bb3Spatrick   if (sigact.sa_flags & SA_SIGINFO) {
693cab2bb3Spatrick     if (sigact.sa_sigaction) {
703cab2bb3Spatrick       if (signum != SIGSEGV)
713cab2bb3Spatrick         return;
723cab2bb3Spatrick       upstream_segv_handler = sigact.sa_sigaction;
733cab2bb3Spatrick     }
743cab2bb3Spatrick   } else {
753cab2bb3Spatrick     if (sigact.sa_handler != SIG_DFL && sigact.sa_handler != SIG_IGN &&
763cab2bb3Spatrick         sigact.sa_handler != SIG_ERR)
773cab2bb3Spatrick       return;
783cab2bb3Spatrick   }
793cab2bb3Spatrick 
80*d89ec533Spatrick   struct sigaction new_sigact = {};
81*d89ec533Spatrick   // Address sanitizer needs SA_ONSTACK (causing the signal handler to run on a
82*d89ec533Spatrick   // dedicated stack) in order to be able to detect stack overflows; keep the
83*d89ec533Spatrick   // flag if it's set.
84*d89ec533Spatrick   new_sigact.sa_flags = SA_SIGINFO | (sigact.sa_flags & SA_ONSTACK);
85*d89ec533Spatrick   new_sigact.sa_sigaction = callback;
86*d89ec533Spatrick   if (sigaction(signum, &new_sigact, nullptr)) {
873cab2bb3Spatrick     Printf("libFuzzer: sigaction failed with %d\n", errno);
883cab2bb3Spatrick     exit(1);
893cab2bb3Spatrick   }
903cab2bb3Spatrick }
913cab2bb3Spatrick 
921f9cb04fSpatrick // Return true on success, false otherwise.
ExecuteCommand(const Command & Cmd,std::string * CmdOutput)931f9cb04fSpatrick bool ExecuteCommand(const Command &Cmd, std::string *CmdOutput) {
941f9cb04fSpatrick   FILE *Pipe = popen(Cmd.toString().c_str(), "r");
951f9cb04fSpatrick   if (!Pipe)
961f9cb04fSpatrick     return false;
971f9cb04fSpatrick 
981f9cb04fSpatrick   if (CmdOutput) {
991f9cb04fSpatrick     char TmpBuffer[128];
1001f9cb04fSpatrick     while (fgets(TmpBuffer, sizeof(TmpBuffer), Pipe))
1011f9cb04fSpatrick       CmdOutput->append(TmpBuffer);
1021f9cb04fSpatrick   }
1031f9cb04fSpatrick   return pclose(Pipe) == 0;
1041f9cb04fSpatrick }
1051f9cb04fSpatrick 
SetTimer(int Seconds)1063cab2bb3Spatrick void SetTimer(int Seconds) {
1073cab2bb3Spatrick   struct itimerval T {
1083cab2bb3Spatrick     {Seconds, 0}, { Seconds, 0 }
1093cab2bb3Spatrick   };
1103cab2bb3Spatrick   if (setitimer(ITIMER_REAL, &T, nullptr)) {
1113cab2bb3Spatrick     Printf("libFuzzer: setitimer failed with %d\n", errno);
1123cab2bb3Spatrick     exit(1);
1133cab2bb3Spatrick   }
1143cab2bb3Spatrick   SetSigaction(SIGALRM, AlarmHandler);
1153cab2bb3Spatrick }
1163cab2bb3Spatrick 
SetSignalHandler(const FuzzingOptions & Options)1173cab2bb3Spatrick void SetSignalHandler(const FuzzingOptions& Options) {
1183cab2bb3Spatrick   // setitimer is not implemented in emscripten.
119*d89ec533Spatrick   if (Options.HandleAlrm && Options.UnitTimeoutSec > 0 && !LIBFUZZER_EMSCRIPTEN)
1203cab2bb3Spatrick     SetTimer(Options.UnitTimeoutSec / 2 + 1);
1213cab2bb3Spatrick   if (Options.HandleInt)
1223cab2bb3Spatrick     SetSigaction(SIGINT, InterruptHandler);
1233cab2bb3Spatrick   if (Options.HandleTerm)
1243cab2bb3Spatrick     SetSigaction(SIGTERM, InterruptHandler);
1253cab2bb3Spatrick   if (Options.HandleSegv)
1263cab2bb3Spatrick     SetSigaction(SIGSEGV, SegvHandler);
1273cab2bb3Spatrick   if (Options.HandleBus)
1283cab2bb3Spatrick     SetSigaction(SIGBUS, CrashHandler);
1293cab2bb3Spatrick   if (Options.HandleAbrt)
1303cab2bb3Spatrick     SetSigaction(SIGABRT, CrashHandler);
1313cab2bb3Spatrick   if (Options.HandleIll)
1323cab2bb3Spatrick     SetSigaction(SIGILL, CrashHandler);
1333cab2bb3Spatrick   if (Options.HandleFpe)
1343cab2bb3Spatrick     SetSigaction(SIGFPE, CrashHandler);
1353cab2bb3Spatrick   if (Options.HandleXfsz)
1363cab2bb3Spatrick     SetSigaction(SIGXFSZ, FileSizeExceedHandler);
1373cab2bb3Spatrick   if (Options.HandleUsr1)
1383cab2bb3Spatrick     SetSigaction(SIGUSR1, GracefulExitHandler);
1393cab2bb3Spatrick   if (Options.HandleUsr2)
1403cab2bb3Spatrick     SetSigaction(SIGUSR2, GracefulExitHandler);
1413cab2bb3Spatrick }
1423cab2bb3Spatrick 
SleepSeconds(int Seconds)1433cab2bb3Spatrick void SleepSeconds(int Seconds) {
1443cab2bb3Spatrick   sleep(Seconds); // Use C API to avoid coverage from instrumented libc++.
1453cab2bb3Spatrick }
1463cab2bb3Spatrick 
GetPid()1473cab2bb3Spatrick unsigned long GetPid() { return (unsigned long)getpid(); }
1483cab2bb3Spatrick 
GetPeakRSSMb()1493cab2bb3Spatrick size_t GetPeakRSSMb() {
1503cab2bb3Spatrick   struct rusage usage;
1513cab2bb3Spatrick   if (getrusage(RUSAGE_SELF, &usage))
1523cab2bb3Spatrick     return 0;
1533cab2bb3Spatrick   if (LIBFUZZER_LINUX || LIBFUZZER_FREEBSD || LIBFUZZER_NETBSD ||
154*d89ec533Spatrick       LIBFUZZER_EMSCRIPTEN) {
1553cab2bb3Spatrick     // ru_maxrss is in KiB
1563cab2bb3Spatrick     return usage.ru_maxrss >> 10;
1573cab2bb3Spatrick   } else if (LIBFUZZER_APPLE) {
1583cab2bb3Spatrick     // ru_maxrss is in bytes
1593cab2bb3Spatrick     return usage.ru_maxrss >> 20;
1603cab2bb3Spatrick   }
1613cab2bb3Spatrick   assert(0 && "GetPeakRSSMb() is not implemented for your platform");
1623cab2bb3Spatrick   return 0;
1633cab2bb3Spatrick }
1643cab2bb3Spatrick 
OpenProcessPipe(const char * Command,const char * Mode)1653cab2bb3Spatrick FILE *OpenProcessPipe(const char *Command, const char *Mode) {
1663cab2bb3Spatrick   return popen(Command, Mode);
1673cab2bb3Spatrick }
1683cab2bb3Spatrick 
CloseProcessPipe(FILE * F)1691f9cb04fSpatrick int CloseProcessPipe(FILE *F) {
1701f9cb04fSpatrick   return pclose(F);
1711f9cb04fSpatrick }
1721f9cb04fSpatrick 
SearchMemory(const void * Data,size_t DataLen,const void * Patt,size_t PattLen)1733cab2bb3Spatrick const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt,
1743cab2bb3Spatrick                          size_t PattLen) {
1753cab2bb3Spatrick   return memmem(Data, DataLen, Patt, PattLen);
1763cab2bb3Spatrick }
1773cab2bb3Spatrick 
DisassembleCmd(const std::string & FileName)1783cab2bb3Spatrick std::string DisassembleCmd(const std::string &FileName) {
1793cab2bb3Spatrick   return "objdump -d " + FileName;
1803cab2bb3Spatrick }
1813cab2bb3Spatrick 
SearchRegexCmd(const std::string & Regex)1823cab2bb3Spatrick std::string SearchRegexCmd(const std::string &Regex) {
1833cab2bb3Spatrick   return "grep '" + Regex + "'";
1843cab2bb3Spatrick }
1853cab2bb3Spatrick 
1863cab2bb3Spatrick }  // namespace fuzzer
1873cab2bb3Spatrick 
1883cab2bb3Spatrick #endif // LIBFUZZER_POSIX
189