1 //===- FuzzerUtilPosix.cpp - Misc utils for Posix. ------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 // Misc utils implementation using Posix API.
10 //===----------------------------------------------------------------------===//
11 #include "FuzzerDefs.h"
12 #if LIBFUZZER_POSIX
13 #include "FuzzerIO.h"
14 #include "FuzzerInternal.h"
15 #include <cassert>
16 #include <chrono>
17 #include <cstring>
18 #include <errno.h>
19 #include <iomanip>
20 #include <signal.h>
21 #include <sstream>
22 #include <stdio.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 
AlarmHandler(int,siginfo_t *,void *)32 static void AlarmHandler(int, siginfo_t *, void *) {
33   Fuzzer::StaticAlarmCallback();
34 }
35 
CrashHandler(int,siginfo_t *,void *)36 static void CrashHandler(int, siginfo_t *, void *) {
37   Fuzzer::StaticCrashSignalCallback();
38 }
39 
InterruptHandler(int,siginfo_t *,void *)40 static void InterruptHandler(int, siginfo_t *, void *) {
41   Fuzzer::StaticInterruptCallback();
42 }
43 
SetSigaction(int signum,void (* callback)(int,siginfo_t *,void *))44 static void SetSigaction(int signum,
45                          void (*callback)(int, siginfo_t *, void *)) {
46   struct sigaction sigact;
47   memset(&sigact, 0, sizeof(sigact));
48   sigact.sa_sigaction = callback;
49   if (sigaction(signum, &sigact, 0)) {
50     Printf("libFuzzer: sigaction failed with %d\n", errno);
51     exit(1);
52   }
53 }
54 
SetTimer(int Seconds)55 void SetTimer(int Seconds) {
56   struct itimerval T {
57     {Seconds, 0}, { Seconds, 0 }
58   };
59   if (setitimer(ITIMER_REAL, &T, nullptr)) {
60     Printf("libFuzzer: setitimer failed with %d\n", errno);
61     exit(1);
62   }
63   SetSigaction(SIGALRM, AlarmHandler);
64 }
65 
SetSignalHandler(const FuzzingOptions & Options)66 void SetSignalHandler(const FuzzingOptions& Options) {
67   if (Options.UnitTimeoutSec > 0)
68     SetTimer(Options.UnitTimeoutSec / 2 + 1);
69   if (Options.HandleInt)
70     SetSigaction(SIGINT, InterruptHandler);
71   if (Options.HandleTerm)
72     SetSigaction(SIGTERM, InterruptHandler);
73   if (Options.HandleSegv)
74     SetSigaction(SIGSEGV, CrashHandler);
75   if (Options.HandleBus)
76     SetSigaction(SIGBUS, CrashHandler);
77   if (Options.HandleAbrt)
78     SetSigaction(SIGABRT, CrashHandler);
79   if (Options.HandleIll)
80     SetSigaction(SIGILL, CrashHandler);
81   if (Options.HandleFpe)
82     SetSigaction(SIGFPE, CrashHandler);
83 }
84 
SleepSeconds(int Seconds)85 void SleepSeconds(int Seconds) {
86   sleep(Seconds); // Use C API to avoid coverage from instrumented libc++.
87 }
88 
GetPid()89 unsigned long GetPid() { return (unsigned long)getpid(); }
90 
GetPeakRSSMb()91 size_t GetPeakRSSMb() {
92   struct rusage usage;
93   if (getrusage(RUSAGE_SELF, &usage))
94     return 0;
95   if (LIBFUZZER_LINUX) {
96     // ru_maxrss is in KiB
97     return usage.ru_maxrss >> 10;
98   } else if (LIBFUZZER_APPLE) {
99     // ru_maxrss is in bytes
100     return usage.ru_maxrss >> 20;
101   }
102   assert(0 && "GetPeakRSSMb() is not implemented for your platform");
103   return 0;
104 }
105 
OpenProcessPipe(const char * Command,const char * Mode)106 FILE *OpenProcessPipe(const char *Command, const char *Mode) {
107   return popen(Command, Mode);
108 }
109 
SearchMemory(const void * Data,size_t DataLen,const void * Patt,size_t PattLen)110 const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt,
111                          size_t PattLen) {
112   return memmem(Data, DataLen, Patt, PattLen);
113 }
114 
115 }  // namespace fuzzer
116 
117 #endif // LIBFUZZER_POSIX
118