blob: 56b10ffa6685d11148ab7b6425c3768255380927 [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"
14#include <cassert>
15#include <chrono>
16#include <cstring>
17#include <errno.h>
18#include <iomanip>
19#include <signal.h>
george.karpenkov29efa6d2017-08-21 23:25:50 +000020#include <stdio.h>
kccda168932019-01-31 00:09:43 +000021#include <sys/mman.h>
george.karpenkov29efa6d2017-08-21 23:25:50 +000022#include <sys/resource.h>
23#include <sys/syscall.h>
24#include <sys/time.h>
25#include <sys/types.h>
26#include <thread>
27#include <unistd.h>
28
29namespace fuzzer {
30
31static void AlarmHandler(int, siginfo_t *, void *) {
32 Fuzzer::StaticAlarmCallback();
33}
34
kccda168932019-01-31 00:09:43 +000035static void SegvHandler(int, siginfo_t *si, void *) {
36 assert(si->si_signo == SIGSEGV);
37 Fuzzer::StaticSegvSignalCallback(si->si_addr);
38}
39
george.karpenkov29efa6d2017-08-21 23:25:50 +000040static void CrashHandler(int, siginfo_t *, void *) {
41 Fuzzer::StaticCrashSignalCallback();
42}
43
44static void InterruptHandler(int, siginfo_t *, void *) {
45 Fuzzer::StaticInterruptCallback();
46}
47
kcc1239a992017-11-09 20:30:19 +000048static void GracefulExitHandler(int, siginfo_t *, void *) {
49 Fuzzer::StaticGracefulExitCallback();
50}
51
george.karpenkov29efa6d2017-08-21 23:25:50 +000052static void FileSizeExceedHandler(int, siginfo_t *, void *) {
53 Fuzzer::StaticFileSizeExceedCallback();
54}
55
56static void SetSigaction(int signum,
57 void (*callback)(int, siginfo_t *, void *)) {
58 struct sigaction sigact = {};
59 if (sigaction(signum, nullptr, &sigact)) {
60 Printf("libFuzzer: sigaction failed with %d\n", errno);
61 exit(1);
62 }
63 if (sigact.sa_flags & SA_SIGINFO) {
64 if (sigact.sa_sigaction)
65 return;
66 } else {
67 if (sigact.sa_handler != SIG_DFL && sigact.sa_handler != SIG_IGN &&
68 sigact.sa_handler != SIG_ERR)
69 return;
70 }
71
72 sigact = {};
kccda168932019-01-31 00:09:43 +000073 sigact.sa_flags = SA_SIGINFO;
george.karpenkov29efa6d2017-08-21 23:25:50 +000074 sigact.sa_sigaction = callback;
75 if (sigaction(signum, &sigact, 0)) {
76 Printf("libFuzzer: sigaction failed with %d\n", errno);
77 exit(1);
78 }
79}
80
81void SetTimer(int Seconds) {
82 struct itimerval T {
83 {Seconds, 0}, { Seconds, 0 }
84 };
85 if (setitimer(ITIMER_REAL, &T, nullptr)) {
86 Printf("libFuzzer: setitimer failed with %d\n", errno);
87 exit(1);
88 }
89 SetSigaction(SIGALRM, AlarmHandler);
90}
91
kccda168932019-01-31 00:09:43 +000092bool Mprotect(void *Ptr, size_t Size, bool AllowReadWrite) {
93 return 0 == mprotect(Ptr, Size,
94 AllowReadWrite ? (PROT_READ | PROT_WRITE) : PROT_NONE);
95}
96
george.karpenkov29efa6d2017-08-21 23:25:50 +000097void SetSignalHandler(const FuzzingOptions& Options) {
98 if (Options.UnitTimeoutSec > 0)
99 SetTimer(Options.UnitTimeoutSec / 2 + 1);
100 if (Options.HandleInt)
101 SetSigaction(SIGINT, InterruptHandler);
102 if (Options.HandleTerm)
103 SetSigaction(SIGTERM, InterruptHandler);
104 if (Options.HandleSegv)
kccda168932019-01-31 00:09:43 +0000105 SetSigaction(SIGSEGV, SegvHandler);
george.karpenkov29efa6d2017-08-21 23:25:50 +0000106 if (Options.HandleBus)
107 SetSigaction(SIGBUS, CrashHandler);
108 if (Options.HandleAbrt)
109 SetSigaction(SIGABRT, CrashHandler);
110 if (Options.HandleIll)
111 SetSigaction(SIGILL, CrashHandler);
112 if (Options.HandleFpe)
113 SetSigaction(SIGFPE, CrashHandler);
114 if (Options.HandleXfsz)
115 SetSigaction(SIGXFSZ, FileSizeExceedHandler);
kcc1239a992017-11-09 20:30:19 +0000116 if (Options.HandleUsr1)
117 SetSigaction(SIGUSR1, GracefulExitHandler);
118 if (Options.HandleUsr2)
119 SetSigaction(SIGUSR2, GracefulExitHandler);
george.karpenkov29efa6d2017-08-21 23:25:50 +0000120}
121
122void SleepSeconds(int Seconds) {
123 sleep(Seconds); // Use C API to avoid coverage from instrumented libc++.
124}
125
126unsigned long GetPid() { return (unsigned long)getpid(); }
127
128size_t GetPeakRSSMb() {
129 struct rusage usage;
130 if (getrusage(RUSAGE_SELF, &usage))
131 return 0;
vitalybuka5f3206d2018-04-09 22:38:26 +0000132 if (LIBFUZZER_LINUX || LIBFUZZER_FREEBSD || LIBFUZZER_NETBSD ||
133 LIBFUZZER_OPENBSD) {
george.karpenkov29efa6d2017-08-21 23:25:50 +0000134 // ru_maxrss is in KiB
135 return usage.ru_maxrss >> 10;
136 } else if (LIBFUZZER_APPLE) {
137 // ru_maxrss is in bytes
138 return usage.ru_maxrss >> 20;
139 }
140 assert(0 && "GetPeakRSSMb() is not implemented for your platform");
141 return 0;
142}
143
144FILE *OpenProcessPipe(const char *Command, const char *Mode) {
145 return popen(Command, Mode);
146}
147
148const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt,
149 size_t PattLen) {
150 return memmem(Data, DataLen, Patt, PattLen);
151}
152
153std::string DisassembleCmd(const std::string &FileName) {
154 return "objdump -d " + FileName;
155}
156
157std::string SearchRegexCmd(const std::string &Regex) {
158 return "grep '" + Regex + "'";
159}
160
161} // namespace fuzzer
162
163#endif // LIBFUZZER_POSIX