about summary refs log tree commit diff
path: root/custom_mutators/libfuzzer/FuzzerUtilPosix.cpp
blob: 372bfa5e577e4467eb3399adba5985ff11a0a9c7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
//===- 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 "FuzzerPlatform.h"
#if LIBFUZZER_POSIX
  #include "FuzzerIO.h"
  #include "FuzzerInternal.h"
  #include "FuzzerTracePC.h"
  #include <cassert>
  #include <chrono>
  #include <cstring>
  #include <errno.h>
  #include <iomanip>
  #include <signal.h>
  #include <stdio.h>
  #include <sys/mman.h>
  #include <sys/resource.h>
  #include <sys/syscall.h>
  #include <sys/time.h>
  #include <sys/types.h>
  #include <thread>
  #include <unistd.h>

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 (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);

  }

}

// Return true on success, false otherwise.
bool ExecuteCommand(const Command &Cmd, std::string *CmdOutput) {

  FILE *Pipe = popen(Cmd.toString().c_str(), "r");
  if (!Pipe) return false;

  if (CmdOutput) {

    char TmpBuffer[128];
    while (fgets(TmpBuffer, sizeof(TmpBuffer), Pipe))
      CmdOutput->append(TmpBuffer);

  }

  return pclose(Pipe) == 0;

}

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) {

  // setitimer is not implemented in emscripten.
  if (Options.HandleAlrm && Options.UnitTimeoutSec > 0 && !LIBFUZZER_EMSCRIPTEN)
    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 || LIBFUZZER_EMSCRIPTEN) {

    // 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);

}

int CloseProcessPipe(FILE *F) {

  return pclose(F);

}

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