168d75effSDimitry Andric //===-- sanitizer_posix.cpp -----------------------------------------------===// 268d75effSDimitry Andric // 368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 668d75effSDimitry Andric // 768d75effSDimitry Andric //===----------------------------------------------------------------------===// 868d75effSDimitry Andric // 968d75effSDimitry Andric // This file is shared between AddressSanitizer and ThreadSanitizer 1068d75effSDimitry Andric // run-time libraries and implements POSIX-specific functions from 1168d75effSDimitry Andric // sanitizer_posix.h. 1268d75effSDimitry Andric //===----------------------------------------------------------------------===// 1368d75effSDimitry Andric 1468d75effSDimitry Andric #include "sanitizer_platform.h" 1568d75effSDimitry Andric 1668d75effSDimitry Andric #if SANITIZER_POSIX 1768d75effSDimitry Andric 1868d75effSDimitry Andric #include "sanitizer_common.h" 1968d75effSDimitry Andric #include "sanitizer_file.h" 2068d75effSDimitry Andric #include "sanitizer_flags.h" 2168d75effSDimitry Andric #include "sanitizer_libc.h" 2268d75effSDimitry Andric #include "sanitizer_posix.h" 2368d75effSDimitry Andric #include "sanitizer_procmaps.h" 2468d75effSDimitry Andric 2568d75effSDimitry Andric #include <errno.h> 2668d75effSDimitry Andric #include <fcntl.h> 2768d75effSDimitry Andric #include <signal.h> 2868d75effSDimitry Andric #include <sys/mman.h> 2968d75effSDimitry Andric 3068d75effSDimitry Andric #if SANITIZER_FREEBSD 3168d75effSDimitry Andric // The MAP_NORESERVE define has been removed in FreeBSD 11.x, and even before 3268d75effSDimitry Andric // that, it was never implemented. So just define it to zero. 3368d75effSDimitry Andric #undef MAP_NORESERVE 3468d75effSDimitry Andric #define MAP_NORESERVE 0 3568d75effSDimitry Andric #endif 3668d75effSDimitry Andric 3768d75effSDimitry Andric namespace __sanitizer { 3868d75effSDimitry Andric 3968d75effSDimitry Andric // ------------- sanitizer_common.h 4068d75effSDimitry Andric uptr GetMmapGranularity() { 4168d75effSDimitry Andric return GetPageSize(); 4268d75effSDimitry Andric } 4368d75effSDimitry Andric 4481ad6265SDimitry Andric bool ErrorIsOOM(error_t err) { return err == ENOMEM; } 4581ad6265SDimitry Andric 4668d75effSDimitry Andric void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) { 4768d75effSDimitry Andric size = RoundUpTo(size, GetPageSizeCached()); 4868d75effSDimitry Andric uptr res = MmapNamed(nullptr, size, PROT_READ | PROT_WRITE, 4968d75effSDimitry Andric MAP_PRIVATE | MAP_ANON, mem_type); 5068d75effSDimitry Andric int reserrno; 5168d75effSDimitry Andric if (UNLIKELY(internal_iserror(res, &reserrno))) 5268d75effSDimitry Andric ReportMmapFailureAndDie(size, mem_type, "allocate", reserrno, raw_report); 5368d75effSDimitry Andric IncreaseTotalMmap(size); 5468d75effSDimitry Andric return (void *)res; 5568d75effSDimitry Andric } 5668d75effSDimitry Andric 57*0fca6ea1SDimitry Andric void UnmapOrDie(void *addr, uptr size, bool raw_report) { 5868d75effSDimitry Andric if (!addr || !size) return; 5968d75effSDimitry Andric uptr res = internal_munmap(addr, size); 6006c3fb27SDimitry Andric int reserrno; 6106c3fb27SDimitry Andric if (UNLIKELY(internal_iserror(res, &reserrno))) 62*0fca6ea1SDimitry Andric ReportMunmapFailureAndDie(addr, size, reserrno, raw_report); 6368d75effSDimitry Andric DecreaseTotalMmap(size); 6468d75effSDimitry Andric } 6568d75effSDimitry Andric 6668d75effSDimitry Andric void *MmapOrDieOnFatalError(uptr size, const char *mem_type) { 6768d75effSDimitry Andric size = RoundUpTo(size, GetPageSizeCached()); 6868d75effSDimitry Andric uptr res = MmapNamed(nullptr, size, PROT_READ | PROT_WRITE, 6968d75effSDimitry Andric MAP_PRIVATE | MAP_ANON, mem_type); 7068d75effSDimitry Andric int reserrno; 7168d75effSDimitry Andric if (UNLIKELY(internal_iserror(res, &reserrno))) { 7268d75effSDimitry Andric if (reserrno == ENOMEM) 7368d75effSDimitry Andric return nullptr; 7468d75effSDimitry Andric ReportMmapFailureAndDie(size, mem_type, "allocate", reserrno); 7568d75effSDimitry Andric } 7668d75effSDimitry Andric IncreaseTotalMmap(size); 7768d75effSDimitry Andric return (void *)res; 7868d75effSDimitry Andric } 7968d75effSDimitry Andric 8068d75effSDimitry Andric // We want to map a chunk of address space aligned to 'alignment'. 8168d75effSDimitry Andric // We do it by mapping a bit more and then unmapping redundant pieces. 8268d75effSDimitry Andric // We probably can do it with fewer syscalls in some OS-dependent way. 8368d75effSDimitry Andric void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment, 8468d75effSDimitry Andric const char *mem_type) { 8568d75effSDimitry Andric CHECK(IsPowerOfTwo(size)); 8668d75effSDimitry Andric CHECK(IsPowerOfTwo(alignment)); 8768d75effSDimitry Andric uptr map_size = size + alignment; 88bdd1243dSDimitry Andric // mmap maps entire pages and rounds up map_size needs to be a an integral 89bdd1243dSDimitry Andric // number of pages. 90bdd1243dSDimitry Andric // We need to be aware of this size for calculating end and for unmapping 91bdd1243dSDimitry Andric // fragments before and after the alignment region. 92bdd1243dSDimitry Andric map_size = RoundUpTo(map_size, GetPageSizeCached()); 9368d75effSDimitry Andric uptr map_res = (uptr)MmapOrDieOnFatalError(map_size, mem_type); 9468d75effSDimitry Andric if (UNLIKELY(!map_res)) 9568d75effSDimitry Andric return nullptr; 9668d75effSDimitry Andric uptr res = map_res; 9768d75effSDimitry Andric if (!IsAligned(res, alignment)) { 9868d75effSDimitry Andric res = (map_res + alignment - 1) & ~(alignment - 1); 9968d75effSDimitry Andric UnmapOrDie((void*)map_res, res - map_res); 10068d75effSDimitry Andric } 101bdd1243dSDimitry Andric uptr map_end = map_res + map_size; 10268d75effSDimitry Andric uptr end = res + size; 10381ad6265SDimitry Andric end = RoundUpTo(end, GetPageSizeCached()); 104bdd1243dSDimitry Andric if (end != map_end) { 105bdd1243dSDimitry Andric CHECK_LT(end, map_end); 10668d75effSDimitry Andric UnmapOrDie((void*)end, map_end - end); 107bdd1243dSDimitry Andric } 10868d75effSDimitry Andric return (void*)res; 10968d75effSDimitry Andric } 11068d75effSDimitry Andric 11168d75effSDimitry Andric void *MmapNoReserveOrDie(uptr size, const char *mem_type) { 11268d75effSDimitry Andric size = RoundUpTo(size, GetPageSizeCached()); 11368d75effSDimitry Andric uptr p = MmapNamed(nullptr, size, PROT_READ | PROT_WRITE, 11468d75effSDimitry Andric MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, mem_type); 11568d75effSDimitry Andric int reserrno; 11668d75effSDimitry Andric if (UNLIKELY(internal_iserror(p, &reserrno))) 11768d75effSDimitry Andric ReportMmapFailureAndDie(size, mem_type, "allocate noreserve", reserrno); 11868d75effSDimitry Andric IncreaseTotalMmap(size); 11968d75effSDimitry Andric return (void *)p; 12068d75effSDimitry Andric } 12168d75effSDimitry Andric 12268d75effSDimitry Andric static void *MmapFixedImpl(uptr fixed_addr, uptr size, bool tolerate_enomem, 12368d75effSDimitry Andric const char *name) { 12468d75effSDimitry Andric size = RoundUpTo(size, GetPageSizeCached()); 12568d75effSDimitry Andric fixed_addr = RoundDownTo(fixed_addr, GetPageSizeCached()); 12668d75effSDimitry Andric uptr p = MmapNamed((void *)fixed_addr, size, PROT_READ | PROT_WRITE, 12768d75effSDimitry Andric MAP_PRIVATE | MAP_ANON | MAP_FIXED, name); 12868d75effSDimitry Andric int reserrno; 12968d75effSDimitry Andric if (UNLIKELY(internal_iserror(p, &reserrno))) { 13068d75effSDimitry Andric if (tolerate_enomem && reserrno == ENOMEM) 13168d75effSDimitry Andric return nullptr; 13268d75effSDimitry Andric char mem_type[40]; 133*0fca6ea1SDimitry Andric internal_snprintf(mem_type, sizeof(mem_type), "memory at address %p", 134*0fca6ea1SDimitry Andric (void *)fixed_addr); 13568d75effSDimitry Andric ReportMmapFailureAndDie(size, mem_type, "allocate", reserrno); 13668d75effSDimitry Andric } 13768d75effSDimitry Andric IncreaseTotalMmap(size); 13868d75effSDimitry Andric return (void *)p; 13968d75effSDimitry Andric } 14068d75effSDimitry Andric 14168d75effSDimitry Andric void *MmapFixedOrDie(uptr fixed_addr, uptr size, const char *name) { 14268d75effSDimitry Andric return MmapFixedImpl(fixed_addr, size, false /*tolerate_enomem*/, name); 14368d75effSDimitry Andric } 14468d75effSDimitry Andric 14568d75effSDimitry Andric void *MmapFixedOrDieOnFatalError(uptr fixed_addr, uptr size, const char *name) { 14668d75effSDimitry Andric return MmapFixedImpl(fixed_addr, size, true /*tolerate_enomem*/, name); 14768d75effSDimitry Andric } 14868d75effSDimitry Andric 14968d75effSDimitry Andric bool MprotectNoAccess(uptr addr, uptr size) { 15068d75effSDimitry Andric return 0 == internal_mprotect((void*)addr, size, PROT_NONE); 15168d75effSDimitry Andric } 15268d75effSDimitry Andric 15368d75effSDimitry Andric bool MprotectReadOnly(uptr addr, uptr size) { 15468d75effSDimitry Andric return 0 == internal_mprotect((void *)addr, size, PROT_READ); 15568d75effSDimitry Andric } 15668d75effSDimitry Andric 15706c3fb27SDimitry Andric bool MprotectReadWrite(uptr addr, uptr size) { 15806c3fb27SDimitry Andric return 0 == internal_mprotect((void *)addr, size, PROT_READ | PROT_WRITE); 15906c3fb27SDimitry Andric } 16006c3fb27SDimitry Andric 16181ad6265SDimitry Andric #if !SANITIZER_APPLE 16268d75effSDimitry Andric void MprotectMallocZones(void *addr, int prot) {} 16368d75effSDimitry Andric #endif 16468d75effSDimitry Andric 16568d75effSDimitry Andric fd_t OpenFile(const char *filename, FileAccessMode mode, error_t *errno_p) { 16668d75effSDimitry Andric if (ShouldMockFailureToOpen(filename)) 16768d75effSDimitry Andric return kInvalidFd; 16868d75effSDimitry Andric int flags; 16968d75effSDimitry Andric switch (mode) { 17068d75effSDimitry Andric case RdOnly: flags = O_RDONLY; break; 17168d75effSDimitry Andric case WrOnly: flags = O_WRONLY | O_CREAT | O_TRUNC; break; 17268d75effSDimitry Andric case RdWr: flags = O_RDWR | O_CREAT; break; 17368d75effSDimitry Andric } 17468d75effSDimitry Andric fd_t res = internal_open(filename, flags, 0660); 17568d75effSDimitry Andric if (internal_iserror(res, errno_p)) 17668d75effSDimitry Andric return kInvalidFd; 17768d75effSDimitry Andric return ReserveStandardFds(res); 17868d75effSDimitry Andric } 17968d75effSDimitry Andric 18068d75effSDimitry Andric void CloseFile(fd_t fd) { 18168d75effSDimitry Andric internal_close(fd); 18268d75effSDimitry Andric } 18368d75effSDimitry Andric 18468d75effSDimitry Andric bool ReadFromFile(fd_t fd, void *buff, uptr buff_size, uptr *bytes_read, 18568d75effSDimitry Andric error_t *error_p) { 18668d75effSDimitry Andric uptr res = internal_read(fd, buff, buff_size); 18768d75effSDimitry Andric if (internal_iserror(res, error_p)) 18868d75effSDimitry Andric return false; 18968d75effSDimitry Andric if (bytes_read) 19068d75effSDimitry Andric *bytes_read = res; 19168d75effSDimitry Andric return true; 19268d75effSDimitry Andric } 19368d75effSDimitry Andric 19468d75effSDimitry Andric bool WriteToFile(fd_t fd, const void *buff, uptr buff_size, uptr *bytes_written, 19568d75effSDimitry Andric error_t *error_p) { 19668d75effSDimitry Andric uptr res = internal_write(fd, buff, buff_size); 19768d75effSDimitry Andric if (internal_iserror(res, error_p)) 19868d75effSDimitry Andric return false; 19968d75effSDimitry Andric if (bytes_written) 20068d75effSDimitry Andric *bytes_written = res; 20168d75effSDimitry Andric return true; 20268d75effSDimitry Andric } 20368d75effSDimitry Andric 20468d75effSDimitry Andric void *MapFileToMemory(const char *file_name, uptr *buff_size) { 20568d75effSDimitry Andric fd_t fd = OpenFile(file_name, RdOnly); 20668d75effSDimitry Andric CHECK(fd != kInvalidFd); 20768d75effSDimitry Andric uptr fsize = internal_filesize(fd); 20868d75effSDimitry Andric CHECK_NE(fsize, (uptr)-1); 20968d75effSDimitry Andric CHECK_GT(fsize, 0); 21068d75effSDimitry Andric *buff_size = RoundUpTo(fsize, GetPageSizeCached()); 21168d75effSDimitry Andric uptr map = internal_mmap(nullptr, *buff_size, PROT_READ, MAP_PRIVATE, fd, 0); 21268d75effSDimitry Andric return internal_iserror(map) ? nullptr : (void *)map; 21368d75effSDimitry Andric } 21468d75effSDimitry Andric 21568d75effSDimitry Andric void *MapWritableFileToMemory(void *addr, uptr size, fd_t fd, OFF_T offset) { 21668d75effSDimitry Andric uptr flags = MAP_SHARED; 21768d75effSDimitry Andric if (addr) flags |= MAP_FIXED; 21868d75effSDimitry Andric uptr p = internal_mmap(addr, size, PROT_READ | PROT_WRITE, flags, fd, offset); 21968d75effSDimitry Andric int mmap_errno = 0; 22068d75effSDimitry Andric if (internal_iserror(p, &mmap_errno)) { 22168d75effSDimitry Andric Printf("could not map writable file (%d, %lld, %zu): %zd, errno: %d\n", 22268d75effSDimitry Andric fd, (long long)offset, size, p, mmap_errno); 22368d75effSDimitry Andric return nullptr; 22468d75effSDimitry Andric } 22568d75effSDimitry Andric return (void *)p; 22668d75effSDimitry Andric } 22768d75effSDimitry Andric 22868d75effSDimitry Andric static inline bool IntervalsAreSeparate(uptr start1, uptr end1, 22968d75effSDimitry Andric uptr start2, uptr end2) { 23068d75effSDimitry Andric CHECK(start1 <= end1); 23168d75effSDimitry Andric CHECK(start2 <= end2); 23268d75effSDimitry Andric return (end1 < start2) || (end2 < start1); 23368d75effSDimitry Andric } 23468d75effSDimitry Andric 23568d75effSDimitry Andric // FIXME: this is thread-unsafe, but should not cause problems most of the time. 23668d75effSDimitry Andric // When the shadow is mapped only a single thread usually exists (plus maybe 23768d75effSDimitry Andric // several worker threads on Mac, which aren't expected to map big chunks of 23868d75effSDimitry Andric // memory). 23968d75effSDimitry Andric bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) { 24068d75effSDimitry Andric MemoryMappingLayout proc_maps(/*cache_enabled*/true); 24168d75effSDimitry Andric if (proc_maps.Error()) 24268d75effSDimitry Andric return true; // and hope for the best 24368d75effSDimitry Andric MemoryMappedSegment segment; 24468d75effSDimitry Andric while (proc_maps.Next(&segment)) { 24568d75effSDimitry Andric if (segment.start == segment.end) continue; // Empty range. 24668d75effSDimitry Andric CHECK_NE(0, segment.end); 24768d75effSDimitry Andric if (!IntervalsAreSeparate(segment.start, segment.end - 1, range_start, 24868d75effSDimitry Andric range_end)) 24968d75effSDimitry Andric return false; 25068d75effSDimitry Andric } 25168d75effSDimitry Andric return true; 25268d75effSDimitry Andric } 25368d75effSDimitry Andric 25481ad6265SDimitry Andric #if !SANITIZER_APPLE 25568d75effSDimitry Andric void DumpProcessMap() { 25668d75effSDimitry Andric MemoryMappingLayout proc_maps(/*cache_enabled*/true); 25768d75effSDimitry Andric const sptr kBufSize = 4095; 25868d75effSDimitry Andric char *filename = (char*)MmapOrDie(kBufSize, __func__); 25968d75effSDimitry Andric MemoryMappedSegment segment(filename, kBufSize); 26068d75effSDimitry Andric Report("Process memory map follows:\n"); 26168d75effSDimitry Andric while (proc_maps.Next(&segment)) { 26268d75effSDimitry Andric Printf("\t%p-%p\t%s\n", (void *)segment.start, (void *)segment.end, 26368d75effSDimitry Andric segment.filename); 26468d75effSDimitry Andric } 26568d75effSDimitry Andric Report("End of process memory map.\n"); 26668d75effSDimitry Andric UnmapOrDie(filename, kBufSize); 26768d75effSDimitry Andric } 268e8d8bef9SDimitry Andric #endif 26968d75effSDimitry Andric 27068d75effSDimitry Andric const char *GetPwd() { 27168d75effSDimitry Andric return GetEnv("PWD"); 27268d75effSDimitry Andric } 27368d75effSDimitry Andric 27468d75effSDimitry Andric bool IsPathSeparator(const char c) { 27568d75effSDimitry Andric return c == '/'; 27668d75effSDimitry Andric } 27768d75effSDimitry Andric 27868d75effSDimitry Andric bool IsAbsolutePath(const char *path) { 27968d75effSDimitry Andric return path != nullptr && IsPathSeparator(path[0]); 28068d75effSDimitry Andric } 28168d75effSDimitry Andric 28268d75effSDimitry Andric void ReportFile::Write(const char *buffer, uptr length) { 28368d75effSDimitry Andric SpinMutexLock l(mu); 28468d75effSDimitry Andric ReopenIfNecessary(); 28568d75effSDimitry Andric internal_write(fd, buffer, length); 28668d75effSDimitry Andric } 28768d75effSDimitry Andric 28868d75effSDimitry Andric bool GetCodeRangeForFile(const char *module, uptr *start, uptr *end) { 28968d75effSDimitry Andric MemoryMappingLayout proc_maps(/*cache_enabled*/false); 290fe6060f1SDimitry Andric InternalMmapVector<char> buff(kMaxPathLength); 291fe6060f1SDimitry Andric MemoryMappedSegment segment(buff.data(), buff.size()); 29268d75effSDimitry Andric while (proc_maps.Next(&segment)) { 29368d75effSDimitry Andric if (segment.IsExecutable() && 29468d75effSDimitry Andric internal_strcmp(module, segment.filename) == 0) { 29568d75effSDimitry Andric *start = segment.start; 29668d75effSDimitry Andric *end = segment.end; 29768d75effSDimitry Andric return true; 29868d75effSDimitry Andric } 29968d75effSDimitry Andric } 30068d75effSDimitry Andric return false; 30168d75effSDimitry Andric } 30268d75effSDimitry Andric 30368d75effSDimitry Andric uptr SignalContext::GetAddress() const { 30468d75effSDimitry Andric auto si = static_cast<const siginfo_t *>(siginfo); 30568d75effSDimitry Andric return (uptr)si->si_addr; 30668d75effSDimitry Andric } 30768d75effSDimitry Andric 30868d75effSDimitry Andric bool SignalContext::IsMemoryAccess() const { 30968d75effSDimitry Andric auto si = static_cast<const siginfo_t *>(siginfo); 310e8d8bef9SDimitry Andric return si->si_signo == SIGSEGV || si->si_signo == SIGBUS; 31168d75effSDimitry Andric } 31268d75effSDimitry Andric 31368d75effSDimitry Andric int SignalContext::GetType() const { 31468d75effSDimitry Andric return static_cast<const siginfo_t *>(siginfo)->si_signo; 31568d75effSDimitry Andric } 31668d75effSDimitry Andric 31768d75effSDimitry Andric const char *SignalContext::Describe() const { 31868d75effSDimitry Andric switch (GetType()) { 31968d75effSDimitry Andric case SIGFPE: 32068d75effSDimitry Andric return "FPE"; 32168d75effSDimitry Andric case SIGILL: 32268d75effSDimitry Andric return "ILL"; 32368d75effSDimitry Andric case SIGABRT: 32468d75effSDimitry Andric return "ABRT"; 32568d75effSDimitry Andric case SIGSEGV: 32668d75effSDimitry Andric return "SEGV"; 32768d75effSDimitry Andric case SIGBUS: 32868d75effSDimitry Andric return "BUS"; 32968d75effSDimitry Andric case SIGTRAP: 33068d75effSDimitry Andric return "TRAP"; 33168d75effSDimitry Andric } 33268d75effSDimitry Andric return "UNKNOWN SIGNAL"; 33368d75effSDimitry Andric } 33468d75effSDimitry Andric 33568d75effSDimitry Andric fd_t ReserveStandardFds(fd_t fd) { 33668d75effSDimitry Andric CHECK_GE(fd, 0); 33768d75effSDimitry Andric if (fd > 2) 33868d75effSDimitry Andric return fd; 33968d75effSDimitry Andric bool used[3]; 34068d75effSDimitry Andric internal_memset(used, 0, sizeof(used)); 34168d75effSDimitry Andric while (fd <= 2) { 34268d75effSDimitry Andric used[fd] = true; 34368d75effSDimitry Andric fd = internal_dup(fd); 34468d75effSDimitry Andric } 34568d75effSDimitry Andric for (int i = 0; i <= 2; ++i) 34668d75effSDimitry Andric if (used[i]) 34768d75effSDimitry Andric internal_close(i); 34868d75effSDimitry Andric return fd; 34968d75effSDimitry Andric } 35068d75effSDimitry Andric 35168d75effSDimitry Andric bool ShouldMockFailureToOpen(const char *path) { 35268d75effSDimitry Andric return common_flags()->test_only_emulate_no_memorymap && 35368d75effSDimitry Andric internal_strncmp(path, "/proc/", 6) == 0; 35468d75effSDimitry Andric } 35568d75effSDimitry Andric 35668d75effSDimitry Andric #if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_GO 35768d75effSDimitry Andric int GetNamedMappingFd(const char *name, uptr size, int *flags) { 35868d75effSDimitry Andric if (!common_flags()->decorate_proc_maps || !name) 35968d75effSDimitry Andric return -1; 36068d75effSDimitry Andric char shmname[200]; 36168d75effSDimitry Andric CHECK(internal_strlen(name) < sizeof(shmname) - 10); 36268d75effSDimitry Andric internal_snprintf(shmname, sizeof(shmname), "/dev/shm/%zu [%s]", 36368d75effSDimitry Andric internal_getpid(), name); 3645ffd83dbSDimitry Andric int o_cloexec = 0; 3655ffd83dbSDimitry Andric #if defined(O_CLOEXEC) 3665ffd83dbSDimitry Andric o_cloexec = O_CLOEXEC; 3675ffd83dbSDimitry Andric #endif 36868d75effSDimitry Andric int fd = ReserveStandardFds( 3695ffd83dbSDimitry Andric internal_open(shmname, O_RDWR | O_CREAT | O_TRUNC | o_cloexec, S_IRWXU)); 37068d75effSDimitry Andric CHECK_GE(fd, 0); 37168d75effSDimitry Andric int res = internal_ftruncate(fd, size); 372e8d8bef9SDimitry Andric #if !defined(O_CLOEXEC) 373e8d8bef9SDimitry Andric res = fcntl(fd, F_SETFD, FD_CLOEXEC); 374e8d8bef9SDimitry Andric CHECK_EQ(0, res); 375e8d8bef9SDimitry Andric #endif 37668d75effSDimitry Andric CHECK_EQ(0, res); 37768d75effSDimitry Andric res = internal_unlink(shmname); 37868d75effSDimitry Andric CHECK_EQ(0, res); 37968d75effSDimitry Andric *flags &= ~(MAP_ANON | MAP_ANONYMOUS); 38068d75effSDimitry Andric return fd; 38168d75effSDimitry Andric } 38268d75effSDimitry Andric #else 38368d75effSDimitry Andric int GetNamedMappingFd(const char *name, uptr size, int *flags) { 38468d75effSDimitry Andric return -1; 38568d75effSDimitry Andric } 38668d75effSDimitry Andric #endif 38768d75effSDimitry Andric 38868d75effSDimitry Andric #if SANITIZER_ANDROID 38968d75effSDimitry Andric #define PR_SET_VMA 0x53564d41 39068d75effSDimitry Andric #define PR_SET_VMA_ANON_NAME 0 39168d75effSDimitry Andric void DecorateMapping(uptr addr, uptr size, const char *name) { 39268d75effSDimitry Andric if (!common_flags()->decorate_proc_maps || !name) 39368d75effSDimitry Andric return; 39468d75effSDimitry Andric internal_prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, addr, size, (uptr)name); 39568d75effSDimitry Andric } 39668d75effSDimitry Andric #else 39768d75effSDimitry Andric void DecorateMapping(uptr addr, uptr size, const char *name) { 39868d75effSDimitry Andric } 39968d75effSDimitry Andric #endif 40068d75effSDimitry Andric 40168d75effSDimitry Andric uptr MmapNamed(void *addr, uptr length, int prot, int flags, const char *name) { 40268d75effSDimitry Andric int fd = GetNamedMappingFd(name, length, &flags); 40368d75effSDimitry Andric uptr res = internal_mmap(addr, length, prot, flags, fd, 0); 40468d75effSDimitry Andric if (!internal_iserror(res)) 40568d75effSDimitry Andric DecorateMapping(res, length, name); 40668d75effSDimitry Andric return res; 40768d75effSDimitry Andric } 40868d75effSDimitry Andric 40968d75effSDimitry Andric 41068d75effSDimitry Andric } // namespace __sanitizer 41168d75effSDimitry Andric 41268d75effSDimitry Andric #endif // SANITIZER_POSIX 413