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
)
81 sigact
.sa_flags
= SA_SIGINFO
;
82 sigact
.sa_sigaction
= callback
;
83 if (sigaction(signum
, &sigact
, 0)) {
84 Printf("libFuzzer: sigaction failed with %d\n", errno
);
89 // Return true on success, false otherwise.
90 bool ExecuteCommand(const Command
&Cmd
, std::string
*CmdOutput
) {
91 FILE *Pipe
= popen(Cmd
.toString().c_str(), "r");
97 while (fgets(TmpBuffer
, sizeof(TmpBuffer
), Pipe
))
98 CmdOutput
->append(TmpBuffer
);
100 return pclose(Pipe
) == 0;
103 void SetTimer(int Seconds
) {
105 {Seconds
, 0}, { Seconds
, 0 }
107 if (setitimer(ITIMER_REAL
, &T
, nullptr)) {
108 Printf("libFuzzer: setitimer failed with %d\n", errno
);
111 SetSigaction(SIGALRM
, AlarmHandler
);
114 void SetSignalHandler(const FuzzingOptions
& Options
) {
115 // setitimer is not implemented in emscripten.
116 if (Options
.UnitTimeoutSec
> 0 && !LIBFUZZER_EMSCRIPTEN
)
117 SetTimer(Options
.UnitTimeoutSec
/ 2 + 1);
118 if (Options
.HandleInt
)
119 SetSigaction(SIGINT
, InterruptHandler
);
120 if (Options
.HandleTerm
)
121 SetSigaction(SIGTERM
, InterruptHandler
);
122 if (Options
.HandleSegv
)
123 SetSigaction(SIGSEGV
, SegvHandler
);
124 if (Options
.HandleBus
)
125 SetSigaction(SIGBUS
, CrashHandler
);
126 if (Options
.HandleAbrt
)
127 SetSigaction(SIGABRT
, CrashHandler
);
128 if (Options
.HandleIll
)
129 SetSigaction(SIGILL
, CrashHandler
);
130 if (Options
.HandleFpe
)
131 SetSigaction(SIGFPE
, CrashHandler
);
132 if (Options
.HandleXfsz
)
133 SetSigaction(SIGXFSZ
, FileSizeExceedHandler
);
134 if (Options
.HandleUsr1
)
135 SetSigaction(SIGUSR1
, GracefulExitHandler
);
136 if (Options
.HandleUsr2
)
137 SetSigaction(SIGUSR2
, GracefulExitHandler
);
140 void SleepSeconds(int Seconds
) {
141 sleep(Seconds
); // Use C API to avoid coverage from instrumented libc++.
144 unsigned long GetPid() { return (unsigned long)getpid(); }
146 size_t GetPeakRSSMb() {
148 if (getrusage(RUSAGE_SELF
, &usage
))
150 if (LIBFUZZER_LINUX
|| LIBFUZZER_FREEBSD
|| LIBFUZZER_NETBSD
||
151 LIBFUZZER_OPENBSD
|| LIBFUZZER_EMSCRIPTEN
) {
152 // ru_maxrss is in KiB
153 return usage
.ru_maxrss
>> 10;
154 } else if (LIBFUZZER_APPLE
) {
155 // ru_maxrss is in bytes
156 return usage
.ru_maxrss
>> 20;
158 assert(0 && "GetPeakRSSMb() is not implemented for your platform");
162 FILE *OpenProcessPipe(const char *Command
, const char *Mode
) {
163 return popen(Command
, Mode
);
166 int CloseProcessPipe(FILE *F
) {
170 const void *SearchMemory(const void *Data
, size_t DataLen
, const void *Patt
,
172 return memmem(Data
, DataLen
, Patt
, PattLen
);
175 std::string
DisassembleCmd(const std::string
&FileName
) {
176 return "objdump -d " + FileName
;
179 std::string
SearchRegexCmd(const std::string
&Regex
) {
180 return "grep '" + Regex
+ "'";
183 } // namespace fuzzer
185 #endif // LIBFUZZER_POSIX