1 1.1 kamil //===- FuzzerShmemPosix.cpp - Posix shared memory ---------------*- C++ -* ===// 2 1.1 kamil // 3 1.1 kamil // The LLVM Compiler Infrastructure 4 1.1 kamil // 5 1.1 kamil // This file is distributed under the University of Illinois Open Source 6 1.1 kamil // License. See LICENSE.TXT for details. 7 1.1 kamil // 8 1.1 kamil //===----------------------------------------------------------------------===// 9 1.1 kamil // SharedMemoryRegion 10 1.1 kamil //===----------------------------------------------------------------------===// 11 1.1 kamil #include "FuzzerDefs.h" 12 1.1 kamil #if LIBFUZZER_POSIX 13 1.1 kamil 14 1.1 kamil #include "FuzzerIO.h" 15 1.1 kamil #include "FuzzerShmem.h" 16 1.1 kamil 17 1.1 kamil #include <errno.h> 18 1.1 kamil #include <fcntl.h> 19 1.1 kamil #include <semaphore.h> 20 1.1 kamil #include <stdio.h> 21 1.1 kamil #include <stdlib.h> 22 1.1 kamil #include <sys/mman.h> 23 1.1 kamil #include <sys/stat.h> 24 1.1 kamil #include <sys/types.h> 25 1.1 kamil #include <unistd.h> 26 1.1 kamil 27 1.1 kamil namespace fuzzer { 28 1.1 kamil 29 1.1 kamil std::string SharedMemoryRegion::Path(const char *Name) { 30 1.1 kamil return DirPlusFile(TmpDir(), Name); 31 1.1 kamil } 32 1.1 kamil 33 1.1 kamil std::string SharedMemoryRegion::SemName(const char *Name, int Idx) { 34 1.1 kamil std::string Res(Name); 35 1.1 kamil // When passing a name without a leading <slash> character to 36 1.1 kamil // sem_open, the behaviour is unspecified in POSIX. Add a leading 37 1.1 kamil // <slash> character for the name if there is no such one. 38 1.1 kamil if (!Res.empty() && Res[0] != '/') 39 1.1 kamil Res.insert(Res.begin(), '/'); 40 1.1 kamil return Res + (char)('0' + Idx); 41 1.1 kamil } 42 1.1 kamil 43 1.1 kamil bool SharedMemoryRegion::Map(int fd) { 44 1.1 kamil Data = 45 1.1 kamil (uint8_t *)mmap(0, kShmemSize, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0); 46 1.1 kamil if (Data == (uint8_t*)-1) 47 1.1 kamil return false; 48 1.1 kamil return true; 49 1.1 kamil } 50 1.1 kamil 51 1.1 kamil bool SharedMemoryRegion::Create(const char *Name) { 52 1.1 kamil int fd = open(Path(Name).c_str(), O_CREAT | O_RDWR, 0777); 53 1.1 kamil if (fd < 0) return false; 54 1.1 kamil if (ftruncate(fd, kShmemSize) < 0) return false; 55 1.1 kamil if (!Map(fd)) 56 1.1 kamil return false; 57 1.1 kamil for (int i = 0; i < 2; i++) { 58 1.1 kamil sem_unlink(SemName(Name, i).c_str()); 59 1.1 kamil Semaphore[i] = sem_open(SemName(Name, i).c_str(), O_CREAT, 0644, 0); 60 1.1 kamil if (Semaphore[i] == SEM_FAILED) 61 1.1 kamil return false; 62 1.1 kamil } 63 1.1 kamil IAmServer = true; 64 1.1 kamil return true; 65 1.1 kamil } 66 1.1 kamil 67 1.1 kamil bool SharedMemoryRegion::Open(const char *Name) { 68 1.1 kamil int fd = open(Path(Name).c_str(), O_RDWR); 69 1.1 kamil if (fd < 0) return false; 70 1.1 kamil struct stat stat_res; 71 1.1 kamil if (0 != fstat(fd, &stat_res)) 72 1.1 kamil return false; 73 1.1 kamil assert(stat_res.st_size == kShmemSize); 74 1.1 kamil if (!Map(fd)) 75 1.1 kamil return false; 76 1.1 kamil for (int i = 0; i < 2; i++) { 77 1.1 kamil Semaphore[i] = sem_open(SemName(Name, i).c_str(), 0); 78 1.1 kamil if (Semaphore[i] == SEM_FAILED) 79 1.1 kamil return false; 80 1.1 kamil } 81 1.1 kamil IAmServer = false; 82 1.1 kamil return true; 83 1.1 kamil } 84 1.1 kamil 85 1.1 kamil bool SharedMemoryRegion::Destroy(const char *Name) { 86 1.1 kamil return 0 == unlink(Path(Name).c_str()); 87 1.1 kamil } 88 1.1 kamil 89 1.1 kamil void SharedMemoryRegion::Post(int Idx) { 90 1.1 kamil assert(Idx == 0 || Idx == 1); 91 1.1 kamil sem_post((sem_t*)Semaphore[Idx]); 92 1.1 kamil } 93 1.1 kamil 94 1.1 kamil void SharedMemoryRegion::Wait(int Idx) { 95 1.1 kamil assert(Idx == 0 || Idx == 1); 96 1.1 kamil for (int i = 0; i < 10 && sem_wait((sem_t*)Semaphore[Idx]); i++) { 97 1.1 kamil // sem_wait may fail if interrupted by a signal. 98 1.1 kamil sleep(i); 99 1.1 kamil if (i) 100 1.1 kamil Printf("%s: sem_wait[%d] failed %s\n", i < 9 ? "WARNING" : "ERROR", i, 101 1.1 kamil strerror(errno)); 102 1.1 kamil if (i == 9) abort(); 103 1.1 kamil } 104 1.1 kamil } 105 1.1 kamil 106 1.1 kamil } // namespace fuzzer 107 1.1 kamil 108 1.1 kamil #endif // LIBFUZZER_POSIX 109