blob: cefe7ae181e7248cbae40ef9766451a12b65440f [file] [log] [blame]
george.karpenkov29efa6d2017-08-21 23:25:50 +00001//===- FuzzerUtilPosix.cpp - Misc utils for Posix. ------------------------===//
2//
chandlerc40284492019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
george.karpenkov29efa6d2017-08-21 23:25:50 +00006//
7//===----------------------------------------------------------------------===//
8// Misc utils implementation using Posix API.
9//===----------------------------------------------------------------------===//
10#include "FuzzerDefs.h"
11#if LIBFUZZER_POSIX
12#include "FuzzerIO.h"
13#include "FuzzerInternal.h"
kccc0a0b1f2019-01-31 01:40:14 +000014#include "FuzzerTracePC.h"
george.karpenkov29efa6d2017-08-21 23:25:50 +000015#include <cassert>
16#include <chrono>
17#include <cstring>
18#include <errno.h>
19#include <iomanip>
20#include <signal.h>
george.karpenkov29efa6d2017-08-21 23:25:50 +000021#include <stdio.h>
kccda168932019-01-31 00:09:43 +000022#include <sys/mman.h>
george.karpenkov29efa6d2017-08-21 23:25:50 +000023#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
kccc0a0b1f2019-01-31 01:40:14 +000036static void (*upstream_segv_handler)(int, siginfo_t *, void *);
37
38static void SegvHandler(int sig, siginfo_t *si, void *ucontext) {
kccda168932019-01-31 00:09:43 +000039 assert(si->si_signo == SIGSEGV);
kccc0a0b1f2019-01-31 01:40:14 +000040 if (upstream_segv_handler)
41 return upstream_segv_handler(sig, si, ucontext);
42 Fuzzer::StaticCrashSignalCallback();
kccda168932019-01-31 00:09:43 +000043}
44
george.karpenkov29efa6d2017-08-21 23:25:50 +000045static void CrashHandler(int, siginfo_t *, void *) {
46 Fuzzer::StaticCrashSignalCallback();
47}
48
49static void InterruptHandler(int, siginfo_t *, void *) {
50 Fuzzer::StaticInterruptCallback();
51}
52
kcc1239a992017-11-09 20:30:19 +000053static void GracefulExitHandler(int, siginfo_t *, void *) {
54 Fuzzer::StaticGracefulExitCallback();
55}
56
george.karpenkov29efa6d2017-08-21 23:25:50 +000057static void FileSizeExceedHandler(int, siginfo_t *, void *) {
58 Fuzzer::StaticFileSizeExceedCallback();
59}
60
61static void SetSigaction(int signum,
62 void (*callback)(int, siginfo_t *, void *)) {
63 struct sigaction sigact = {};
64 if (sigaction(signum, nullptr, &sigact)) {
65 Printf("libFuzzer: sigaction failed with %d\n", errno);
66 exit(1);
67 }
68 if (sigact.sa_flags & SA_SIGINFO) {
kccc0a0b1f2019-01-31 01:40:14 +000069 if (sigact.sa_sigaction) {
70 if (signum != SIGSEGV)
71 return;
72 upstream_segv_handler = sigact.sa_sigaction;
73 }
george.karpenkov29efa6d2017-08-21 23:25:50 +000074 } else {
75 if (sigact.sa_handler != SIG_DFL && sigact.sa_handler != SIG_IGN &&
76 sigact.sa_handler != SIG_ERR)
77 return;
78 }
79
80 sigact = {};
kccda168932019-01-31 00:09:43 +000081 sigact.sa_flags = SA_SIGINFO;
george.karpenkov29efa6d2017-08-21 23:25:50 +000082 sigact.sa_sigaction = callback;
83 if (sigaction(signum, &sigact, 0)) {
84 Printf("libFuzzer: sigaction failed with %d\n", errno);
85 exit(1);
86 }
87}
88
89void SetTimer(int Seconds) {
90 struct itimerval T {
91 {Seconds, 0}, { Seconds, 0 }
92 };
93 if (setitimer(ITIMER_REAL, &T, nullptr)) {
94 Printf("libFuzzer: setitimer failed with %d\n", errno);
95 exit(1);
96 }
97 SetSigaction(SIGALRM, AlarmHandler);
98}
99
100void SetSignalHandler(const FuzzingOptions& Options) {
101 if (Options.UnitTimeoutSec > 0)
102 SetTimer(Options.UnitTimeoutSec / 2 + 1);
103 if (Options.HandleInt)
104 SetSigaction(SIGINT, InterruptHandler);
105 if (Options.HandleTerm)
106 SetSigaction(SIGTERM, InterruptHandler);
107 if (Options.HandleSegv)
kccda168932019-01-31 00:09:43 +0000108 SetSigaction(SIGSEGV, SegvHandler);
george.karpenkov29efa6d2017-08-21 23:25:50 +0000109 if (Options.HandleBus)
110 SetSigaction(SIGBUS, CrashHandler);
111 if (Options.HandleAbrt)
112 SetSigaction(SIGABRT, CrashHandler);
113 if (Options.HandleIll)
114 SetSigaction(SIGILL, CrashHandler);
115 if (Options.HandleFpe)
116 SetSigaction(SIGFPE, CrashHandler);
117 if (Options.HandleXfsz)
118 SetSigaction(SIGXFSZ, FileSizeExceedHandler);
kcc1239a992017-11-09 20:30:19 +0000119 if (Options.HandleUsr1)
120 SetSigaction(SIGUSR1, GracefulExitHandler);
121 if (Options.HandleUsr2)
122 SetSigaction(SIGUSR2, GracefulExitHandler);
george.karpenkov29efa6d2017-08-21 23:25:50 +0000123}
124
125void SleepSeconds(int Seconds) {
126 sleep(Seconds); // Use C API to avoid coverage from instrumented libc++.
127}
128
129unsigned long GetPid() { return (unsigned long)getpid(); }
130
131size_t GetPeakRSSMb() {
132 struct rusage usage;
133 if (getrusage(RUSAGE_SELF, &usage))
134 return 0;
vitalybuka5f3206d2018-04-09 22:38:26 +0000135 if (LIBFUZZER_LINUX || LIBFUZZER_FREEBSD || LIBFUZZER_NETBSD ||
136 LIBFUZZER_OPENBSD) {
george.karpenkov29efa6d2017-08-21 23:25:50 +0000137 // ru_maxrss is in KiB
138 return usage.ru_maxrss >> 10;
139 } else if (LIBFUZZER_APPLE) {
140 // ru_maxrss is in bytes
141 return usage.ru_maxrss >> 20;
142 }
143 assert(0 && "GetPeakRSSMb() is not implemented for your platform");
144 return 0;
145}
146
147FILE *OpenProcessPipe(const char *Command, const char *Mode) {
148 return popen(Command, Mode);
149}
150
151const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt,
152 size_t PattLen) {
153 return memmem(Data, DataLen, Patt, PattLen);
154}
155
156std::string DisassembleCmd(const std::string &FileName) {
157 return "objdump -d " + FileName;
158}
159
160std::string SearchRegexCmd(const std::string &Regex) {
161 return "grep '" + Regex + "'";
162}
163
164} // namespace fuzzer
165
166#endif // LIBFUZZER_POSIX