1 // Copyright 2023 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 #include "partition_alloc/thread_isolation/thread_isolation.h"
6
7 #if BUILDFLAG(ENABLE_THREAD_ISOLATION)
8
9 #include "partition_alloc/address_pool_manager.h"
10 #include "partition_alloc/page_allocator.h"
11 #include "partition_alloc/partition_alloc_check.h"
12 #include "partition_alloc/partition_alloc_constants.h"
13 #include "partition_alloc/reservation_offset_table.h"
14
15 #if BUILDFLAG(ENABLE_PKEYS)
16 #include "partition_alloc/thread_isolation/pkey.h"
17 #endif
18
19 namespace partition_alloc::internal {
20
21 #if BUILDFLAG(PA_DCHECK_IS_ON)
22 ThreadIsolationSettings ThreadIsolationSettings::settings;
23 #endif
24
WriteProtectThreadIsolatedMemory(ThreadIsolationOption thread_isolation,void * address,size_t size,bool read_only=false)25 void WriteProtectThreadIsolatedMemory(ThreadIsolationOption thread_isolation,
26 void* address,
27 size_t size,
28 bool read_only = false) {
29 PA_DCHECK((reinterpret_cast<uintptr_t>(address) &
30 PA_THREAD_ISOLATED_ALIGN_OFFSET_MASK) == 0);
31 if (read_only) {
32 SetSystemPagesAccess(
33 address, size,
34 PageAccessibilityConfiguration(
35 thread_isolation.enabled
36 ? PageAccessibilityConfiguration::Permissions::kRead
37 : PageAccessibilityConfiguration::Permissions::kReadWrite));
38 return;
39 }
40 #if BUILDFLAG(ENABLE_PKEYS)
41 partition_alloc::internal::TagMemoryWithPkey(
42 thread_isolation.enabled ? thread_isolation.pkey : kDefaultPkey, address,
43 size);
44 #else
45 #error unexpected thread isolation mode
46 #endif
47 }
48
49 template <typename T>
WriteProtectThreadIsolatedVariable(ThreadIsolationOption thread_isolation,T & var,size_t offset=0,bool read_only=false)50 void WriteProtectThreadIsolatedVariable(ThreadIsolationOption thread_isolation,
51 T& var,
52 size_t offset = 0,
53 bool read_only = false) {
54 WriteProtectThreadIsolatedMemory(thread_isolation, (char*)&var + offset,
55 sizeof(T) - offset, read_only);
56 }
57
MprotectWithThreadIsolation(void * addr,size_t len,int prot,ThreadIsolationOption thread_isolation)58 int MprotectWithThreadIsolation(void* addr,
59 size_t len,
60 int prot,
61 ThreadIsolationOption thread_isolation) {
62 #if BUILDFLAG(ENABLE_PKEYS)
63 return PkeyMprotect(addr, len, prot, thread_isolation.pkey);
64 #endif
65 }
66
WriteProtectThreadIsolatedGlobals(ThreadIsolationOption thread_isolation)67 void WriteProtectThreadIsolatedGlobals(ThreadIsolationOption thread_isolation) {
68 WriteProtectThreadIsolatedVariable(thread_isolation,
69 PartitionAddressSpace::setup_, 0, true);
70
71 AddressPoolManager::Pool* pool =
72 AddressPoolManager::GetInstance().GetPool(kThreadIsolatedPoolHandle);
73 WriteProtectThreadIsolatedVariable(
74 thread_isolation, *pool,
75 offsetof(AddressPoolManager::Pool, alloc_bitset_));
76
77 uint16_t* pkey_reservation_offset_table =
78 GetReservationOffsetTable(kThreadIsolatedPoolHandle);
79 WriteProtectThreadIsolatedMemory(
80 thread_isolation, pkey_reservation_offset_table,
81 ReservationOffsetTable::kReservationOffsetTableLength);
82
83 #if BUILDFLAG(PA_DCHECK_IS_ON)
84 WriteProtectThreadIsolatedVariable(thread_isolation,
85 ThreadIsolationSettings::settings);
86 #endif
87 }
88
UnprotectThreadIsolatedGlobals()89 void UnprotectThreadIsolatedGlobals() {
90 WriteProtectThreadIsolatedGlobals(ThreadIsolationOption(false));
91 }
92
93 } // namespace partition_alloc::internal
94
95 #endif // BUILDFLAG(ENABLE_THREAD_ISOLATION)
96