1 //===- FuzzerUtilPosix.cpp - Misc utils for Posix. ------------------------===//
3 // 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
7 //===----------------------------------------------------------------------===//
8 // Misc utils implementation using Posix API.
9 //===----------------------------------------------------------------------===//
10 #include "FuzzerPlatform.h"
13 #include "FuzzerInternal.h"
14 #include "FuzzerTracePC.h"
23 #include <sys/resource.h>
24 #include <sys/syscall.h>
26 #include <sys/types.h>
32 static void AlarmHandler(int, siginfo_t
*, void *) {
33 Fuzzer::StaticAlarmCallback();
36 static void (*upstream_segv_handler
)(int, siginfo_t
*, void *);
38 static void SegvHandler(int sig
, siginfo_t
*si
, void *ucontext
) {
39 assert(si
->si_signo
== SIGSEGV
);
40 if (upstream_segv_handler
)
41 return upstream_segv_handler(sig
, si
, ucontext
);
42 Fuzzer::StaticCrashSignalCallback();
45 static void CrashHandler(int, siginfo_t
*, void *) {
46 Fuzzer::StaticCrashSignalCallback();
49 static void InterruptHandler(int, siginfo_t
*, void *) {
50 Fuzzer::StaticInterruptCallback();
53 static void GracefulExitHandler(int, siginfo_t
*, void *) {
54 Fuzzer::StaticGracefulExitCallback();
57 static void FileSizeExceedHandler(int, siginfo_t
*, void *) {
58 Fuzzer::StaticFileSizeExceedCallback();
61 static 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
);
68 if (sigact
.sa_flags
& SA_SIGINFO
) {
69 if (sigact
.sa_sigaction
) {
70 if (signum
!= SIGSEGV
)
72 upstream_segv_handler
= sigact
.sa_sigaction
;
75 if (sigact
.sa_handler
!= SIG_DFL
&& sigact
.sa_handler
!= SIG_IGN
&&
76 sigact
.sa_handler
!= SIG_ERR
)
80 struct sigaction new_sigact
= {};
81 // Address sanitizer needs SA_ONSTACK (causing the signal handler to run on a
82 // dedicated stack) in order to be able to detect stack overflows; keep the
84 new_sigact
.sa_flags
= SA_SIGINFO
| (sigact
.sa_flags
& SA_ONSTACK
);
85 new_sigact
.sa_sigaction
= callback
;
86 if (sigaction(signum
, &new_sigact
, nullptr)) {
87 Printf("libFuzzer: sigaction failed with %d\n", errno
);
92 // Return true on success, false otherwise.
93 bool ExecuteCommand(const Command
&Cmd
, std::string
*CmdOutput
) {
94 FILE *Pipe
= popen(Cmd
.toString().c_str(), "r");
100 while (fgets(TmpBuffer
, sizeof(TmpBuffer
), Pipe
))
101 CmdOutput
->append(TmpBuffer
);
103 return pclose(Pipe
) == 0;
106 void SetTimer(int Seconds
) {
108 {Seconds
, 0}, { Seconds
, 0 }
110 if (setitimer(ITIMER_REAL
, &T
, nullptr)) {
111 Printf("libFuzzer: setitimer failed with %d\n", errno
);
114 SetSigaction(SIGALRM
, AlarmHandler
);
117 void SetSignalHandler(const FuzzingOptions
& Options
) {
118 // setitimer is not implemented in emscripten.
119 if (Options
.HandleAlrm
&& Options
.UnitTimeoutSec
> 0 && !LIBFUZZER_EMSCRIPTEN
)
120 SetTimer(Options
.UnitTimeoutSec
/ 2 + 1);
121 if (Options
.HandleInt
)
122 SetSigaction(SIGINT
, InterruptHandler
);
123 if (Options
.HandleTerm
)
124 SetSigaction(SIGTERM
, InterruptHandler
);
125 if (Options
.HandleSegv
)
126 SetSigaction(SIGSEGV
, SegvHandler
);
127 if (Options
.HandleBus
)
128 SetSigaction(SIGBUS
, CrashHandler
);
129 if (Options
.HandleAbrt
)
130 SetSigaction(SIGABRT
, CrashHandler
);
131 if (Options
.HandleIll
)
132 SetSigaction(SIGILL
, CrashHandler
);
133 if (Options
.HandleFpe
)
134 SetSigaction(SIGFPE
, CrashHandler
);
135 if (Options
.HandleXfsz
)
136 SetSigaction(SIGXFSZ
, FileSizeExceedHandler
);
137 if (Options
.HandleUsr1
)
138 SetSigaction(SIGUSR1
, GracefulExitHandler
);
139 if (Options
.HandleUsr2
)
140 SetSigaction(SIGUSR2
, GracefulExitHandler
);
143 void SleepSeconds(int Seconds
) {
144 sleep(Seconds
); // Use C API to avoid coverage from instrumented libc++.
147 unsigned long GetPid() { return (unsigned long)getpid(); }
149 size_t GetPeakRSSMb() {
151 if (getrusage(RUSAGE_SELF
, &usage
))
153 if (LIBFUZZER_LINUX
|| LIBFUZZER_FREEBSD
|| LIBFUZZER_NETBSD
||
154 LIBFUZZER_EMSCRIPTEN
) {
155 // ru_maxrss is in KiB
156 return usage
.ru_maxrss
>> 10;
157 } else if (LIBFUZZER_APPLE
) {
158 // ru_maxrss is in bytes
159 return usage
.ru_maxrss
>> 20;
161 assert(0 && "GetPeakRSSMb() is not implemented for your platform");
165 FILE *OpenProcessPipe(const char *Command
, const char *Mode
) {
166 return popen(Command
, Mode
);
169 int CloseProcessPipe(FILE *F
) {
173 const void *SearchMemory(const void *Data
, size_t DataLen
, const void *Patt
,
175 return memmem(Data
, DataLen
, Patt
, PattLen
);
178 std::string
DisassembleCmd(const std::string
&FileName
) {
179 return "objdump -d " + FileName
;
182 std::string
SearchRegexCmd(const std::string
&Regex
) {
183 return "grep '" + Regex
+ "'";
187 static size_t PageSizeCached
= sysconf(_SC_PAGESIZE
);
188 return PageSizeCached
;
191 } // namespace fuzzer
193 #endif // LIBFUZZER_POSIX