brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.2 KiB · df3e54c Raw
159 lines · cpp
1//===-- mem_map_linux.cpp ---------------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "platform.h"10 11#if SCUDO_LINUX12 13#include "mem_map_linux.h"14 15#include "common.h"16#include "internal_defs.h"17#include "linux.h"18#include "mutex.h"19#include "report_linux.h"20#include "string_utils.h"21 22#include <errno.h>23#include <fcntl.h>24#include <linux/futex.h>25#include <sched.h>26#include <stdio.h>27#include <stdlib.h>28#include <string.h>29#include <sys/mman.h>30#include <sys/stat.h>31#include <sys/syscall.h>32#include <sys/time.h>33#include <time.h>34#include <unistd.h>35 36#if SCUDO_ANDROID37// TODO(chiahungduan): Review if we still need the followings macros.38#include <sys/prctl.h>39// Definitions of prctl arguments to set a vma name in Android kernels.40#define ANDROID_PR_SET_VMA 0x53564d4141#define ANDROID_PR_SET_VMA_ANON_NAME 042#endif43 44namespace scudo {45 46static void *mmapWrapper(uptr Addr, uptr Size, const char *Name, uptr Flags) {47  int MmapFlags = MAP_PRIVATE | MAP_ANONYMOUS;48  int MmapProt;49  if (Flags & MAP_NOACCESS) {50    MmapFlags |= MAP_NORESERVE;51    MmapProt = PROT_NONE;52  } else {53    MmapProt = PROT_READ | PROT_WRITE;54  }55#if defined(__aarch64__)56#ifndef PROT_MTE57#define PROT_MTE 0x2058#endif59  if (Flags & MAP_MEMTAG)60    MmapProt |= PROT_MTE;61#endif62  if (Addr)63    MmapFlags |= MAP_FIXED;64  void *P =65      mmap(reinterpret_cast<void *>(Addr), Size, MmapProt, MmapFlags, -1, 0);66  if (P == MAP_FAILED) {67    if (!(Flags & MAP_ALLOWNOMEM) || errno != ENOMEM)68      reportMapError(errno == ENOMEM ? Size : 0);69    return nullptr;70  }71#if SCUDO_ANDROID72  if (Name)73    prctl(ANDROID_PR_SET_VMA, ANDROID_PR_SET_VMA_ANON_NAME, P, Size, Name);74#else75  (void)Name;76#endif77 78  return P;79}80 81bool MemMapLinux::mapImpl(uptr Addr, uptr Size, const char *Name, uptr Flags) {82  void *P = mmapWrapper(Addr, Size, Name, Flags);83  if (P == nullptr)84    return false;85 86  MapBase = reinterpret_cast<uptr>(P);87  MapCapacity = Size;88  return true;89}90 91void MemMapLinux::unmapImpl(uptr Addr, uptr Size) {92  // If we unmap all the pages, also mark `MapBase` to 0 to indicate invalid93  // status.94  if (Size == MapCapacity) {95    MapBase = MapCapacity = 0;96  } else {97    // This is partial unmap and is unmapping the pages from the beginning,98    // shift `MapBase` to the new base.99    if (MapBase == Addr)100      MapBase = Addr + Size;101    MapCapacity -= Size;102  }103 104  if (munmap(reinterpret_cast<void *>(Addr), Size) != 0)105    reportUnmapError(Addr, Size);106}107 108bool MemMapLinux::remapImpl(uptr Addr, uptr Size, const char *Name,109                            uptr Flags) {110  void *P = mmapWrapper(Addr, Size, Name, Flags);111  if (reinterpret_cast<uptr>(P) != Addr)112    reportMapError();113  return true;114}115 116void MemMapLinux::setMemoryPermissionImpl(uptr Addr, uptr Size, uptr Flags) {117  int Prot = (Flags & MAP_NOACCESS) ? PROT_NONE : (PROT_READ | PROT_WRITE);118  if (mprotect(reinterpret_cast<void *>(Addr), Size, Prot) != 0)119    reportProtectError(Addr, Size, Prot);120}121 122void MemMapLinux::releaseAndZeroPagesToOSImpl(uptr From, uptr Size) {123  void *Addr = reinterpret_cast<void *>(From);124 125  int rc;126  while ((rc = madvise(Addr, Size, MADV_DONTNEED)) == -1 && errno == EAGAIN) {127  }128  if (rc == -1) {129    // If we can't madvies the memory, then we still need to zero it.130    memset(Addr, 0, Size);131  }132}133 134bool ReservedMemoryLinux::createImpl(uptr Addr, uptr Size, const char *Name,135                                     uptr Flags) {136  ReservedMemoryLinux::MemMapT MemMap;137  if (!MemMap.map(Addr, Size, Name, Flags | MAP_NOACCESS))138    return false;139 140  MapBase = MemMap.getBase();141  MapCapacity = MemMap.getCapacity();142 143  return true;144}145 146void ReservedMemoryLinux::releaseImpl() {147  if (munmap(reinterpret_cast<void *>(getBase()), getCapacity()) != 0)148    reportUnmapError(getBase(), getCapacity());149}150 151ReservedMemoryLinux::MemMapT ReservedMemoryLinux::dispatchImpl(uptr Addr,152                                                               uptr Size) {153  return ReservedMemoryLinux::MemMapT(Addr, Size);154}155 156} // namespace scudo157 158#endif // SCUDO_LINUX159