Home | History | Annotate | Download | only in nonsfi
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <errno.h>
      6 #include <sys/mman.h>
      7 
      8 #include "base/logging.h"
      9 #include "components/nacl/loader/nonsfi/irt_interfaces.h"
     10 #include "components/nacl/loader/nonsfi/irt_util.h"
     11 #include "native_client/src/trusted/service_runtime/include/machine/_types.h"
     12 #include "native_client/src/trusted/service_runtime/include/sys/mman.h"
     13 
     14 namespace nacl {
     15 namespace nonsfi {
     16 namespace {
     17 
     18 int NaClProtToProt(int nacl_prot) {
     19   int prot = 0;
     20   if ((nacl_prot & NACL_ABI_PROT_MASK) == NACL_ABI_PROT_NONE)
     21     return PROT_NONE;
     22 
     23   if (nacl_prot & NACL_ABI_PROT_READ)
     24     prot |= PROT_READ;
     25   if (nacl_prot & NACL_ABI_PROT_WRITE)
     26     prot |= PROT_WRITE;
     27   if (nacl_prot & NACL_ABI_PROT_EXEC)
     28     prot |= PROT_EXEC;
     29   return prot;
     30 }
     31 
     32 int NaClFlagsToFlags(int nacl_flags) {
     33   int flags = 0;
     34 
     35   if (nacl_flags & NACL_ABI_MAP_SHARED)
     36     flags |= MAP_SHARED;
     37   if (nacl_flags & NACL_ABI_MAP_PRIVATE)
     38     flags |= MAP_PRIVATE;
     39   if (nacl_flags & NACL_ABI_MAP_FIXED)
     40     flags |= MAP_FIXED;
     41 
     42   // Note: NACL_ABI_MAP_ANON is an alias of NACL_ABI_MAP_ANONYMOUS.
     43   if (nacl_flags & NACL_ABI_MAP_ANONYMOUS)
     44     flags |= MAP_ANONYMOUS;
     45   return flags;
     46 }
     47 
     48 int IrtMMap(void** addr, size_t len, int prot, int flags,
     49             int fd, nacl_abi_off_t off) {
     50   const int host_prot = NaClProtToProt(prot);
     51   // On Chrome OS, mmap can fail if PROT_EXEC is set in |host_prot|,
     52   // but mprotect will allow changing the permissions later.
     53   // This is because Chrome OS mounts writable filesystems with "noexec".
     54   void* result = mmap(
     55       *addr, len, host_prot & ~PROT_EXEC, NaClFlagsToFlags(flags), fd, off);
     56   if (result == MAP_FAILED)
     57     return errno;
     58   if (host_prot & PROT_EXEC) {
     59     if (mprotect(result, len, host_prot) != 0) {
     60       // This aborts here because it cannot easily undo the mmap() call.
     61       PLOG(FATAL) << "IrtMMap: mprotect to turn on PROT_EXEC failed.";
     62     }
     63   }
     64 
     65   *addr = result;
     66   return 0;
     67 }
     68 
     69 int IrtMUnmap(void* addr, size_t len) {
     70   return CheckError(munmap(addr, len));
     71 }
     72 
     73 int IrtMProtect(void* addr, size_t len, int prot) {
     74   return CheckError(mprotect(addr, len, NaClProtToProt(prot)));
     75 }
     76 
     77 }  // namespace
     78 
     79 // For mmap, the argument types should be nacl_abi_off_t rather than off_t.
     80 // However, the definition of nacl_irt_memory uses the host type off_t, so here
     81 // we need to cast it.
     82 const nacl_irt_memory kIrtMemory = {
     83   reinterpret_cast<int(*)(void**, size_t, int, int, int, off_t)>(IrtMMap),
     84   IrtMUnmap,
     85   IrtMProtect,
     86 };
     87 
     88 }  // namespace nonsfi
     89 }  // namespace nacl
     90