blob: 555ddf909a4c89d9ac2108b1be7d93727c7aee1a [file] [log] [blame]
Jeff Goura3e4ebd2024-01-23 21:04:491// Copyright 2024 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 "base/memory/protected_memory.h"
André Kempe5adc4d5a2024-03-15 12:23:336
7#include <stddef.h>
8#include <stdint.h>
9
10#include <climits>
André Kempe0f7da88a2024-03-22 19:12:4711#include <type_traits>
André Kempe5adc4d5a2024-03-15 12:23:3312
13#include "base/memory/protected_memory_buildflags.h"
Jeff Goura3e4ebd2024-01-23 21:04:4914#include "base/synchronization/lock.h"
15#include "base/test/gtest_util.h"
Jeff Goura3e4ebd2024-01-23 21:04:4916#include "build/build_config.h"
17#include "testing/gtest/include/gtest/gtest.h"
18
19namespace base {
Jeff Goura3e4ebd2024-01-23 21:04:4920namespace {
21
22struct Data {
23 Data() = default;
André Kempe0f7da88a2024-03-22 19:12:4724 constexpr Data(int16_t f, int32_t b) : foo(f), bar(b) {}
25 int16_t foo = 0;
26 int32_t bar = -1;
Jeff Goura3e4ebd2024-01-23 21:04:4927};
28
André Kempe0f7da88a2024-03-22 19:12:4729struct DataWithNonTrivialConstructor {
30 explicit DataWithNonTrivialConstructor(int f) : foo(f) {}
31 int foo;
32};
33
34static_assert(
35 !std::is_trivially_constructible_v<DataWithNonTrivialConstructor>);
36
André Kempe5adc4d5a2024-03-15 12:23:3337#if BUILDFLAG(PROTECTED_MEMORY_ENABLED)
38void VerifyByteSequenceIsNotWriteable(unsigned char* const byte_pattern,
39 const size_t number_of_bits,
40 const size_t bit_increment) {
41 const auto check_bit_not_writeable = [=](const size_t bit_index) {
42 const size_t byte_index = bit_index / CHAR_BIT;
43 const size_t local_bit_index = bit_index % CHAR_BIT;
44
45 EXPECT_CHECK_DEATH_WITH(
46 byte_pattern[byte_index] ^= (0x1 << local_bit_index), "")
47 << " at bit " << bit_index << " of " << number_of_bits;
48 };
49
50 // Check the boundary bits explicitly to ensure we cover these.
51 if (number_of_bits >= 1) {
52 check_bit_not_writeable(0);
53 }
54
55 if (number_of_bits >= 2) {
56 check_bit_not_writeable(number_of_bits - 1);
57 }
58
59 // Now check the bits in between at the requested increment.
60 for (size_t bit_index = bit_increment; bit_index < (number_of_bits - 1);
61 bit_index += bit_increment) {
62 check_bit_not_writeable(bit_index);
63 }
64}
65
66template <typename T>
67void VerifyInstanceIsNotWriteable(T& instance, const size_t bit_increment = 3) {
68 VerifyByteSequenceIsNotWriteable(
69 reinterpret_cast<unsigned char*>(std::addressof(instance)),
70 sizeof(T) * CHAR_BIT, bit_increment);
71}
72#endif // BUILDFLAG(PROTECTED_MEMORY_ENABLED)
73
André Kempe0f7da88a2024-03-22 19:12:4774DEFINE_PROTECTED_DATA ProtectedMemory<int, false /*ConstructLazily*/>
75 g_default_initialization;
André Kempe5adc4d5a2024-03-15 12:23:3376
André Kempe0f7da88a2024-03-22 19:12:4777TEST(ProtectedMemoryTest, DefaultInitialization) {
78 EXPECT_EQ(*g_default_initialization, int());
Jeff Goura3e4ebd2024-01-23 21:04:4979}
80
André Kempe0f7da88a2024-03-22 19:12:4781DEFINE_PROTECTED_DATA ProtectedMemory<Data, false /*ConstructLazily*/>
82 g_with_initialization_declaration(4, 3);
83
84TEST(ProtectedMemoryTest, InitializationDeclaration) {
85 EXPECT_EQ(g_with_initialization_declaration->foo, 4);
86 EXPECT_EQ(g_with_initialization_declaration->bar, 3);
André Kempe5adc4d5a2024-03-15 12:23:3387}
88
André Kempe0f7da88a2024-03-22 19:12:4789DEFINE_PROTECTED_DATA ProtectedMemory<int, false /*ConstructLazily*/>
90 g_explicit_initialization;
André Kempe5adc4d5a2024-03-15 12:23:3391
André Kempe0f7da88a2024-03-22 19:12:4792TEST(ProtectedMemoryTest, ExplicitInitializationWithExplicitValue) {
93 static ProtectedMemoryInitializer initializer_explicit_value(
94 g_explicit_initialization, 4);
André Kempe5adc4d5a2024-03-15 12:23:3395
André Kempe0f7da88a2024-03-22 19:12:4796 EXPECT_EQ(*g_explicit_initialization, 4);
97}
98
99DEFINE_PROTECTED_DATA ProtectedMemory<int, false /*ConstructLazily*/>
100 g_explicit_initialization_with_default_value;
101
102TEST(ProtectedMemoryTest, VerifyExplicitInitializationWithDefaultValue) {
103 static ProtectedMemoryInitializer initializer_explicit_value(
104 g_explicit_initialization_with_default_value);
105
106 EXPECT_EQ(*g_explicit_initialization_with_default_value, int());
107}
108
109DEFINE_PROTECTED_DATA
110ProtectedMemory<DataWithNonTrivialConstructor, true /*ConstructLazily*/>
111 g_lazily_initialized_with_explicit_initialization;
112
113TEST(ProtectedMemoryTest, ExplicitLazyInitializationWithExplicitValue) {
114 static ProtectedMemoryInitializer initializer_explicit_value(
115 g_lazily_initialized_with_explicit_initialization, 4);
116
117 EXPECT_EQ(g_lazily_initialized_with_explicit_initialization->foo, 4);
118}
119
120DEFINE_PROTECTED_DATA
121ProtectedMemory<DataWithNonTrivialConstructor, true /*ConstructLazily*/>
122 g_uninitialized;
123
124TEST(ProtectedMemoryDeathTest, AccessWithoutInitialization) {
125 EXPECT_CHECK_DEATH_WITH(g_uninitialized.operator*(), "");
126 EXPECT_CHECK_DEATH_WITH(g_uninitialized.operator->(), "");
Jeff Goura3e4ebd2024-01-23 21:04:49127}
128
129#if BUILDFLAG(PROTECTED_MEMORY_ENABLED)
André Kempe0f7da88a2024-03-22 19:12:47130DEFINE_PROTECTED_DATA ProtectedMemory<Data, false /*ConstructLazily*/>
131 g_eagerly_initialized;
132
133TEST(ProtectedMemoryTest, VerifySetValue) {
134 ASSERT_NE(g_eagerly_initialized->foo, 5);
135 EXPECT_EQ(g_eagerly_initialized->bar, -1);
136 {
137 base::AutoWritableMemory writer(g_eagerly_initialized);
138 writer.GetProtectedDataPtr()->foo = 5;
139 }
140 EXPECT_EQ(g_eagerly_initialized->foo, 5);
141 EXPECT_EQ(g_eagerly_initialized->bar, -1);
André Kempe5adc4d5a2024-03-15 12:23:33142}
Jeff Goura3e4ebd2024-01-23 21:04:49143
André Kempe0f7da88a2024-03-22 19:12:47144TEST(ProtectedMemoryDeathTest, AccessWithoutWriteAccessCrashes) {
145 VerifyInstanceIsNotWriteable(g_with_initialization_declaration);
Jeff Goura3e4ebd2024-01-23 21:04:49146}
147
André Kempe0f7da88a2024-03-22 19:12:47148TEST(ProtectedMemoryDeathTest, FailsIfDefinedOutsideOfProtectMemoryRegion) {
Jeff Goura3e4ebd2024-01-23 21:04:49149 ProtectedMemory<Data> data;
150 EXPECT_CHECK_DEATH({ AutoWritableMemory writer(data); });
151}
André Kempe0f7da88a2024-03-22 19:12:47152
Jeff Goura3e4ebd2024-01-23 21:04:49153#endif // BUILDFLAG(PROTECTED_MEMORY_ENABLED)
154
André Kempe0f7da88a2024-03-22 19:12:47155} // namespace
Jeff Goura3e4ebd2024-01-23 21:04:49156} // namespace base