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