196 lines · cpp
1//===- FuzzerUtilPosix.cpp - Misc utils for Posix. ------------------------===//2//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-exception6//7//===----------------------------------------------------------------------===//8// Misc utils implementation using Posix API.9//===----------------------------------------------------------------------===//10#include "FuzzerPlatform.h"11#if LIBFUZZER_POSIX12#include "FuzzerIO.h"13#include "FuzzerInternal.h"14#include "FuzzerTracePC.h"15#include <cassert>16#include <chrono>17#include <cstring>18#include <errno.h>19#include <iomanip>20#include <signal.h>21#include <stdio.h>22#include <sys/mman.h>23#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 36static void (*upstream_segv_handler)(int, siginfo_t *, void *);37 38static 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();43}44 45static void CrashHandler(int, siginfo_t *, void *) {46 Fuzzer::StaticCrashSignalCallback();47}48 49static void InterruptHandler(int, siginfo_t *, void *) {50 Fuzzer::StaticInterruptCallback();51}52 53static void GracefulExitHandler(int, siginfo_t *, void *) {54 Fuzzer::StaticGracefulExitCallback();55}56 57static 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) {69 if (sigact.sa_sigaction) {70 if (signum != SIGSEGV)71 return;72 upstream_segv_handler = sigact.sa_sigaction;73 }74 } else {75 if (sigact.sa_handler != SIG_DFL && sigact.sa_handler != SIG_IGN &&76 sigact.sa_handler != SIG_ERR)77 return;78 }79 80 struct sigaction new_sigact = {};81 // Address sanitizer needs SA_ONSTACK (causing the signal handler to run on a82 // dedicated stack) in order to be able to detect stack overflows; keep the83 // flag if it's set.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);88 exit(1);89 }90}91 92// Return true on success, false otherwise.93bool ExecuteCommand(const Command &Cmd, std::string *CmdOutput) {94 FILE *Pipe = popen(Cmd.toString().c_str(), "r");95 if (!Pipe)96 return false;97 98 if (CmdOutput) {99 char TmpBuffer[128];100 while (fgets(TmpBuffer, sizeof(TmpBuffer), Pipe))101 CmdOutput->append(TmpBuffer);102 }103 return pclose(Pipe) == 0;104}105 106void SetTimer(int Seconds) {107 struct itimerval T {108 {Seconds, 0}, { Seconds, 0 }109 };110 if (setitimer(ITIMER_REAL, &T, nullptr)) {111 Printf("libFuzzer: setitimer failed with %d\n", errno);112 exit(1);113 }114 SetSigaction(SIGALRM, AlarmHandler);115}116 117void 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.HandleTrap)136 SetSigaction(SIGTRAP, CrashHandler);137 if (Options.HandleXfsz)138 SetSigaction(SIGXFSZ, FileSizeExceedHandler);139 if (Options.HandleUsr1)140 SetSigaction(SIGUSR1, GracefulExitHandler);141 if (Options.HandleUsr2)142 SetSigaction(SIGUSR2, GracefulExitHandler);143}144 145void SleepSeconds(int Seconds) {146 sleep(Seconds); // Use C API to avoid coverage from instrumented libc++.147}148 149unsigned long GetPid() { return (unsigned long)getpid(); }150 151size_t GetPeakRSSMb() {152 struct rusage usage;153 if (getrusage(RUSAGE_SELF, &usage))154 return 0;155 if (LIBFUZZER_LINUX || LIBFUZZER_FREEBSD || LIBFUZZER_NETBSD ||156 LIBFUZZER_EMSCRIPTEN) {157 // ru_maxrss is in KiB158 return usage.ru_maxrss >> 10;159 } else if (LIBFUZZER_APPLE) {160 // ru_maxrss is in bytes161 return usage.ru_maxrss >> 20;162 }163 assert(0 && "GetPeakRSSMb() is not implemented for your platform");164 return 0;165}166 167FILE *OpenProcessPipe(const char *Command, const char *Mode) {168 return popen(Command, Mode);169}170 171int CloseProcessPipe(FILE *F) {172 return pclose(F);173}174 175const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt,176 size_t PattLen) {177 return memmem(Data, DataLen, Patt, PattLen);178}179 180std::string DisassembleCmd(const std::string &FileName) {181 return "objdump -d " + FileName;182}183 184std::string SearchRegexCmd(const std::string &Regex) {185 return "grep '" + Regex + "'";186}187 188size_t PageSize() {189 static size_t PageSizeCached = sysconf(_SC_PAGESIZE);190 return PageSizeCached;191}192 193} // namespace fuzzer194 195#endif // LIBFUZZER_POSIX196