blob: 93955e5607b1dd306d0f832fa5cfa00feb286aeb [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
danakj51d26a42024-04-25 14:23:565#ifdef UNSAFE_BUFFERS_BUILD
6// TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7#pragma allow_unsafe_buffers
8#endif
9
Jeff Goura3e4ebd2024-01-23 21:04:4910#include "base/memory/protected_memory.h"
André Kempe5adc4d5a2024-03-15 12:23:3311
12#include <stddef.h>
13#include <stdint.h>
14
15#include <climits>
André Kempe0f7da88a2024-03-22 19:12:4716#include <type_traits>
André Kempe5adc4d5a2024-03-15 12:23:3317
18#include "base/memory/protected_memory_buildflags.h"
Jeff Goura3e4ebd2024-01-23 21:04:4919#include "base/synchronization/lock.h"
20#include "base/test/gtest_util.h"
Jeff Goura3e4ebd2024-01-23 21:04:4921#include "build/build_config.h"
22#include "testing/gtest/include/gtest/gtest.h"
23
24namespace base {
Jeff Goura3e4ebd2024-01-23 21:04:4925namespace {
26
27struct Data {
28 Data() = default;
André Kempe0f7da88a2024-03-22 19:12:4729 constexpr Data(int16_t f, int32_t b) : foo(f), bar(b) {}
30 int16_t foo = 0;
31 int32_t bar = -1;
Jeff Goura3e4ebd2024-01-23 21:04:4932};
33
André Kempe0f7da88a2024-03-22 19:12:4734struct DataWithNonTrivialConstructor {
35 explicit DataWithNonTrivialConstructor(int f) : foo(f) {}
36 int foo;
37};
38
39static_assert(
40 !std::is_trivially_constructible_v<DataWithNonTrivialConstructor>);
41
André Kempe5adc4d5a2024-03-15 12:23:3342#if BUILDFLAG(PROTECTED_MEMORY_ENABLED)
43void VerifyByteSequenceIsNotWriteable(unsigned char* const byte_pattern,
44 const size_t number_of_bits,
45 const size_t bit_increment) {
46 const auto check_bit_not_writeable = [=](const size_t bit_index) {
47 const size_t byte_index = bit_index / CHAR_BIT;
48 const size_t local_bit_index = bit_index % CHAR_BIT;
49
50 EXPECT_CHECK_DEATH_WITH(
51 byte_pattern[byte_index] ^= (0x1 << local_bit_index), "")
52 << " at bit " << bit_index << " of " << number_of_bits;
53 };
54
55 // Check the boundary bits explicitly to ensure we cover these.
56 if (number_of_bits >= 1) {
57 check_bit_not_writeable(0);
58 }
59
60 if (number_of_bits >= 2) {
61 check_bit_not_writeable(number_of_bits - 1);
62 }
63
64 // Now check the bits in between at the requested increment.
65 for (size_t bit_index = bit_increment; bit_index < (number_of_bits - 1);
66 bit_index += bit_increment) {
67 check_bit_not_writeable(bit_index);
68 }
69}
70
71template <typename T>
72void VerifyInstanceIsNotWriteable(T& instance, const size_t bit_increment = 3) {
73 VerifyByteSequenceIsNotWriteable(
74 reinterpret_cast<unsigned char*>(std::addressof(instance)),
75 sizeof(T) * CHAR_BIT, bit_increment);
76}
77#endif // BUILDFLAG(PROTECTED_MEMORY_ENABLED)
78
Jeffrey Gour6f946aad2024-07-11 16:07:5479DEFINE_PROTECTED_DATA ProtectedMemory<int> g_explicit_initialization;
André Kempe5adc4d5a2024-03-15 12:23:3380
André Kempe0f7da88a2024-03-22 19:12:4781TEST(ProtectedMemoryTest, ExplicitInitializationWithExplicitValue) {
82 static ProtectedMemoryInitializer initializer_explicit_value(
83 g_explicit_initialization, 4);
André Kempe5adc4d5a2024-03-15 12:23:3384
André Kempe0f7da88a2024-03-22 19:12:4785 EXPECT_EQ(*g_explicit_initialization, 4);
86}
87
Jeffrey Gour6f946aad2024-07-11 16:07:5488DEFINE_PROTECTED_DATA ProtectedMemory<int>
André Kempe0f7da88a2024-03-22 19:12:4789 g_explicit_initialization_with_default_value;
90
91TEST(ProtectedMemoryTest, VerifyExplicitInitializationWithDefaultValue) {
92 static ProtectedMemoryInitializer initializer_explicit_value(
93 g_explicit_initialization_with_default_value);
94
95 EXPECT_EQ(*g_explicit_initialization_with_default_value, int());
96}
97
98DEFINE_PROTECTED_DATA
Jeffrey Gour6f946aad2024-07-11 16:07:5499ProtectedMemory<DataWithNonTrivialConstructor>
André Kempe0f7da88a2024-03-22 19:12:47100 g_lazily_initialized_with_explicit_initialization;
101
102TEST(ProtectedMemoryTest, ExplicitLazyInitializationWithExplicitValue) {
103 static ProtectedMemoryInitializer initializer_explicit_value(
104 g_lazily_initialized_with_explicit_initialization, 4);
105
106 EXPECT_EQ(g_lazily_initialized_with_explicit_initialization->foo, 4);
107}
108
109DEFINE_PROTECTED_DATA
Jeffrey Gour6f946aad2024-07-11 16:07:54110ProtectedMemory<DataWithNonTrivialConstructor> g_uninitialized;
André Kempe0f7da88a2024-03-22 19:12:47111
112TEST(ProtectedMemoryDeathTest, AccessWithoutInitialization) {
113 EXPECT_CHECK_DEATH_WITH(g_uninitialized.operator*(), "");
114 EXPECT_CHECK_DEATH_WITH(g_uninitialized.operator->(), "");
Jeff Goura3e4ebd2024-01-23 21:04:49115}
116
117#if BUILDFLAG(PROTECTED_MEMORY_ENABLED)
Jeffrey Gour6f946aad2024-07-11 16:07:54118DEFINE_PROTECTED_DATA ProtectedMemory<Data> g_initialized;
André Kempe0f7da88a2024-03-22 19:12:47119
120TEST(ProtectedMemoryTest, VerifySetValue) {
Jeffrey Gour6f946aad2024-07-11 16:07:54121 static ProtectedMemoryInitializer initializer_explicit_value(g_initialized);
122 ASSERT_NE(g_initialized->foo, 5);
123 EXPECT_EQ(g_initialized->bar, -1);
André Kempe0f7da88a2024-03-22 19:12:47124 {
Jeffrey Gour6f946aad2024-07-11 16:07:54125 base::AutoWritableMemory writer(g_initialized);
André Kempe0f7da88a2024-03-22 19:12:47126 writer.GetProtectedDataPtr()->foo = 5;
127 }
Jeffrey Gour6f946aad2024-07-11 16:07:54128 EXPECT_EQ(g_initialized->foo, 5);
129 EXPECT_EQ(g_initialized->bar, -1);
André Kempe5adc4d5a2024-03-15 12:23:33130}
Jeff Goura3e4ebd2024-01-23 21:04:49131
Jeffrey Gour6f946aad2024-07-11 16:07:54132DEFINE_PROTECTED_DATA ProtectedMemory<Data> g_not_writable;
133
André Kempe0f7da88a2024-03-22 19:12:47134TEST(ProtectedMemoryDeathTest, AccessWithoutWriteAccessCrashes) {
Jeffrey Gour6f946aad2024-07-11 16:07:54135 static ProtectedMemoryInitializer initializer_explicit_value(g_not_writable);
136 VerifyInstanceIsNotWriteable(g_not_writable);
Jeff Goura3e4ebd2024-01-23 21:04:49137}
138
André Kempe0f7da88a2024-03-22 19:12:47139TEST(ProtectedMemoryDeathTest, FailsIfDefinedOutsideOfProtectMemoryRegion) {
Jeff Goura3e4ebd2024-01-23 21:04:49140 ProtectedMemory<Data> data;
141 EXPECT_CHECK_DEATH({ AutoWritableMemory writer(data); });
142}
André Kempe0f7da88a2024-03-22 19:12:47143
Jeff Goura3e4ebd2024-01-23 21:04:49144#endif // BUILDFLAG(PROTECTED_MEMORY_ENABLED)
145
André Kempe0f7da88a2024-03-22 19:12:47146} // namespace
Jeff Goura3e4ebd2024-01-23 21:04:49147} // namespace base