1*ffb1132eSMatt Morehouse //===- FuzzerUtilFuchsia.cpp - Misc utils for Fuchsia. --------------------===// 2*ffb1132eSMatt Morehouse // 3*ffb1132eSMatt Morehouse // The LLVM Compiler Infrastructure 4*ffb1132eSMatt Morehouse // 5*ffb1132eSMatt Morehouse // This file is distributed under the University of Illinois Open Source 6*ffb1132eSMatt Morehouse // License. See LICENSE.TXT for details. 7*ffb1132eSMatt Morehouse // 8*ffb1132eSMatt Morehouse //===----------------------------------------------------------------------===// 9*ffb1132eSMatt Morehouse // Misc utils implementation using Fuchsia/Zircon APIs. 10*ffb1132eSMatt Morehouse //===----------------------------------------------------------------------===// 11*ffb1132eSMatt Morehouse #include "FuzzerDefs.h" 12*ffb1132eSMatt Morehouse 13*ffb1132eSMatt Morehouse #if LIBFUZZER_FUCHSIA 14*ffb1132eSMatt Morehouse 15*ffb1132eSMatt Morehouse #include "FuzzerInternal.h" 16*ffb1132eSMatt Morehouse #include "FuzzerUtil.h" 17*ffb1132eSMatt Morehouse #include <cerrno> 18*ffb1132eSMatt Morehouse #include <cinttypes> 19*ffb1132eSMatt Morehouse #include <cstdint> 20*ffb1132eSMatt Morehouse #include <fbl/unique_fd.h> 21*ffb1132eSMatt Morehouse #include <fcntl.h> 22*ffb1132eSMatt Morehouse #include <launchpad/launchpad.h> 23*ffb1132eSMatt Morehouse #include <string> 24*ffb1132eSMatt Morehouse #include <thread> 25*ffb1132eSMatt Morehouse #include <zircon/errors.h> 26*ffb1132eSMatt Morehouse #include <zircon/status.h> 27*ffb1132eSMatt Morehouse #include <zircon/syscalls.h> 28*ffb1132eSMatt Morehouse #include <zircon/syscalls/port.h> 29*ffb1132eSMatt Morehouse #include <zircon/types.h> 30*ffb1132eSMatt Morehouse #include <zx/object.h> 31*ffb1132eSMatt Morehouse #include <zx/port.h> 32*ffb1132eSMatt Morehouse #include <zx/process.h> 33*ffb1132eSMatt Morehouse #include <zx/time.h> 34*ffb1132eSMatt Morehouse 35*ffb1132eSMatt Morehouse namespace fuzzer { 36*ffb1132eSMatt Morehouse 37*ffb1132eSMatt Morehouse namespace { 38*ffb1132eSMatt Morehouse 39*ffb1132eSMatt Morehouse // A magic value for the Zircon exception port, chosen to spell 'FUZZING' 40*ffb1132eSMatt Morehouse // when interpreted as a byte sequence on little-endian platforms. 41*ffb1132eSMatt Morehouse const uint64_t kFuzzingCrash = 0x474e495a5a5546; 42*ffb1132eSMatt Morehouse 43*ffb1132eSMatt Morehouse void AlarmHandler(int Seconds) { 44*ffb1132eSMatt Morehouse while (true) { 45*ffb1132eSMatt Morehouse SleepSeconds(Seconds); 46*ffb1132eSMatt Morehouse Fuzzer::StaticAlarmCallback(); 47*ffb1132eSMatt Morehouse } 48*ffb1132eSMatt Morehouse } 49*ffb1132eSMatt Morehouse 50*ffb1132eSMatt Morehouse void InterruptHandler() { 51*ffb1132eSMatt Morehouse // Ctrl-C sends ETX in Zircon. 52*ffb1132eSMatt Morehouse while (getchar() != 0x03); 53*ffb1132eSMatt Morehouse Fuzzer::StaticInterruptCallback(); 54*ffb1132eSMatt Morehouse } 55*ffb1132eSMatt Morehouse 56*ffb1132eSMatt Morehouse void CrashHandler(zx::port *Port) { 57*ffb1132eSMatt Morehouse std::unique_ptr<zx::port> ExceptionPort(Port); 58*ffb1132eSMatt Morehouse zx_port_packet_t Packet; 59*ffb1132eSMatt Morehouse ExceptionPort->wait(ZX_TIME_INFINITE, &Packet, 0); 60*ffb1132eSMatt Morehouse // Unbind as soon as possible so we don't receive exceptions from this thread. 61*ffb1132eSMatt Morehouse if (zx_task_bind_exception_port(ZX_HANDLE_INVALID, ZX_HANDLE_INVALID, 62*ffb1132eSMatt Morehouse kFuzzingCrash, 0) != ZX_OK) { 63*ffb1132eSMatt Morehouse // Shouldn't happen; if it does the safest option is to just exit. 64*ffb1132eSMatt Morehouse Printf("libFuzzer: unable to unbind exception port; aborting!\n"); 65*ffb1132eSMatt Morehouse exit(1); 66*ffb1132eSMatt Morehouse } 67*ffb1132eSMatt Morehouse if (Packet.key != kFuzzingCrash) { 68*ffb1132eSMatt Morehouse Printf("libFuzzer: invalid crash key: %" PRIx64 "; aborting!\n", 69*ffb1132eSMatt Morehouse Packet.key); 70*ffb1132eSMatt Morehouse exit(1); 71*ffb1132eSMatt Morehouse } 72*ffb1132eSMatt Morehouse // CrashCallback should not return from this call 73*ffb1132eSMatt Morehouse Fuzzer::StaticCrashSignalCallback(); 74*ffb1132eSMatt Morehouse } 75*ffb1132eSMatt Morehouse 76*ffb1132eSMatt Morehouse } // namespace 77*ffb1132eSMatt Morehouse 78*ffb1132eSMatt Morehouse // Platform specific functions. 79*ffb1132eSMatt Morehouse void SetSignalHandler(const FuzzingOptions &Options) { 80*ffb1132eSMatt Morehouse zx_status_t rc; 81*ffb1132eSMatt Morehouse 82*ffb1132eSMatt Morehouse // Set up alarm handler if needed. 83*ffb1132eSMatt Morehouse if (Options.UnitTimeoutSec > 0) { 84*ffb1132eSMatt Morehouse std::thread T(AlarmHandler, Options.UnitTimeoutSec / 2 + 1); 85*ffb1132eSMatt Morehouse T.detach(); 86*ffb1132eSMatt Morehouse } 87*ffb1132eSMatt Morehouse 88*ffb1132eSMatt Morehouse // Set up interrupt handler if needed. 89*ffb1132eSMatt Morehouse if (Options.HandleInt || Options.HandleTerm) { 90*ffb1132eSMatt Morehouse std::thread T(InterruptHandler); 91*ffb1132eSMatt Morehouse T.detach(); 92*ffb1132eSMatt Morehouse } 93*ffb1132eSMatt Morehouse 94*ffb1132eSMatt Morehouse // Early exit if no crash handler needed. 95*ffb1132eSMatt Morehouse if (!Options.HandleSegv && !Options.HandleBus && !Options.HandleIll && 96*ffb1132eSMatt Morehouse !Options.HandleFpe && !Options.HandleAbrt) 97*ffb1132eSMatt Morehouse return; 98*ffb1132eSMatt Morehouse 99*ffb1132eSMatt Morehouse // Create an exception port 100*ffb1132eSMatt Morehouse zx::port *ExceptionPort = new zx::port(); 101*ffb1132eSMatt Morehouse if ((rc = zx::port::create(0, ExceptionPort)) != ZX_OK) { 102*ffb1132eSMatt Morehouse Printf("libFuzzer: zx_port_create failed: %s\n", zx_status_get_string(rc)); 103*ffb1132eSMatt Morehouse exit(1); 104*ffb1132eSMatt Morehouse } 105*ffb1132eSMatt Morehouse 106*ffb1132eSMatt Morehouse // Bind the port to receive exceptions from our process 107*ffb1132eSMatt Morehouse if ((rc = zx_task_bind_exception_port(zx_process_self(), ExceptionPort->get(), 108*ffb1132eSMatt Morehouse kFuzzingCrash, 0)) != ZX_OK) { 109*ffb1132eSMatt Morehouse Printf("libFuzzer: unable to bind exception port: %s\n", 110*ffb1132eSMatt Morehouse zx_status_get_string(rc)); 111*ffb1132eSMatt Morehouse exit(1); 112*ffb1132eSMatt Morehouse } 113*ffb1132eSMatt Morehouse 114*ffb1132eSMatt Morehouse // Set up the crash handler. 115*ffb1132eSMatt Morehouse std::thread T(CrashHandler, ExceptionPort); 116*ffb1132eSMatt Morehouse T.detach(); 117*ffb1132eSMatt Morehouse } 118*ffb1132eSMatt Morehouse 119*ffb1132eSMatt Morehouse void SleepSeconds(int Seconds) { 120*ffb1132eSMatt Morehouse zx::nanosleep(zx::deadline_after(ZX_SEC(Seconds))); 121*ffb1132eSMatt Morehouse } 122*ffb1132eSMatt Morehouse 123*ffb1132eSMatt Morehouse unsigned long GetPid() { 124*ffb1132eSMatt Morehouse zx_status_t rc; 125*ffb1132eSMatt Morehouse zx_info_handle_basic_t Info; 126*ffb1132eSMatt Morehouse if ((rc = zx_object_get_info(zx_process_self(), ZX_INFO_HANDLE_BASIC, &Info, 127*ffb1132eSMatt Morehouse sizeof(Info), NULL, NULL)) != ZX_OK) { 128*ffb1132eSMatt Morehouse Printf("libFuzzer: unable to get info about self: %s\n", 129*ffb1132eSMatt Morehouse zx_status_get_string(rc)); 130*ffb1132eSMatt Morehouse exit(1); 131*ffb1132eSMatt Morehouse } 132*ffb1132eSMatt Morehouse return Info.koid; 133*ffb1132eSMatt Morehouse } 134*ffb1132eSMatt Morehouse 135*ffb1132eSMatt Morehouse size_t GetPeakRSSMb() { 136*ffb1132eSMatt Morehouse zx_status_t rc; 137*ffb1132eSMatt Morehouse zx_info_task_stats_t Info; 138*ffb1132eSMatt Morehouse if ((rc = zx_object_get_info(zx_process_self(), ZX_INFO_TASK_STATS, &Info, 139*ffb1132eSMatt Morehouse sizeof(Info), NULL, NULL)) != ZX_OK) { 140*ffb1132eSMatt Morehouse Printf("libFuzzer: unable to get info about self: %s\n", 141*ffb1132eSMatt Morehouse zx_status_get_string(rc)); 142*ffb1132eSMatt Morehouse exit(1); 143*ffb1132eSMatt Morehouse } 144*ffb1132eSMatt Morehouse return (Info.mem_private_bytes + Info.mem_shared_bytes) >> 20; 145*ffb1132eSMatt Morehouse } 146*ffb1132eSMatt Morehouse 147*ffb1132eSMatt Morehouse int ExecuteCommand(const Command &Cmd) { 148*ffb1132eSMatt Morehouse zx_status_t rc; 149*ffb1132eSMatt Morehouse 150*ffb1132eSMatt Morehouse // Convert arguments to C array 151*ffb1132eSMatt Morehouse auto Args = Cmd.getArguments(); 152*ffb1132eSMatt Morehouse size_t Argc = Args.size(); 153*ffb1132eSMatt Morehouse assert(Argc != 0); 154*ffb1132eSMatt Morehouse std::unique_ptr<const char *[]> Argv(new const char *[Argc]); 155*ffb1132eSMatt Morehouse for (size_t i = 0; i < Argc; ++i) 156*ffb1132eSMatt Morehouse Argv[i] = Args[i].c_str(); 157*ffb1132eSMatt Morehouse 158*ffb1132eSMatt Morehouse // Create the basic launchpad. Clone everything except stdio. 159*ffb1132eSMatt Morehouse launchpad_t *lp; 160*ffb1132eSMatt Morehouse launchpad_create(ZX_HANDLE_INVALID, Argv[0], &lp); 161*ffb1132eSMatt Morehouse launchpad_load_from_file(lp, Argv[0]); 162*ffb1132eSMatt Morehouse launchpad_set_args(lp, Argc, Argv.get()); 163*ffb1132eSMatt Morehouse launchpad_clone(lp, LP_CLONE_ALL & (~LP_CLONE_FDIO_STDIO)); 164*ffb1132eSMatt Morehouse 165*ffb1132eSMatt Morehouse // Determine stdout 166*ffb1132eSMatt Morehouse int FdOut = STDOUT_FILENO; 167*ffb1132eSMatt Morehouse fbl::unique_fd OutputFile; 168*ffb1132eSMatt Morehouse if (Cmd.hasOutputFile()) { 169*ffb1132eSMatt Morehouse auto Filename = Cmd.getOutputFile(); 170*ffb1132eSMatt Morehouse OutputFile.reset(open(Filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0)); 171*ffb1132eSMatt Morehouse if (!OutputFile) { 172*ffb1132eSMatt Morehouse Printf("libFuzzer: failed to open %s: %s\n", Filename.c_str(), 173*ffb1132eSMatt Morehouse strerror(errno)); 174*ffb1132eSMatt Morehouse return ZX_ERR_IO; 175*ffb1132eSMatt Morehouse } 176*ffb1132eSMatt Morehouse FdOut = OutputFile.get(); 177*ffb1132eSMatt Morehouse } 178*ffb1132eSMatt Morehouse 179*ffb1132eSMatt Morehouse // Determine stderr 180*ffb1132eSMatt Morehouse int FdErr = STDERR_FILENO; 181*ffb1132eSMatt Morehouse if (Cmd.isOutAndErrCombined()) 182*ffb1132eSMatt Morehouse FdErr = FdOut; 183*ffb1132eSMatt Morehouse 184*ffb1132eSMatt Morehouse // Clone the file descriptors into the new process 185*ffb1132eSMatt Morehouse if ((rc = launchpad_clone_fd(lp, STDIN_FILENO, STDIN_FILENO)) != ZX_OK || 186*ffb1132eSMatt Morehouse (rc = launchpad_clone_fd(lp, FdOut, STDOUT_FILENO)) != ZX_OK || 187*ffb1132eSMatt Morehouse (rc = launchpad_clone_fd(lp, FdErr, STDERR_FILENO)) != ZX_OK) { 188*ffb1132eSMatt Morehouse Printf("libFuzzer: failed to clone FDIO: %s\n", zx_status_get_string(rc)); 189*ffb1132eSMatt Morehouse return rc; 190*ffb1132eSMatt Morehouse } 191*ffb1132eSMatt Morehouse 192*ffb1132eSMatt Morehouse // Start the process 193*ffb1132eSMatt Morehouse zx_handle_t ProcessHandle = ZX_HANDLE_INVALID; 194*ffb1132eSMatt Morehouse const char *ErrorMsg = nullptr; 195*ffb1132eSMatt Morehouse if ((rc = launchpad_go(lp, &ProcessHandle, &ErrorMsg)) != ZX_OK) { 196*ffb1132eSMatt Morehouse Printf("libFuzzer: failed to launch '%s': %s, %s\n", Argv[0], ErrorMsg, 197*ffb1132eSMatt Morehouse zx_status_get_string(rc)); 198*ffb1132eSMatt Morehouse return rc; 199*ffb1132eSMatt Morehouse } 200*ffb1132eSMatt Morehouse zx::process Process(ProcessHandle); 201*ffb1132eSMatt Morehouse 202*ffb1132eSMatt Morehouse // Now join the process and return the exit status. 203*ffb1132eSMatt Morehouse if ((rc = Process.wait_one(ZX_PROCESS_TERMINATED, ZX_TIME_INFINITE, 204*ffb1132eSMatt Morehouse nullptr)) != ZX_OK) { 205*ffb1132eSMatt Morehouse Printf("libFuzzer: failed to join '%s': %s\n", Argv[0], 206*ffb1132eSMatt Morehouse zx_status_get_string(rc)); 207*ffb1132eSMatt Morehouse return rc; 208*ffb1132eSMatt Morehouse } 209*ffb1132eSMatt Morehouse 210*ffb1132eSMatt Morehouse zx_info_process_t Info; 211*ffb1132eSMatt Morehouse if ((rc = Process.get_info(ZX_INFO_PROCESS, &Info, sizeof(Info), nullptr, 212*ffb1132eSMatt Morehouse nullptr)) != ZX_OK) { 213*ffb1132eSMatt Morehouse Printf("libFuzzer: unable to get return code from '%s': %s\n", Argv[0], 214*ffb1132eSMatt Morehouse zx_status_get_string(rc)); 215*ffb1132eSMatt Morehouse return rc; 216*ffb1132eSMatt Morehouse } 217*ffb1132eSMatt Morehouse 218*ffb1132eSMatt Morehouse return Info.return_code; 219*ffb1132eSMatt Morehouse } 220*ffb1132eSMatt Morehouse 221*ffb1132eSMatt Morehouse const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt, 222*ffb1132eSMatt Morehouse size_t PattLen) { 223*ffb1132eSMatt Morehouse return memmem(Data, DataLen, Patt, PattLen); 224*ffb1132eSMatt Morehouse } 225*ffb1132eSMatt Morehouse 226*ffb1132eSMatt Morehouse } // namespace fuzzer 227*ffb1132eSMatt Morehouse 228*ffb1132eSMatt Morehouse #endif // LIBFUZZER_FUCHSIA 229