tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

AutoMemMap.cpp (2861B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "AutoMemMap.h"
      8 #include "ScriptPreloader-inl.h"
      9 
     10 #include "mozilla/Try.h"
     11 #include "mozilla/ipc/FileDescriptor.h"
     12 #include "nsIFile.h"
     13 
     14 #include <private/pprio.h>
     15 
     16 namespace mozilla {
     17 namespace loader {
     18 
     19 using namespace mozilla::ipc;
     20 
     21 AutoMemMap::~AutoMemMap() { reset(); }
     22 
     23 FileDescriptor AutoMemMap::cloneFileDescriptor() const {
     24  if (fd.get()) {
     25    auto handle =
     26        FileDescriptor::PlatformHandleType(PR_FileDesc2NativeHandle(fd.get()));
     27    return FileDescriptor(handle);
     28  }
     29  return FileDescriptor();
     30 }
     31 
     32 Result<Ok, nsresult> AutoMemMap::init(nsIFile* file, int flags, int mode,
     33                                      PRFileMapProtect prot) {
     34  MOZ_ASSERT(!fd);
     35 
     36  MOZ_TRY(file->OpenNSPRFileDesc(flags, mode, getter_Transfers(fd)));
     37 
     38  return initInternal(prot);
     39 }
     40 
     41 Result<Ok, nsresult> AutoMemMap::init(const FileDescriptor& file,
     42                                      PRFileMapProtect prot, size_t maybeSize) {
     43  MOZ_ASSERT(!fd);
     44  if (!file.IsValid()) {
     45    return Err(NS_ERROR_INVALID_ARG);
     46  }
     47 
     48  auto handle = file.ClonePlatformHandle();
     49 
     50  fd.reset(PR_ImportFile(PROsfd(handle.get())));
     51  if (!fd) {
     52    return Err(NS_ERROR_FAILURE);
     53  }
     54  (void)handle.release();
     55 
     56  return initInternal(prot, maybeSize);
     57 }
     58 
     59 Result<Ok, nsresult> AutoMemMap::initInternal(PRFileMapProtect prot,
     60                                              size_t maybeSize) {
     61  MOZ_ASSERT(!fileMap);
     62  MOZ_ASSERT(!addr);
     63 
     64  if (maybeSize > 0) {
     65    // Some OSes' shared memory objects can't be stat()ed, either at
     66    // all (Android) or without loosening the sandbox (Mac) so just
     67    // use the size.
     68    size_ = maybeSize;
     69  } else {
     70    // But if we don't have the size, assume it's a regular file and
     71    // ask for it.
     72    PRFileInfo64 fileInfo;
     73    MOZ_TRY(PR_GetOpenFileInfo64(fd.get(), &fileInfo));
     74 
     75    if (fileInfo.size > UINT32_MAX) {
     76      return Err(NS_ERROR_INVALID_ARG);
     77    }
     78    size_ = fileInfo.size;
     79  }
     80 
     81  fileMap = PR_CreateFileMap(fd.get(), 0, prot);
     82  if (!fileMap) {
     83    return Err(NS_ERROR_FAILURE);
     84  }
     85 
     86  addr = PR_MemMap(fileMap, 0, size_);
     87  if (!addr) {
     88    return Err(NS_ERROR_FAILURE);
     89  }
     90 
     91  return Ok();
     92 }
     93 
     94 FileDescriptor AutoMemMap::cloneHandle() const { return cloneFileDescriptor(); }
     95 
     96 void AutoMemMap::reset() {
     97  if (addr && !persistent_) {
     98    (void)NS_WARN_IF(PR_MemUnmap(addr, size()) != PR_SUCCESS);
     99    addr = nullptr;
    100  }
    101  if (fileMap) {
    102    (void)NS_WARN_IF(PR_CloseFileMap(fileMap) != PR_SUCCESS);
    103    fileMap = nullptr;
    104  }
    105  fd = nullptr;
    106 }
    107 
    108 }  // namespace loader
    109 }  // namespace mozilla