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