• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
5 #if !V8_ENABLE_WEBASSEMBLY
6 #error This header should only be included if WebAssembly is enabled.
7 #endif  // !V8_ENABLE_WEBASSEMBLY
8 
9 #ifndef V8_WASM_MEMORY_PROTECTION_KEY_H_
10 #define V8_WASM_MEMORY_PROTECTION_KEY_H_
11 
12 #if defined(V8_OS_LINUX) && defined(V8_HOST_ARCH_X64)
13 #include <sys/mman.h>  // For STATIC_ASSERT of permission values.
14 #undef MAP_TYPE  // Conflicts with MAP_TYPE in Torque-generated instance-types.h
15 #endif
16 
17 #include "include/v8-platform.h"
18 #include "src/base/address-region.h"
19 
20 namespace v8 {
21 namespace internal {
22 namespace wasm {
23 
24 // TODO(dlehmann): Move this to base/platform/platform.h {OS} (lower-level API)
25 // and {base::PageAllocator} (higher-level, exported API) once the API is more
26 // stable and we have converged on a better design (e.g., typed class wrapper
27 // around int memory protection key).
28 
29 // Sentinel value if there is no PKU support or allocation of a key failed.
30 // This is also the return value on an error of pkey_alloc() and has the
31 // benefit that calling pkey_mprotect() with -1 behaves the same as regular
32 // mprotect().
33 constexpr int kNoMemoryProtectionKey = -1;
34 
35 // Permissions for memory protection keys on top of the page's permissions.
36 // NOTE: Since there is no executable bit, the executable permission cannot be
37 // withdrawn by memory protection keys.
38 enum MemoryProtectionKeyPermission {
39   kNoRestrictions = 0,
40   kDisableAccess = 1,
41   kDisableWrite = 2,
42 };
43 
44 // If sys/mman.h has PKEY support (on newer Linux distributions), ensure that
45 // our definitions of the permissions is consistent with the ones in glibc.
46 #if defined(PKEY_DISABLE_ACCESS)
47 STATIC_ASSERT(kDisableAccess == PKEY_DISABLE_ACCESS);
48 STATIC_ASSERT(kDisableWrite == PKEY_DISABLE_WRITE);
49 #endif
50 
51 // Call exactly once per process to determine if PKU is supported on this
52 // platform and initialize global data structures.
53 void InitializeMemoryProtectionKeySupport();
54 
55 // Allocates a memory protection key on platforms with PKU support, returns
56 // {kNoMemoryProtectionKey} on platforms without support or when allocation
57 // failed at runtime.
58 int AllocateMemoryProtectionKey();
59 
60 // Frees the given memory protection key, to make it available again for the
61 // next call to {AllocateMemoryProtectionKey()}. Note that this does NOT
62 // invalidate access rights to pages that are still tied to that key. That is,
63 // if the key is reused and pages with that key are still accessable, this might
64 // be a security issue. See
65 // https://www.gnu.org/software/libc/manual/html_mono/libc.html#Memory-Protection-Keys
66 void FreeMemoryProtectionKey(int key);
67 
68 // Associates a memory protection {key} with the given {region}.
69 // If {key} is {kNoMemoryProtectionKey} this behaves like "plain"
70 // {SetPermissions()} and associates the default key to the region. That is,
71 // explicitly calling with {kNoMemoryProtectionKey} can be used to disassociate
72 // any protection key from a region. This also means "plain" {SetPermissions()}
73 // disassociates the key from a region, making the key's access restrictions
74 // irrelevant/inactive for that region.
75 // Returns true if changing permissions and key was successful. (Returns a bool
76 // to be consistent with {SetPermissions()}).
77 // The {page_permissions} are the permissions of the page, not the key. For
78 // changing the permissions of the key, use
79 // {SetPermissionsForMemoryProtectionKey()} instead.
80 bool SetPermissionsAndMemoryProtectionKey(
81     PageAllocator* page_allocator, base::AddressRegion region,
82     PageAllocator::Permission page_permissions, int key);
83 
84 // Set the key's permissions. {key} must be valid, i.e. not
85 // {kNoMemoryProtectionKey}.
86 void SetPermissionsForMemoryProtectionKey(
87     int key, MemoryProtectionKeyPermission permissions);
88 
89 // Get the permissions of the protection key {key} for the current thread.
90 MemoryProtectionKeyPermission GetMemoryProtectionKeyPermission(int key);
91 
92 }  // namespace wasm
93 }  // namespace internal
94 }  // namespace v8
95 
96 #endif  // V8_WASM_MEMORY_PROTECTION_KEY_H_
97