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/rtl_impl.h"
21 : #include "syzygy/agent/asan/runtime.h"
22 : #include "syzygy/agent/asan/shadow.h"
23 : #include "syzygy/agent/asan/unittest_util.h"
24 : #include "syzygy/common/align.h"
25 :
26 m : namespace agent {
27 m : namespace asan {
28 :
29 m : namespace {
30 :
31 m : class NestedHeapTest : public testing::Test {
32 m : public:
33 m : void SetUp() OVERRIDE {
34 m : testing::Test::SetUp();
35 m : runtime_.SetUp(std::wstring());
36 m : agent::asan::SetUpRtl(&runtime_);
37 m : }
38 :
39 m : void TearDown() OVERRIDE {
40 m : agent::asan::TearDownRtl();
41 m : runtime_.TearDown();
42 m : testing::Test::TearDown();
43 m : }
44 :
45 m : static const size_t kMaxAlignment = 2048;
46 : // If we want to test the alignments up to 2048 we need a buffer of at least
47 : // 3 * 2048 bytes:
48 : // +--- 0 <= size < 2048 bytes---+---2048 bytes---+--2048 bytes--+
49 : // ^buffer ^aligned_buffer ^user_pointer
50 m : static const size_t kBufferSize = kMaxAlignment * 3;
51 :
52 m : bool MemoryRangeIsPoisoned(const uint8* address, size_t size) {
53 m : EXPECT_TRUE(address != NULL);
54 m : for (size_t i = 0; i < size; ++i) {
55 m : if (Shadow::IsAccessible(address + i))
56 m : return false;
57 m : }
58 m : return true;
59 m : }
60 :
61 m : bool MemoryRangeIsAccessible(const uint8* address, size_t size) {
62 m : EXPECT_TRUE(address != NULL);
63 m : for (size_t i = 0; i < size; ++i) {
64 m : if (!Shadow::IsAccessible(address + i))
65 m : return false;
66 m : }
67 m : return true;
68 m : }
69 :
70 m : AsanRuntime runtime_;
71 :
72 : // The buffers we use internally.
73 m : uint8 buffer[kBufferSize];
74 m : uint8 buffer_copy[kBufferSize];
75 m : };
76 :
77 m : } // namespace
78 :
79 m : TEST_F(NestedHeapTest, IntegrationTest) {
80 m : const size_t kAllocSize = 100;
81 m : const uint8 kMagicValue = 0x9C;
82 :
83 m : for (size_t alignment = kShadowRatio; alignment <= kMaxAlignment;
84 m : alignment *= 2) {
85 m : uint8* aligned_buffer = reinterpret_cast<uint8*>(
86 m : common::AlignUp(reinterpret_cast<size_t>(buffer), alignment));
87 m : uint8* aligned_buffer_copy = reinterpret_cast<uint8*>(
88 m : common::AlignUp(reinterpret_cast<size_t>(buffer_copy), alignment));
89 :
90 : // The simulated 'allocations' that we use must be a multiple of 8 bytes
91 : // in length.
92 m : size_t real_buffer_size = common::AlignDown(
93 m : kBufferSize - (aligned_buffer - buffer), 8);
94 m : size_t real_buffer_copy_size = common::AlignDown(
95 m : kBufferSize - (aligned_buffer_copy - buffer_copy), 8);
96 :
97 m : EXPECT_TRUE(MemoryRangeIsAccessible(aligned_buffer, real_buffer_size));
98 m : asan_PoisonMemoryRange(aligned_buffer, real_buffer_size);
99 m : EXPECT_TRUE(MemoryRangeIsPoisoned(aligned_buffer, real_buffer_size));
100 m : asan_UnpoisonMemoryRange(aligned_buffer, real_buffer_size);
101 m : EXPECT_TRUE(MemoryRangeIsAccessible(aligned_buffer, real_buffer_size));
102 :
103 m : size_t asan_size = asan_GetAsanObjectSize(kAllocSize, alignment);
104 m : ASSERT_GE(real_buffer_size, asan_size);
105 m : ASSERT_GE(real_buffer_copy_size, asan_size);
106 :
107 m : asan_InitializeObject(aligned_buffer, kAllocSize, alignment);
108 :
109 m : void* user_pointer = NULL;
110 m : size_t tmp_size = 0;
111 m : asan_GetUserExtent(aligned_buffer, &user_pointer, &tmp_size);
112 m : EXPECT_NE(reinterpret_cast<void*>(NULL), user_pointer);
113 m : EXPECT_EQ(kAllocSize, tmp_size);
114 m : ::memset(user_pointer, kMagicValue, kAllocSize);
115 :
116 m : void* asan_pointer = NULL;
117 m : asan_GetAsanExtent(user_pointer, &asan_pointer, &tmp_size);
118 m : EXPECT_EQ(asan_size, tmp_size);
119 m : EXPECT_EQ(reinterpret_cast<void*>(aligned_buffer), asan_pointer);
120 :
121 m : asan_CloneObject(aligned_buffer, aligned_buffer_copy);
122 m : void* user_pointer_copy = NULL;
123 m : asan_GetUserExtent(aligned_buffer_copy, &user_pointer_copy, &tmp_size);
124 m : EXPECT_NE(reinterpret_cast<void*>(NULL), user_pointer_copy);
125 :
126 m : for (size_t i = 0; i < kAllocSize; ++i)
127 m : EXPECT_EQ(kMagicValue, reinterpret_cast<uint8*>(user_pointer_copy)[i]);
128 :
129 m : size_t header_size = reinterpret_cast<uint8*>(user_pointer_copy)
130 m : - aligned_buffer_copy;
131 m : EXPECT_TRUE(MemoryRangeIsPoisoned(aligned_buffer_copy, header_size));
132 m : EXPECT_TRUE(MemoryRangeIsAccessible(reinterpret_cast<uint8*>(user_pointer),
133 m : kAllocSize));
134 m : EXPECT_TRUE(MemoryRangeIsPoisoned(
135 m : reinterpret_cast<uint8*>(user_pointer) + kAllocSize,
136 m : asan_size - kAllocSize - header_size));
137 :
138 m : asan_QuarantineObject(aligned_buffer);
139 m : EXPECT_TRUE(MemoryRangeIsPoisoned(aligned_buffer, asan_size));
140 :
141 m : asan_DestroyObject(aligned_buffer);
142 : // Destroying the object shouldn't affect the shadow memory.
143 m : EXPECT_TRUE(MemoryRangeIsPoisoned(aligned_buffer, asan_size));
144 :
145 m : asan_UnpoisonMemoryRange(aligned_buffer, real_buffer_size);
146 m : asan_UnpoisonMemoryRange(aligned_buffer_copy, real_buffer_copy_size);
147 m : }
148 m : }
149 :
150 m : } // namespace asan
151 m : } // namespace agent
|