"Fossies" - the Fresh Open Source Software Archive

Member "honggfuzz-2.2/posix/arch.c" (23 Apr 2020, 8219 Bytes) of package /linux/privat/honggfuzz-2.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "arch.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.1_vs_2.2.

    1 /*
    2  *
    3  * honggfuzz - architecture dependent code (POSIX / SIGNAL)
    4  * -----------------------------------------
    5  *
    6  * Author: Robert Swiecki <swiecki@google.com>
    7  *
    8  * Copyright 2010-2018 by Google Inc. All Rights Reserved.
    9  *
   10  * Licensed under the Apache License, Version 2.0 (the "License"); you may
   11  * not use this file except in compliance with the License. You may obtain
   12  * a copy of the License at
   13  *
   14  * http://www.apache.org/licenses/LICENSE-2.0
   15  *
   16  * Unless required by applicable law or agreed to in writing, software
   17  * distributed under the License is distributed on an "AS IS" BASIS,
   18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
   19  * implied. See the License for the specific language governing
   20  * permissions and limitations under the License.
   21  *
   22  */
   23 
   24 #include "arch.h"
   25 
   26 #include <ctype.h>
   27 #include <errno.h>
   28 #include <fcntl.h>
   29 #include <locale.h>
   30 #include <poll.h>
   31 #include <signal.h>
   32 #include <stdio.h>
   33 #include <stdlib.h>
   34 #include <string.h>
   35 #include <sys/cdefs.h>
   36 #include <sys/resource.h>
   37 #include <sys/stat.h>
   38 #include <sys/time.h>
   39 #include <sys/types.h>
   40 #include <sys/wait.h>
   41 #include <time.h>
   42 #include <unistd.h>
   43 
   44 #include "fuzz.h"
   45 #include "libhfcommon/common.h"
   46 #include "libhfcommon/files.h"
   47 #include "libhfcommon/log.h"
   48 #include "libhfcommon/util.h"
   49 #include "report.h"
   50 #include "sanitizers.h"
   51 #include "subproc.h"
   52 
   53 struct {
   54     bool important;
   55     const char* descr;
   56 } arch_sigs[NSIG] = {
   57     [0 ...(NSIG - 1)].important = false,
   58     [0 ...(NSIG - 1)].descr = "UNKNOWN",
   59 
   60     [SIGILL].important = true,
   61     [SIGILL].descr = "SIGILL",
   62 
   63     [SIGFPE].important = true,
   64     [SIGFPE].descr = "SIGFPE",
   65 
   66     [SIGSEGV].important = true,
   67     [SIGSEGV].descr = "SIGSEGV",
   68 
   69     [SIGBUS].important = true,
   70     [SIGBUS].descr = "SIGBUS",
   71 
   72     [SIGABRT].important = true,
   73     [SIGABRT].descr = "SIGABRT",
   74 
   75     /* Is affected from tmout_vtalrm flag */
   76     [SIGVTALRM].important = false,
   77     [SIGVTALRM].descr = "SIGVTALRM-TMOUT",
   78 };
   79 
   80 /*
   81  * Returns true if a process exited (so, presumably, we can delete an input
   82  * file)
   83  */
   84 static void arch_analyzeSignal(run_t* run, pid_t pid, int status) {
   85     /*
   86      * Resumed by delivery of SIGCONT
   87      */
   88     if (WIFCONTINUED(status)) {
   89         return;
   90     }
   91 
   92     /*
   93      * Boring, the process just exited
   94      */
   95     if (WIFEXITED(status)) {
   96         LOG_D("Process (pid %d) exited normally with status %d", pid, WEXITSTATUS(status));
   97         return;
   98     }
   99 
  100     /*
  101      * Shouldn't really happen, but, well..
  102      */
  103     if (!WIFSIGNALED(status)) {
  104         LOG_E("Process (pid %d) exited with the following status %d, please report that as a bug",
  105             pid, status);
  106         return;
  107     }
  108 
  109     int termsig = WTERMSIG(status);
  110     LOG_D("Process (pid %d) killed by signal %d '%s'", pid, termsig, strsignal(termsig));
  111     if (!arch_sigs[termsig].important) {
  112         LOG_D("It's not that important signal, skipping");
  113         return;
  114     }
  115 
  116     funcs_t* funcs = util_Calloc(_HF_MAX_FUNCS * sizeof(funcs_t));
  117     defer {
  118         free(funcs);
  119     };
  120     uint64_t pc = 0;
  121     uint64_t crashAddr = 0;
  122     char description[HF_STR_LEN] = {};
  123     size_t funcCnt = sanitizers_parseReport(run, pid, funcs, &pc, &crashAddr, description);
  124 
  125     /*
  126      * Calculate backtrace callstack hash signature
  127      */
  128     run->backtrace = sanitizers_hashCallstack(run, funcs, funcCnt, false);
  129 
  130     /*
  131      * If unique flag is set and single frame crash, disable uniqueness for this crash
  132      * to always save (timestamp will be added to the filename)
  133      */
  134     bool saveUnique = run->global->io.saveUnique;
  135     if (saveUnique && (funcCnt == 0)) {
  136         saveUnique = false;
  137     }
  138 
  139     /* If dry run mode, copy file with same name into workspace */
  140     if (run->global->mutate.mutationsPerRun == 0U && run->global->cfg.useVerifier) {
  141         snprintf(run->crashFileName, sizeof(run->crashFileName), "%s/%s", run->global->io.crashDir,
  142             run->dynfile->path);
  143     } else if (saveUnique) {
  144         snprintf(run->crashFileName, sizeof(run->crashFileName),
  145             "%s/%s.PC.%" PRIx64 ".STACK.%" PRIx64 ".ADDR.%" PRIx64 ".%s", run->global->io.crashDir,
  146             util_sigName(termsig), pc, run->backtrace, crashAddr, run->global->io.fileExtn);
  147     } else {
  148         char localtmstr[HF_STR_LEN];
  149         util_getLocalTime("%F.%H:%M:%S", localtmstr, sizeof(localtmstr), time(NULL));
  150         snprintf(run->crashFileName, sizeof(run->crashFileName),
  151             "%s/%s.PC.%" PRIx64 ".STACK.%" PRIx64 ".ADDR.%" PRIx64 ".%s.%d.%s",
  152             run->global->io.crashDir, util_sigName(termsig), pc, run->backtrace, crashAddr,
  153             localtmstr, pid, run->global->io.fileExtn);
  154     }
  155 
  156     if (files_exists(run->crashFileName)) {
  157         LOG_I("Crash (dup): '%s' already exists, skipping", run->crashFileName);
  158         /* Clear filename so that verifier can understand we hit a duplicate */
  159         memset(run->crashFileName, 0, sizeof(run->crashFileName));
  160         return;
  161     }
  162 
  163     LOG_I("Ok, that's interesting, saving input '%s'", run->crashFileName);
  164 
  165     ATOMIC_POST_INC(run->global->cnts.crashesCnt);
  166     ATOMIC_POST_INC(run->global->cnts.uniqueCrashesCnt);
  167     /* If unique crash found, reset dynFile counter */
  168     ATOMIC_CLEAR(run->global->cfg.dynFileIterExpire);
  169 
  170     if (files_writeBufToFile(run->crashFileName, run->dynfile->data, run->dynfile->size,
  171             O_CREAT | O_EXCL | O_WRONLY) == false) {
  172         LOG_E("Couldn't save crash to '%s'", run->crashFileName);
  173     }
  174 
  175     report_appendReport(pid, run, funcs, funcCnt, pc, crashAddr, termsig, "", description);
  176 }
  177 
  178 pid_t arch_fork(run_t* fuzzer HF_ATTR_UNUSED) {
  179     return fork();
  180 }
  181 
  182 bool arch_launchChild(run_t* run) {
  183     /* alarm persists across forks, so disable it here */
  184     alarm(0);
  185     execvp(run->args[0], (char* const*)run->args);
  186     alarm(1);
  187 
  188     return false;
  189 }
  190 
  191 void arch_prepareParent(run_t* fuzzer HF_ATTR_UNUSED) {
  192 }
  193 
  194 void arch_prepareParentAfterFork(run_t* fuzzer HF_ATTR_UNUSED) {
  195 }
  196 
  197 static bool arch_checkWait(run_t* run) {
  198     /* All queued wait events must be tested when SIGCHLD was delivered */
  199     for (;;) {
  200         int status;
  201         pid_t pid = TEMP_FAILURE_RETRY(waitpid(run->pid, &status, WNOHANG));
  202         if (pid == 0) {
  203             return false;
  204         }
  205         if (pid == -1 && errno == ECHILD) {
  206             LOG_D("No more processes to track");
  207             return true;
  208         }
  209         if (pid == -1) {
  210             PLOG_F("waitpid() failed");
  211         }
  212 
  213         char statusStr[4096];
  214         LOG_D("pid=%d returned with status: %s", pid,
  215             subproc_StatusToStr(status, statusStr, sizeof(statusStr)));
  216 
  217         arch_analyzeSignal(run, pid, status);
  218 
  219         if (pid == run->pid && (WIFEXITED(status) || WIFSIGNALED(status))) {
  220             if (run->global->exe.persistent) {
  221                 if (!fuzz_isTerminating()) {
  222                     LOG_W("Persistent mode: pid=%d exited with status: %s", (int)run->pid,
  223                         subproc_StatusToStr(status, statusStr, sizeof(statusStr)));
  224                 }
  225             }
  226             return true;
  227         }
  228     }
  229 }
  230 
  231 void arch_reapChild(run_t* run) {
  232     for (;;) {
  233         if (subproc_persistentModeStateMachine(run)) {
  234             break;
  235         }
  236 
  237         subproc_checkTimeLimit(run);
  238         subproc_checkTermination(run);
  239 
  240         if (run->global->exe.persistent) {
  241             struct pollfd pfd = {
  242                 .fd = run->persistentSock,
  243                 .events = POLLIN,
  244             };
  245             int r = poll(&pfd, 1, 250 /* 0.25s */);
  246             if (r == -1 && errno != EINTR) {
  247                 PLOG_F("poll(fd=%d)", run->persistentSock);
  248             }
  249         } else {
  250             /* Return with SIGIO, SIGCHLD */
  251             errno = 0;
  252             int sig;
  253             int ret = sigwait(&run->global->exe.waitSigSet, &sig);
  254             if (ret != 0 && ret != EINTR) {
  255                 PLOG_F("sigwait(SIGIO|SIGCHLD)");
  256             }
  257         }
  258 
  259         if (arch_checkWait(run)) {
  260             run->pid = 0;
  261             break;
  262         }
  263     }
  264 }
  265 
  266 bool arch_archInit(honggfuzz_t* hfuzz HF_ATTR_UNUSED) {
  267     /* Make %'d work */
  268     setlocale(LC_NUMERIC, "en_US.UTF-8");
  269 
  270     return true;
  271 }
  272 
  273 bool arch_archThreadInit(run_t* fuzzer HF_ATTR_UNUSED) {
  274     return true;
  275 }