• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_PKEY_H_
6 #define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PKEY_H_
7 
8 #include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
9 
10 #if BUILDFLAG(ENABLE_PKEYS)
11 
12 #include "base/allocator/partition_allocator/page_allocator_constants.h"
13 #include "base/allocator/partition_allocator/partition_alloc_base/component_export.h"
14 #include "base/allocator/partition_allocator/partition_alloc_base/debug/debugging_buildflags.h"
15 
16 #include <cstddef>
17 #include <cstdint>
18 
19 #if !BUILDFLAG(HAS_64_BIT_POINTERS)
20 #error "pkey support requires 64 bit pointers"
21 #endif
22 
23 #define PA_PKEY_ALIGN_SZ SystemPageSize()
24 #define PA_PKEY_ALIGN_OFFSET_MASK (PA_PKEY_ALIGN_SZ - 1)
25 #define PA_PKEY_ALIGN_BASE_MASK (~PA_PKEY_ALIGN_OFFSET_MASK)
26 #define PA_PKEY_ALIGN alignas(PA_PKEY_ALIGN_SZ)
27 
28 #define PA_PKEY_FILL_PAGE_SZ(size) \
29   ((PA_PKEY_ALIGN_SZ - (size & PA_PKEY_ALIGN_OFFSET_MASK)) % PA_PKEY_ALIGN_SZ)
30 // Calculate the required padding so that the last element of a page-aligned
31 // array lands on a page boundary. In other words, calculate that padding so
32 // that (count-1) elements are a multiple of page size.
33 #define PA_PKEY_ARRAY_PAD_SZ(Type, count) \
34   PA_PKEY_FILL_PAGE_SZ(sizeof(Type) * (count - 1))
35 
36 namespace partition_alloc::internal {
37 
38 constexpr int kDefaultPkey = 0;
39 constexpr int kInvalidPkey = -1;
40 
41 // Check if the CPU supports pkeys.
42 bool CPUHasPkeySupport();
43 
44 // A wrapper around pkey_mprotect that falls back to regular mprotect if
45 // PkeySettings::enabled is false.
46 [[nodiscard]] int PkeyMprotectIfEnabled(void* addr,
47                                         size_t len,
48                                         int prot,
49                                         int pkey);
50 // A wrapper around pkey_mprotect without fallback.
51 [[nodiscard]] int PkeyMprotect(void* addr, size_t len, int prot, int pkey);
52 
53 // If we set up a pkey pool, we need to tag global variables with the pkey to
54 // make them readable in case default pkey access is disabled. Called once
55 // during pkey pool initialization.
56 void TagGlobalsWithPkey(int pkey);
57 
58 int PkeyAlloc(int access_rights);
59 
60 void PkeyFree(int pkey);
61 
62 // Read the pkru register (the current pkey state).
63 uint32_t Rdpkru();
64 
65 // Write the pkru register (the current pkey state).
66 void Wrpkru(uint32_t pkru);
67 
68 struct PkeySettings {
69   bool enabled = false;
70   char pad_[PA_PKEY_FILL_PAGE_SZ(sizeof(enabled))] = {};
71   static PkeySettings settings PA_PKEY_ALIGN PA_CONSTINIT;
72 };
73 
74 #if BUILDFLAG(PA_DCHECK_IS_ON)
75 
PA_COMPONENT_EXPORT(PARTITION_ALLOC)76 class PA_COMPONENT_EXPORT(PARTITION_ALLOC) LiftPkeyRestrictionsScope {
77  public:
78   static constexpr uint32_t kDefaultPkeyValue = 0x55555554;
79   static constexpr uint32_t kAllowAllPkeyValue = 0x0;
80 
81   LiftPkeyRestrictionsScope();
82   ~LiftPkeyRestrictionsScope();
83 
84  private:
85   uint32_t saved_pkey_value_;
86 };
87 
88 #endif  // BUILDFLAG(PA_DCHECK_IS_ON)
89 
90 }  // namespace partition_alloc::internal
91 
92 #else  // BUILDFLAG(ENABLE_PKEYS)
93 #define PA_PKEY_ALIGN
94 #define PA_PKEY_FILL_PAGE_SZ(size) 0
95 #define PA_PKEY_ARRAY_PAD_SZ(Type, size) 0
96 #endif  // BUILDFLAG(ENABLE_PKEYS)
97 
98 #endif  // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PKEY_H_
99