blob: 110785d874137b3243e40807f8717ad2dbc159bf [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 (TPC.UnprotectLazyCounters(si->si_addr)) return;
41 if (upstream_segv_handler)
42 return upstream_segv_handler(sig, si, ucontext);
43 Fuzzer::StaticCrashSignalCallback();
kccda168932019-01-31 00:09:43 +000044}
45
george.karpenkov29efa6d2017-08-21 23:25:50 +000046static void CrashHandler(int, siginfo_t *, void *) {
47 Fuzzer::StaticCrashSignalCallback();
48}
49
50static void InterruptHandler(int, siginfo_t *, void *) {
51 Fuzzer::StaticInterruptCallback();
52}
53
kcc1239a992017-11-09 20:30:19 +000054static void GracefulExitHandler(int, siginfo_t *, void *) {
55 Fuzzer::StaticGracefulExitCallback();
56}
57
george.karpenkov29efa6d2017-08-21 23:25:50 +000058static void FileSizeExceedHandler(int, siginfo_t *, void *) {
59 Fuzzer::StaticFileSizeExceedCallback();
60}
61
62static void SetSigaction(int signum,
63 void (*callback)(int, siginfo_t *, void *)) {
64 struct sigaction sigact = {};
65 if (sigaction(signum, nullptr, &sigact)) {
66 Printf("libFuzzer: sigaction failed with %d\n", errno);
67 exit(1);
68 }
69 if (sigact.sa_flags & SA_SIGINFO) {
kccc0a0b1f2019-01-31 01:40:14 +000070 if (sigact.sa_sigaction) {
71 if (signum != SIGSEGV)
72 return;
73 upstream_segv_handler = sigact.sa_sigaction;
74 }
george.karpenkov29efa6d2017-08-21 23:25:50 +000075 } else {
76 if (sigact.sa_handler != SIG_DFL && sigact.sa_handler != SIG_IGN &&
77 sigact.sa_handler != SIG_ERR)
78 return;
79 }
80
81 sigact = {};
kccda168932019-01-31 00:09:43 +000082 sigact.sa_flags = SA_SIGINFO;
george.karpenkov29efa6d2017-08-21 23:25:50 +000083 sigact.sa_sigaction = callback;
84 if (sigaction(signum, &sigact, 0)) {
85 Printf("libFuzzer: sigaction failed with %d\n", errno);
86 exit(1);
87 }
88}
89
90void SetTimer(int Seconds) {
91 struct itimerval T {
92 {Seconds, 0}, { Seconds, 0 }
93 };
94 if (setitimer(ITIMER_REAL, &T, nullptr)) {
95 Printf("libFuzzer: setitimer failed with %d\n", errno);
96 exit(1);
97 }
98 SetSigaction(SIGALRM, AlarmHandler);
99}
100
kccda168932019-01-31 00:09:43 +0000101bool Mprotect(void *Ptr, size_t Size, bool AllowReadWrite) {
102 return 0 == mprotect(Ptr, Size,
103 AllowReadWrite ? (PROT_READ | PROT_WRITE) : PROT_NONE);
104}
105
george.karpenkov29efa6d2017-08-21 23:25:50 +0000106void SetSignalHandler(const FuzzingOptions& Options) {
107 if (Options.UnitTimeoutSec > 0)
108 SetTimer(Options.UnitTimeoutSec / 2 + 1);
109 if (Options.HandleInt)
110 SetSigaction(SIGINT, InterruptHandler);
111 if (Options.HandleTerm)
112 SetSigaction(SIGTERM, InterruptHandler);
113 if (Options.HandleSegv)
kccda168932019-01-31 00:09:43 +0000114 SetSigaction(SIGSEGV, SegvHandler);
george.karpenkov29efa6d2017-08-21 23:25:50 +0000115 if (Options.HandleBus)
116 SetSigaction(SIGBUS, CrashHandler);
117 if (Options.HandleAbrt)
118 SetSigaction(SIGABRT, CrashHandler);
119 if (Options.HandleIll)
120 SetSigaction(SIGILL, CrashHandler);
121 if (Options.HandleFpe)
122 SetSigaction(SIGFPE, CrashHandler);
123 if (Options.HandleXfsz)
124 SetSigaction(SIGXFSZ, FileSizeExceedHandler);
kcc1239a992017-11-09 20:30:19 +0000125 if (Options.HandleUsr1)
126 SetSigaction(SIGUSR1, GracefulExitHandler);
127 if (Options.HandleUsr2)
128 SetSigaction(SIGUSR2, GracefulExitHandler);
george.karpenkov29efa6d2017-08-21 23:25:50 +0000129}
130
131void SleepSeconds(int Seconds) {
132 sleep(Seconds); // Use C API to avoid coverage from instrumented libc++.
133}
134
135unsigned long GetPid() { return (unsigned long)getpid(); }
136
137size_t GetPeakRSSMb() {
138 struct rusage usage;
139 if (getrusage(RUSAGE_SELF, &usage))
140 return 0;
vitalybuka5f3206d2018-04-09 22:38:26 +0000141 if (LIBFUZZER_LINUX || LIBFUZZER_FREEBSD || LIBFUZZER_NETBSD ||
142 LIBFUZZER_OPENBSD) {
george.karpenkov29efa6d2017-08-21 23:25:50 +0000143 // ru_maxrss is in KiB
144 return usage.ru_maxrss >> 10;
145 } else if (LIBFUZZER_APPLE) {
146 // ru_maxrss is in bytes
147 return usage.ru_maxrss >> 20;
148 }
149 assert(0 && "GetPeakRSSMb() is not implemented for your platform");
150 return 0;
151}
152
153FILE *OpenProcessPipe(const char *Command, const char *Mode) {
154 return popen(Command, Mode);
155}
156
157const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt,
158 size_t PattLen) {
159 return memmem(Data, DataLen, Patt, PattLen);
160}
161
162std::string DisassembleCmd(const std::string &FileName) {
163 return "objdump -d " + FileName;
164}
165
166std::string SearchRegexCmd(const std::string &Regex) {
167 return "grep '" + Regex + "'";
168}
169
170} // namespace fuzzer
171
172#endif // LIBFUZZER_POSIX