brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.5 KiB · ae22ecf Raw
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