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
30namespace fuzzer {
31
32static void AlarmHandler(int, siginfo_t *, void *) {
33  Fuzzer::StaticAlarmCallback();
34}
35
36static void CrashHandler(int, siginfo_t *, void *) {
37  Fuzzer::StaticCrashSignalCallback();
38}
39
40static void InterruptHandler(int, siginfo_t *, void *) {
41  Fuzzer::StaticInterruptCallback();
42}
43
44static 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
55void 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
66void 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
85void SleepSeconds(int Seconds) {
86  sleep(Seconds); // Use C API to avoid coverage from instrumented libc++.
87}
88
89unsigned long GetPid() { return (unsigned long)getpid(); }
90
91size_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
106FILE *OpenProcessPipe(const char *Command, const char *Mode) {
107  return popen(Command, Mode);
108}
109
110const 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