1 : // Copyright 2013 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include "syzygy/agent/asan/nested_heap.h"
16 :
17 : #include <algorithm>
18 :
19 : #include "gtest/gtest.h"
20 : #include "syzygy/agent/asan/asan_heap.h"
21 : #include "syzygy/agent/asan/asan_rtl_impl.h"
22 : #include "syzygy/agent/asan/asan_runtime.h"
23 : #include "syzygy/agent/asan/asan_shadow.h"
24 : #include "syzygy/agent/asan/unittest_util.h"
25 : #include "syzygy/common/align.h"
26 :
27 : namespace agent {
28 : namespace asan {
29 :
30 : namespace {
31 :
32 : class NestedHeapTest : public testing::Test {
33 : public:
34 E : void SetUp() OVERRIDE {
35 E : testing::Test::SetUp();
36 E : runtime_.SetUp(std::wstring());
37 E : agent::asan::SetUpRtl(&runtime_);
38 E : }
39 :
40 E : void TearDown() OVERRIDE {
41 E : agent::asan::TearDownRtl();
42 E : runtime_.TearDown();
43 E : testing::Test::TearDown();
44 E : }
45 :
46 : static const size_t kMaxAlignment = 2048;
47 : // If we want to test the alignments up to 2048 we need a buffer of at least
48 : // 3 * 2048 bytes:
49 : // +--- 0 <= size < 2048 bytes---+---2048 bytes---+--2048 bytes--+
50 : // ^buffer ^aligned_buffer ^user_pointer
51 : static const size_t kBufferSize = kMaxAlignment * 3;
52 :
53 E : bool MemoryRangeIsPoisoned(const uint8* address, size_t size) {
54 E : EXPECT_TRUE(address != NULL);
55 E : for (size_t i = 0; i < size; ++i) {
56 E : if (Shadow::IsAccessible(address + i))
57 i : return false;
58 E : }
59 E : return true;
60 E : }
61 :
62 E : bool MemoryRangeIsAccessible(const uint8* address, size_t size) {
63 E : EXPECT_TRUE(address != NULL);
64 E : for (size_t i = 0; i < size; ++i) {
65 E : if (!Shadow::IsAccessible(address + i))
66 i : return false;
67 E : }
68 E : return true;
69 E : }
70 :
71 : AsanRuntime runtime_;
72 :
73 : // The buffers we use internally.
74 : uint8 buffer[kBufferSize];
75 : uint8 buffer_copy[kBufferSize];
76 : };
77 :
78 : } // namespace
79 :
80 E : TEST_F(NestedHeapTest, IntegrationTest) {
81 E : const size_t kAllocSize = 100;
82 E : const uint8 kMagicValue = 0x9C;
83 :
84 E : for (size_t alignment = Shadow::kShadowGranularity;
85 E : alignment <= kMaxAlignment;
86 E : alignment *= 2) {
87 : uint8* aligned_buffer = reinterpret_cast<uint8*>(
88 E : common::AlignUp(reinterpret_cast<size_t>(buffer), alignment));
89 : uint8* aligned_buffer_copy = reinterpret_cast<uint8*>(
90 E : common::AlignUp(reinterpret_cast<size_t>(buffer_copy), alignment));
91 E : size_t real_buffer_size = kBufferSize - (aligned_buffer - buffer);
92 : size_t real_buffer_copy_size = kBufferSize - (aligned_buffer_copy -
93 E : buffer_copy);
94 :
95 E : EXPECT_TRUE(MemoryRangeIsAccessible(aligned_buffer, real_buffer_size));
96 E : asan_PoisonMemoryRange(aligned_buffer, real_buffer_size);
97 E : EXPECT_TRUE(MemoryRangeIsPoisoned(aligned_buffer, real_buffer_size));
98 E : asan_UnpoisonMemoryRange(aligned_buffer, real_buffer_size);
99 E : EXPECT_TRUE(MemoryRangeIsAccessible(aligned_buffer, real_buffer_size));
100 :
101 E : size_t asan_size = asan_GetAsanObjectSize(kAllocSize, alignment);
102 E : ASSERT_GT(real_buffer_size, asan_size);
103 E : ASSERT_GT(real_buffer_copy_size, asan_size);
104 :
105 E : asan_InitializeObject(aligned_buffer, kAllocSize, alignment);
106 :
107 E : void* user_pointer = NULL;
108 E : size_t tmp_size = 0;
109 E : asan_GetUserExtent(aligned_buffer, &user_pointer, &tmp_size);
110 E : EXPECT_NE(reinterpret_cast<void*>(NULL), user_pointer);
111 E : EXPECT_EQ(kAllocSize, tmp_size);
112 E : memset(user_pointer, kMagicValue, kAllocSize);
113 :
114 E : void* asan_pointer = NULL;
115 E : asan_GetAsanExtent(user_pointer, &asan_pointer, &tmp_size);
116 E : EXPECT_EQ(asan_size, tmp_size);
117 E : EXPECT_EQ(reinterpret_cast<void*>(aligned_buffer), asan_pointer);
118 :
119 E : asan_CloneObject(aligned_buffer, aligned_buffer_copy);
120 E : void* user_pointer_copy = NULL;
121 E : asan_GetUserExtent(aligned_buffer_copy, &user_pointer_copy, &tmp_size);
122 E : EXPECT_NE(reinterpret_cast<void*>(NULL), user_pointer_copy);
123 :
124 E : for (size_t i = 0; i < kAllocSize; ++i) {
125 E : EXPECT_EQ(kMagicValue, reinterpret_cast<uint8*>(user_pointer_copy)[i]);
126 E : }
127 : size_t header_size = reinterpret_cast<uint8*>(user_pointer_copy)
128 E : - aligned_buffer_copy;
129 E : EXPECT_TRUE(MemoryRangeIsPoisoned(aligned_buffer_copy, header_size));
130 : EXPECT_TRUE(MemoryRangeIsAccessible(reinterpret_cast<uint8*>(user_pointer),
131 E : kAllocSize));
132 : EXPECT_TRUE(MemoryRangeIsPoisoned(
133 : reinterpret_cast<uint8*>(user_pointer) + kAllocSize,
134 E : asan_size - kAllocSize - header_size));
135 :
136 E : asan_QuarantineObject(aligned_buffer);
137 E : EXPECT_TRUE(MemoryRangeIsPoisoned(aligned_buffer, asan_size));
138 :
139 E : asan_DestroyObject(aligned_buffer);
140 : // Destroying the object shouldn't affect the shadow memory.
141 E : EXPECT_TRUE(MemoryRangeIsPoisoned(aligned_buffer, asan_size));
142 :
143 E : asan_UnpoisonMemoryRange(aligned_buffer, real_buffer_size);
144 E : asan_UnpoisonMemoryRange(aligned_buffer_copy, real_buffer_copy_size);
145 E : }
146 E : }
147 :
148 : } // namespace asan
149 : } // namespace agent
|