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 <stdio.h>
22 #include <sys/resource.h>
23 #include <sys/syscall.h>
24 #include <sys/time.h>
25 #include <sys/types.h>
26 #include <thread>
27 #include <unistd.h>
28 
29 namespace fuzzer {
30 
31 static void AlarmHandler(int, siginfo_t *, void *) {
32   Fuzzer::StaticAlarmCallback();
33 }
34 
35 static void CrashHandler(int, siginfo_t *, void *) {
36   Fuzzer::StaticCrashSignalCallback();
37 }
38 
39 static void InterruptHandler(int, siginfo_t *, void *) {
40   Fuzzer::StaticInterruptCallback();
41 }
42 
43 static void FileSizeExceedHandler(int, siginfo_t *, void *) {
44   Fuzzer::StaticFileSizeExceedCallback();
45 }
46 
47 static void SetSigaction(int signum,
48                          void (*callback)(int, siginfo_t *, void *)) {
49   struct sigaction sigact = {};
50   if (sigaction(signum, nullptr, &sigact)) {
51     Printf("libFuzzer: sigaction failed with %d\n", errno);
52     exit(1);
53   }
54   if (sigact.sa_flags & SA_SIGINFO) {
55     if (sigact.sa_sigaction)
56       return;
57   } else {
58     if (sigact.sa_handler != SIG_DFL && sigact.sa_handler != SIG_IGN &&
59         sigact.sa_handler != SIG_ERR)
60       return;
61   }
62 
63   sigact = {};
64   sigact.sa_sigaction = callback;
65   if (sigaction(signum, &sigact, 0)) {
66     Printf("libFuzzer: sigaction failed with %d\n", errno);
67     exit(1);
68   }
69 }
70 
71 void SetTimer(int Seconds) {
72   struct itimerval T {
73     {Seconds, 0}, { Seconds, 0 }
74   };
75   if (setitimer(ITIMER_REAL, &T, nullptr)) {
76     Printf("libFuzzer: setitimer failed with %d\n", errno);
77     exit(1);
78   }
79   SetSigaction(SIGALRM, AlarmHandler);
80 }
81 
82 void SetSignalHandler(const FuzzingOptions& Options) {
83   if (Options.UnitTimeoutSec > 0)
84     SetTimer(Options.UnitTimeoutSec / 2 + 1);
85   if (Options.HandleInt)
86     SetSigaction(SIGINT, InterruptHandler);
87   if (Options.HandleTerm)
88     SetSigaction(SIGTERM, InterruptHandler);
89   if (Options.HandleSegv)
90     SetSigaction(SIGSEGV, CrashHandler);
91   if (Options.HandleBus)
92     SetSigaction(SIGBUS, CrashHandler);
93   if (Options.HandleAbrt)
94     SetSigaction(SIGABRT, CrashHandler);
95   if (Options.HandleIll)
96     SetSigaction(SIGILL, CrashHandler);
97   if (Options.HandleFpe)
98     SetSigaction(SIGFPE, CrashHandler);
99   if (Options.HandleXfsz)
100     SetSigaction(SIGXFSZ, FileSizeExceedHandler);
101 }
102 
103 void SleepSeconds(int Seconds) {
104   sleep(Seconds); // Use C API to avoid coverage from instrumented libc++.
105 }
106 
107 unsigned long GetPid() { return (unsigned long)getpid(); }
108 
109 size_t GetPeakRSSMb() {
110   struct rusage usage;
111   if (getrusage(RUSAGE_SELF, &usage))
112     return 0;
113   if (LIBFUZZER_LINUX) {
114     // ru_maxrss is in KiB
115     return usage.ru_maxrss >> 10;
116   } else if (LIBFUZZER_APPLE) {
117     // ru_maxrss is in bytes
118     return usage.ru_maxrss >> 20;
119   }
120   assert(0 && "GetPeakRSSMb() is not implemented for your platform");
121   return 0;
122 }
123 
124 FILE *OpenProcessPipe(const char *Command, const char *Mode) {
125   return popen(Command, Mode);
126 }
127 
128 const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt,
129                          size_t PattLen) {
130   return memmem(Data, DataLen, Patt, PattLen);
131 }
132 
133 std::string DisassembleCmd(const std::string &FileName) {
134   return "objdump -d " + FileName;
135 }
136 
137 std::string SearchRegexCmd(const std::string &Regex) {
138   return "grep '" + Regex + "'";
139 }
140 
141 }  // namespace fuzzer
142 
143 #endif // LIBFUZZER_POSIX
144