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