1326943Sdim//===- FuzzerUtilPosix.cpp - Misc utils for Posix. ------------------------===//
2326943Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6326943Sdim//
7326943Sdim//===----------------------------------------------------------------------===//
8326943Sdim// Misc utils implementation using Posix API.
9326943Sdim//===----------------------------------------------------------------------===//
10326943Sdim#include "FuzzerDefs.h"
11326943Sdim#if LIBFUZZER_POSIX
12326943Sdim#include "FuzzerIO.h"
13326943Sdim#include "FuzzerInternal.h"
14353358Sdim#include "FuzzerTracePC.h"
15326943Sdim#include <cassert>
16326943Sdim#include <chrono>
17326943Sdim#include <cstring>
18326943Sdim#include <errno.h>
19326943Sdim#include <iomanip>
20326943Sdim#include <signal.h>
21326943Sdim#include <stdio.h>
22353358Sdim#include <sys/mman.h>
23326943Sdim#include <sys/resource.h>
24326943Sdim#include <sys/syscall.h>
25326943Sdim#include <sys/time.h>
26326943Sdim#include <sys/types.h>
27326943Sdim#include <thread>
28326943Sdim#include <unistd.h>
29326943Sdim
30326943Sdimnamespace fuzzer {
31326943Sdim
32326943Sdimstatic void AlarmHandler(int, siginfo_t *, void *) {
33326943Sdim  Fuzzer::StaticAlarmCallback();
34326943Sdim}
35326943Sdim
36353358Sdimstatic void (*upstream_segv_handler)(int, siginfo_t *, void *);
37353358Sdim
38353358Sdimstatic void SegvHandler(int sig, siginfo_t *si, void *ucontext) {
39353358Sdim  assert(si->si_signo == SIGSEGV);
40353358Sdim  if (upstream_segv_handler)
41353358Sdim    return upstream_segv_handler(sig, si, ucontext);
42353358Sdim  Fuzzer::StaticCrashSignalCallback();
43353358Sdim}
44353358Sdim
45326943Sdimstatic void CrashHandler(int, siginfo_t *, void *) {
46326943Sdim  Fuzzer::StaticCrashSignalCallback();
47326943Sdim}
48326943Sdim
49326943Sdimstatic void InterruptHandler(int, siginfo_t *, void *) {
50326943Sdim  Fuzzer::StaticInterruptCallback();
51326943Sdim}
52326943Sdim
53326943Sdimstatic void GracefulExitHandler(int, siginfo_t *, void *) {
54326943Sdim  Fuzzer::StaticGracefulExitCallback();
55326943Sdim}
56326943Sdim
57326943Sdimstatic void FileSizeExceedHandler(int, siginfo_t *, void *) {
58326943Sdim  Fuzzer::StaticFileSizeExceedCallback();
59326943Sdim}
60326943Sdim
61326943Sdimstatic void SetSigaction(int signum,
62326943Sdim                         void (*callback)(int, siginfo_t *, void *)) {
63326943Sdim  struct sigaction sigact = {};
64326943Sdim  if (sigaction(signum, nullptr, &sigact)) {
65326943Sdim    Printf("libFuzzer: sigaction failed with %d\n", errno);
66326943Sdim    exit(1);
67326943Sdim  }
68326943Sdim  if (sigact.sa_flags & SA_SIGINFO) {
69353358Sdim    if (sigact.sa_sigaction) {
70353358Sdim      if (signum != SIGSEGV)
71353358Sdim        return;
72353358Sdim      upstream_segv_handler = sigact.sa_sigaction;
73353358Sdim    }
74326943Sdim  } else {
75326943Sdim    if (sigact.sa_handler != SIG_DFL && sigact.sa_handler != SIG_IGN &&
76326943Sdim        sigact.sa_handler != SIG_ERR)
77326943Sdim      return;
78326943Sdim  }
79326943Sdim
80326943Sdim  sigact = {};
81353358Sdim  sigact.sa_flags = SA_SIGINFO;
82326943Sdim  sigact.sa_sigaction = callback;
83326943Sdim  if (sigaction(signum, &sigact, 0)) {
84326943Sdim    Printf("libFuzzer: sigaction failed with %d\n", errno);
85326943Sdim    exit(1);
86326943Sdim  }
87326943Sdim}
88326943Sdim
89326943Sdimvoid SetTimer(int Seconds) {
90326943Sdim  struct itimerval T {
91326943Sdim    {Seconds, 0}, { Seconds, 0 }
92326943Sdim  };
93326943Sdim  if (setitimer(ITIMER_REAL, &T, nullptr)) {
94326943Sdim    Printf("libFuzzer: setitimer failed with %d\n", errno);
95326943Sdim    exit(1);
96326943Sdim  }
97326943Sdim  SetSigaction(SIGALRM, AlarmHandler);
98326943Sdim}
99326943Sdim
100326943Sdimvoid SetSignalHandler(const FuzzingOptions& Options) {
101360784Sdim  // setitimer is not implemented in emscripten.
102360784Sdim  if (Options.UnitTimeoutSec > 0 && !LIBFUZZER_EMSCRIPTEN)
103326943Sdim    SetTimer(Options.UnitTimeoutSec / 2 + 1);
104326943Sdim  if (Options.HandleInt)
105326943Sdim    SetSigaction(SIGINT, InterruptHandler);
106326943Sdim  if (Options.HandleTerm)
107326943Sdim    SetSigaction(SIGTERM, InterruptHandler);
108326943Sdim  if (Options.HandleSegv)
109353358Sdim    SetSigaction(SIGSEGV, SegvHandler);
110326943Sdim  if (Options.HandleBus)
111326943Sdim    SetSigaction(SIGBUS, CrashHandler);
112326943Sdim  if (Options.HandleAbrt)
113326943Sdim    SetSigaction(SIGABRT, CrashHandler);
114326943Sdim  if (Options.HandleIll)
115326943Sdim    SetSigaction(SIGILL, CrashHandler);
116326943Sdim  if (Options.HandleFpe)
117326943Sdim    SetSigaction(SIGFPE, CrashHandler);
118326943Sdim  if (Options.HandleXfsz)
119326943Sdim    SetSigaction(SIGXFSZ, FileSizeExceedHandler);
120326943Sdim  if (Options.HandleUsr1)
121326943Sdim    SetSigaction(SIGUSR1, GracefulExitHandler);
122326943Sdim  if (Options.HandleUsr2)
123326943Sdim    SetSigaction(SIGUSR2, GracefulExitHandler);
124326943Sdim}
125326943Sdim
126326943Sdimvoid SleepSeconds(int Seconds) {
127326943Sdim  sleep(Seconds); // Use C API to avoid coverage from instrumented libc++.
128326943Sdim}
129326943Sdim
130326943Sdimunsigned long GetPid() { return (unsigned long)getpid(); }
131326943Sdim
132326943Sdimsize_t GetPeakRSSMb() {
133326943Sdim  struct rusage usage;
134326943Sdim  if (getrusage(RUSAGE_SELF, &usage))
135326943Sdim    return 0;
136336817Sdim  if (LIBFUZZER_LINUX || LIBFUZZER_FREEBSD || LIBFUZZER_NETBSD ||
137360784Sdim      LIBFUZZER_OPENBSD || LIBFUZZER_EMSCRIPTEN) {
138326943Sdim    // ru_maxrss is in KiB
139326943Sdim    return usage.ru_maxrss >> 10;
140326943Sdim  } else if (LIBFUZZER_APPLE) {
141326943Sdim    // ru_maxrss is in bytes
142326943Sdim    return usage.ru_maxrss >> 20;
143326943Sdim  }
144326943Sdim  assert(0 && "GetPeakRSSMb() is not implemented for your platform");
145326943Sdim  return 0;
146326943Sdim}
147326943Sdim
148326943SdimFILE *OpenProcessPipe(const char *Command, const char *Mode) {
149326943Sdim  return popen(Command, Mode);
150326943Sdim}
151326943Sdim
152326943Sdimconst void *SearchMemory(const void *Data, size_t DataLen, const void *Patt,
153326943Sdim                         size_t PattLen) {
154326943Sdim  return memmem(Data, DataLen, Patt, PattLen);
155326943Sdim}
156326943Sdim
157326943Sdimstd::string DisassembleCmd(const std::string &FileName) {
158326943Sdim  return "objdump -d " + FileName;
159326943Sdim}
160326943Sdim
161326943Sdimstd::string SearchRegexCmd(const std::string &Regex) {
162326943Sdim  return "grep '" + Regex + "'";
163326943Sdim}
164326943Sdim
165326943Sdim}  // namespace fuzzer
166326943Sdim
167326943Sdim#endif // LIBFUZZER_POSIX
168