v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
memory-protection-key.cc
Go to the documentation of this file.
1// Copyright 2021 the V8 project 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
6
7#if V8_HAS_PKU_JIT_WRITE_PROTECT
8
9#include <sys/mman.h> // For {mprotect()} protection macros.
10#undef MAP_TYPE // Conflicts with MAP_TYPE in Torque-generated instance-types.h
11
12#include "src/base/logging.h"
13#include "src/base/macros.h"
14
15// Declare all the pkey functions as weak to support older glibc versions where
16// they don't exist yet.
17int pkey_mprotect(void* addr, size_t len, int prot, int pkey) V8_WEAK;
18int pkey_get(int key) V8_WEAK;
19int pkey_set(int, unsigned) V8_WEAK;
20int pkey_alloc(unsigned int, unsigned int) V8_WEAK;
21
22namespace v8 {
23namespace base {
24
25namespace {
26
28 // Mappings for PKU are either RWX (for code), no access (for uncommitted
29 // memory), or RO for globals.
30 switch (permission) {
32 return PROT_NONE;
34 return PROT_READ;
36 return PROT_READ | PROT_WRITE;
38 return PROT_READ | PROT_WRITE | PROT_EXEC;
39 default:
41 }
42}
43
44} // namespace
45
46bool MemoryProtectionKey::HasMemoryProtectionKeySupport() {
47 if (!pkey_mprotect) return false;
48 // If {pkey_mprotect} is available, the others must also be available.
49 CHECK(pkey_get && pkey_set && pkey_alloc);
50
51 return true;
52}
53
54// static
55int MemoryProtectionKey::AllocateKey() {
56 if (!pkey_alloc) {
57 return kNoMemoryProtectionKey;
58 }
59
60 return pkey_alloc(0, 0);
61}
62
63// static
64bool MemoryProtectionKey::SetPermissionsAndKey(
65 base::AddressRegion region, v8::PageAllocator::Permission page_permissions,
66 int key) {
67 DCHECK_NE(key, kNoMemoryProtectionKey);
68 CHECK_NOT_NULL(pkey_mprotect);
69
70 void* address = reinterpret_cast<void*>(region.begin());
71 size_t size = region.size();
72
73 int protection = GetProtectionFromMemoryPermission(page_permissions);
74
75 return pkey_mprotect(address, size, protection, key) == 0;
76}
77
78// static
79void MemoryProtectionKey::SetPermissionsForKey(int key,
80 Permission permissions) {
81 DCHECK_NE(kNoMemoryProtectionKey, key);
82
83 // If a valid key was allocated, {pkey_set()} must also be available.
84 DCHECK_NOT_NULL(pkey_set);
85
86 CHECK_EQ(0 /* success */, pkey_set(key, permissions));
87}
88
89// static
90MemoryProtectionKey::Permission MemoryProtectionKey::GetKeyPermission(int key) {
91 DCHECK_NE(kNoMemoryProtectionKey, key);
92
93 // If a valid key was allocated, {pkey_get()} must also be available.
94 DCHECK_NOT_NULL(pkey_get);
95
96 int permission = pkey_get(key);
97 CHECK(permission == kNoRestrictions || permission == kDisableAccess ||
98 permission == kDisableWrite);
99 return static_cast<Permission>(permission);
100}
101
102} // namespace base
103} // namespace v8
104
105#endif // V8_HAS_PKU_JIT_WRITE_PROTECT
int GetProtectionFromMemoryPermission(OS::MemoryPermission access)
#define UNREACHABLE()
Definition logging.h:67
#define CHECK(condition)
Definition logging.h:124
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define CHECK_NOT_NULL(val)
#define DCHECK_NE(v1, v2)
Definition logging.h:486
#define CHECK_EQ(lhs, rhs)
#define V8_WEAK
Definition v8config.h:679
std::unique_ptr< ValueMirror > key