1 // Copyright 2017 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 "base/memory/protected_memory.h"
6 
7 #include <stdint.h>
8 #include <sys/mman.h>
9 #include <unistd.h>
10 
11 #if defined(OS_LINUX)
12 #include <sys/resource.h>
13 #endif  // defined(OS_LINUX)
14 
15 #if defined(OS_MACOSX) && !defined(OS_IOS)
16 #include <mach/mach.h>
17 #include <mach/mach_vm.h>
18 #endif  // defined(OS_MACOSX) && !defined(OS_IOS)
19 
20 #include "base/posix/eintr_wrapper.h"
21 #include "base/process/process_metrics.h"
22 #include "base/synchronization/lock.h"
23 #include "build/build_config.h"
24 
25 namespace base {
26 
27 namespace {
28 
SetMemory(void * start,void * end,int prot)29 bool SetMemory(void* start, void* end, int prot) {
30   DCHECK(end > start);
31   const uintptr_t page_mask = ~(base::GetPageSize() - 1);
32   const uintptr_t page_start = reinterpret_cast<uintptr_t>(start) & page_mask;
33   return mprotect(reinterpret_cast<void*>(page_start),
34                   reinterpret_cast<uintptr_t>(end) - page_start, prot) == 0;
35 }
36 
37 }  // namespace
38 
SetMemoryReadWrite(void * start,void * end)39 bool AutoWritableMemory::SetMemoryReadWrite(void* start, void* end) {
40   return SetMemory(start, end, PROT_READ | PROT_WRITE);
41 }
42 
SetMemoryReadOnly(void * start,void * end)43 bool AutoWritableMemory::SetMemoryReadOnly(void* start, void* end) {
44   return SetMemory(start, end, PROT_READ);
45 }
46 
47 #if defined(OS_LINUX)
AssertMemoryIsReadOnly(const void * ptr)48 void AssertMemoryIsReadOnly(const void* ptr) {
49 #if DCHECK_IS_ON()
50   const uintptr_t page_mask = ~(base::GetPageSize() - 1);
51   const uintptr_t page_start = reinterpret_cast<uintptr_t>(ptr) & page_mask;
52 
53   // Note: We've casted away const here, which should not be meaningful since
54   // if the memory is written to we will abort immediately.
55   int result =
56       getrlimit(RLIMIT_NPROC, reinterpret_cast<struct rlimit*>(page_start));
57   DCHECK_EQ(result, -1);
58   DCHECK_EQ(errno, EFAULT);
59 #endif  // DCHECK_IS_ON()
60 }
61 #elif defined(OS_MACOSX) && !defined(OS_IOS)
AssertMemoryIsReadOnly(const void * ptr)62 void AssertMemoryIsReadOnly(const void* ptr) {
63 #if DCHECK_IS_ON()
64   mach_port_t object_name;
65   vm_region_basic_info_64 region_info;
66   mach_vm_size_t size = 1;
67   mach_msg_type_number_t count = VM_REGION_BASIC_INFO_COUNT_64;
68 
69   kern_return_t kr = mach_vm_region(
70       mach_task_self(), reinterpret_cast<mach_vm_address_t*>(&ptr), &size,
71       VM_REGION_BASIC_INFO_64, reinterpret_cast<vm_region_info_t>(&region_info),
72       &count, &object_name);
73   DCHECK_EQ(kr, KERN_SUCCESS);
74   DCHECK_EQ(region_info.protection, VM_PROT_READ);
75 #endif  // DCHECK_IS_ON()
76 }
77 #endif  // defined(OS_LINUX) || (defined(OS_MACOSX) && !defined(OS_IOS))
78 
79 }  // namespace base
80