1 : // Copyright 2015 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/registry_cache.h"
16 :
17 : #include "base/base_paths.h"
18 : #include "base/file_version_info_win.h"
19 : #include "base/path_service.h"
20 : #include "base/rand_util.h"
21 : #include "base/files/file_path.h"
22 : #include "base/test/test_reg_util_win.h"
23 : #include "base/win/registry.h"
24 : #include "gtest/gtest.h"
25 : #include "syzygy/agent/asan/block.h"
26 : #include "syzygy/agent/asan/heap_checker.h"
27 : #include "syzygy/agent/common/stack_capture.h"
28 :
29 : namespace agent {
30 : namespace asan {
31 :
32 : namespace {
33 :
34 : using registry_util::RegistryOverrideManager;
35 :
36 : // A derived class to expose protected members for unit-testing.
37 : class TestRegistryCache : public RegistryCache {
38 : public:
39 : using RegistryCache::max_days_in_registry_;
40 : using RegistryCache::max_entries_per_version_;
41 : using RegistryCache::max_modules_;
42 : using RegistryCache::max_versions_;
43 : using RegistryCache::registry_cache_key_;
44 : using RegistryCache::module_key_name_;
45 : using RegistryCache::AddOrUpdateStackId;
46 : using RegistryCache::RegValueIter;
47 : using RegistryCache::RegKeyIter;
48 : using RegistryCache::StackId;
49 : static const wchar_t kTestRegistryName[];
50 :
51 E : TestRegistryCache() : RegistryCache(kTestRegistryName) {}
52 : TestRegistryCache(const wchar_t registry_name[],
53 : size_t max_days_in_registry,
54 : size_t max_entries_per_version,
55 : size_t max_modules,
56 : size_t max_versions)
57 : : RegistryCache(registry_name,
58 : max_days_in_registry,
59 : max_entries_per_version,
60 : max_modules,
61 E : max_versions) {}
62 : };
63 :
64 : const wchar_t TestRegistryCache::kTestRegistryName[] = L"TEST";
65 :
66 : class RegistryCacheTest : public testing::Test {
67 : public:
68 E : void SetUp() override {
69 : // Setup the "global" state.
70 E : registry_key_ = TestRegistryCache::kRegistryBaseKey;
71 E : registry_key_ += TestRegistryCache::kTestRegistryName;
72 E : override_manager_.OverrideRegistry(TestRegistryCache::kRegistryRootKey);
73 E : }
74 :
75 E : base::Time RecentTime() const {
76 : return base::Time::Now() -
77 E : base::TimeDelta::FromDays(registry_cache_.max_days_in_registry_ / 2);
78 E : }
79 :
80 E : base::Time OldTime() const {
81 : return base::Time::Now() -
82 E : base::TimeDelta::FromDays(registry_cache_.max_days_in_registry_ + 9);
83 E : }
84 :
85 : // Returns the number of keys that exist in a registry location.
86 : // @param root The root key of the registry.
87 : // @param location The location in the registry.
88 : // @return Number of keys.
89 E : int GetKeyCount(const HKEY root, const std::wstring& location) const {
90 E : int count = 0;
91 E : TestRegistryCache::RegKeyIter iter(root, location.c_str());
92 E : while (iter.Valid()) {
93 E : ++count;
94 E : ++iter;
95 E : }
96 E : return count;
97 E : }
98 :
99 : protected:
100 : TestRegistryCache registry_cache_;
101 : RegistryOverrideManager override_manager_;
102 : base::win::RegKey key_;
103 : base::string16 registry_key_;
104 : };
105 :
106 : } // namespace
107 :
108 E : TEST_F(RegistryCacheTest, Constructors) {
109 : // Default constructor.
110 : EXPECT_EQ(RegistryCache::kDefaultMaxDaysInRegistry,
111 E : registry_cache_.max_days_in_registry_);
112 : EXPECT_EQ(RegistryCache::kDefaultMaxEntriesPerVersion,
113 E : registry_cache_.max_entries_per_version_);
114 : EXPECT_EQ(RegistryCache::kDefaultMaxModules,
115 E : registry_cache_.max_modules_);
116 : EXPECT_EQ(RegistryCache::kDefaultMaxVersions,
117 E : registry_cache_.max_versions_);
118 :
119 E : TestRegistryCache registry_cache2(L"TESTING", 10, 20, 30, 40);
120 E : EXPECT_EQ(10, registry_cache2.max_days_in_registry_);
121 E : EXPECT_EQ(20, registry_cache2.max_entries_per_version_);
122 E : EXPECT_EQ(30, registry_cache2.max_modules_);
123 E : EXPECT_EQ(40, registry_cache2.max_versions_);
124 : EXPECT_EQ(L"TESTING", registry_cache2.registry_cache_key_.substr(
125 E : registry_cache2.registry_cache_key_.size() - 7));
126 E : }
127 :
128 E : TEST_F(RegistryCacheTest, RemoveOldEntries) {
129 E : base::Time recent_time = RecentTime();
130 E : base::Time old_time = OldTime();
131 : key_.Create(TestRegistryCache::kRegistryRootKey,
132 E : (registry_key_ + L"\\Application 1\\v1").c_str(), KEY_ALL_ACCESS);
133 E : ASSERT_TRUE(key_.Valid());
134 :
135 E : TestRegistryCache::StackId stack_id_old = 4567890;
136 : key_.WriteValue(base::Int64ToString16(old_time.ToInternalValue()).c_str(),
137 E : &stack_id_old, sizeof(stack_id_old), REG_BINARY);
138 E : TestRegistryCache::StackId stack_id_recent = 9876543;
139 : key_.WriteValue(base::Int64ToString16(recent_time.ToInternalValue()).c_str(),
140 E : &stack_id_recent, sizeof(stack_id_recent), REG_BINARY);
141 :
142 E : registry_cache_.Init();
143 :
144 : // Only the recent entry should be left.
145 E : EXPECT_EQ(1, key_.GetValueCount());
146 : TestRegistryCache::StackId value;
147 E : DWORD dsize = sizeof(value);
148 E : DWORD dtype = 0;
149 : key_.ReadValue(base::Int64ToString16(recent_time.ToInternalValue()).c_str(),
150 E : &value, &dsize, &dtype);
151 E : EXPECT_EQ(sizeof(stack_id_recent), dsize);
152 E : EXPECT_EQ(stack_id_recent, value);
153 E : }
154 :
155 E : TEST_F(RegistryCacheTest, RemoveEmptyKeys) {
156 E : base::Time recent_time = RecentTime();
157 : key_.Create(TestRegistryCache::kRegistryRootKey,
158 E : (registry_key_ + L"\\Application 1\\v1").c_str(), KEY_ALL_ACCESS);
159 E : ASSERT_TRUE(key_.Valid());
160 : key_.Create(TestRegistryCache::kRegistryRootKey,
161 E : (registry_key_ + L"\\Application 2\\v1").c_str(), KEY_ALL_ACCESS);
162 E : ASSERT_TRUE(key_.Valid());
163 E : const TestRegistryCache::StackId stack_id = 4567890;
164 : key_.WriteValue(base::Int64ToString16(recent_time.ToInternalValue()).c_str(),
165 E : &stack_id, sizeof(stack_id), REG_BINARY);
166 E : key_.Close();
167 :
168 E : registry_cache_.Init();
169 :
170 : key_.Open(TestRegistryCache::kRegistryRootKey,
171 E : (registry_key_ + L"\\Application 1\\v1").c_str(), KEY_ALL_ACCESS);
172 E : EXPECT_FALSE(key_.Valid());
173 : key_.Open(TestRegistryCache::kRegistryRootKey,
174 E : (registry_key_ + L"\\Application 1").c_str(), KEY_ALL_ACCESS);
175 E : EXPECT_FALSE(key_.Valid());
176 : key_.Open(TestRegistryCache::kRegistryRootKey,
177 E : (registry_key_ + L"\\Application 2\\v1").c_str(), KEY_ALL_ACCESS);
178 E : EXPECT_TRUE(key_.Valid());
179 E : }
180 :
181 E : TEST_F(RegistryCacheTest, MaximumNbKeys) {
182 E : const int delta = 42;
183 : key_.Create(TestRegistryCache::kRegistryRootKey,
184 E : (registry_key_ + L"\\Application 1\\v1").c_str(), KEY_ALL_ACCESS);
185 E : ASSERT_TRUE(key_.Valid());
186 : TestRegistryCache::StackId stack_id;
187 : // Start with current time and add increment for each iteration of the loop,
188 : // instead of using Time::now() each time. Avoids having possible duplicates
189 : // if the iteration runs too fast.
190 E : base::Time start_time = base::Time::Now();
191 E : for (int i = 0; i < TestRegistryCache::kDefaultMaxEntriesPerVersion + delta;
192 E : i++) {
193 E : stack_id = base::RandUint64();
194 E : base::Time time = start_time + base::TimeDelta::FromMilliseconds(i);
195 : key_.WriteValue(base::Int64ToString16(time.ToInternalValue()).c_str(),
196 E : &stack_id, sizeof(stack_id), REG_BINARY);
197 E : }
198 : EXPECT_EQ(TestRegistryCache::kDefaultMaxEntriesPerVersion + delta,
199 E : key_.GetValueCount());
200 E : registry_cache_.Init();
201 : EXPECT_EQ(TestRegistryCache::kDefaultMaxEntriesPerVersion,
202 E : key_.GetValueCount());
203 E : }
204 :
205 E : TEST_F(RegistryCacheTest, MaximumNbVersions) {
206 E : const int delta = 42;
207 E : const std::wstring app_base_key(registry_key_ + L"\\App");
208 : TestRegistryCache::StackId stack_id;
209 : key_.Create(TestRegistryCache::kRegistryRootKey, app_base_key.c_str(),
210 E : KEY_ALL_ACCESS);
211 E : ASSERT_TRUE(key_.Valid());
212 E : key_.Close();
213 : // Create a lot of version numbers under a single module (more than
214 : // |kMaxVersions|). The number of keys should be brought down to
215 : // |kMaxVersions| after the cleaning process.
216 E : for (int i = 0; i < TestRegistryCache::kDefaultMaxVersions + delta; i++) {
217 : key_.Create(TestRegistryCache::kRegistryRootKey,
218 : (app_base_key + L"\\v" + base::IntToString16(i)).c_str(),
219 E : KEY_ALL_ACCESS);
220 E : ASSERT_TRUE(key_.Valid());
221 E : stack_id = base::RandUint64();
222 : key_.WriteValue(
223 : base::Int64ToString16(base::Time::Now().ToInternalValue()).c_str(),
224 E : &stack_id, sizeof(stack_id), REG_BINARY);
225 E : ASSERT_EQ(1, key_.GetValueCount());
226 E : key_.Close();
227 E : }
228 : EXPECT_EQ(TestRegistryCache::kDefaultMaxVersions + delta,
229 E : GetKeyCount(TestRegistryCache::kRegistryRootKey, app_base_key));
230 E : registry_cache_.Init();
231 : EXPECT_EQ(TestRegistryCache::kDefaultMaxVersions,
232 E : GetKeyCount(TestRegistryCache::kRegistryRootKey, app_base_key));
233 E : }
234 :
235 E : TEST_F(RegistryCacheTest, MaximumNbModules) {
236 E : const int delta = 42;
237 : TestRegistryCache::StackId stack_id;
238 : key_.Create(TestRegistryCache::kRegistryRootKey, (registry_key_).c_str(),
239 E : KEY_ALL_ACCESS);
240 E : ASSERT_TRUE(key_.Valid());
241 E : key_.Close();
242 : // Create a lot of modules (more than |kMaxModules|). The number of keys
243 : // should be brought down to |kMaxModules| after the cleaning process.
244 E : for (int i = 0; i < TestRegistryCache::kDefaultMaxModules + delta; i++) {
245 : key_.Create(
246 : TestRegistryCache::kRegistryRootKey,
247 : (registry_key_ + L"\\App" + base::IntToString16(i) + L"\\v1").c_str(),
248 E : KEY_ALL_ACCESS);
249 E : ASSERT_TRUE(key_.Valid());
250 E : stack_id = base::RandUint64();
251 : key_.WriteValue(
252 : base::Int64ToString16(base::Time::Now().ToInternalValue()).c_str(),
253 E : &stack_id, sizeof(stack_id), REG_BINARY);
254 E : ASSERT_EQ(1, key_.GetValueCount());
255 E : key_.Close();
256 E : }
257 : EXPECT_EQ(TestRegistryCache::kDefaultMaxModules + delta,
258 E : GetKeyCount(TestRegistryCache::kRegistryRootKey, registry_key_));
259 E : registry_cache_.Init();
260 : EXPECT_EQ(TestRegistryCache::kDefaultMaxModules,
261 E : GetKeyCount(TestRegistryCache::kRegistryRootKey, registry_key_));
262 E : }
263 :
264 E : TEST_F(RegistryCacheTest, DoesIdExist) {
265 : // Called a 1st time to initialize |module_key_name_|.
266 E : registry_cache_.Init();
267 :
268 E : base::Time recent_time = RecentTime();
269 : key_.Create(TestRegistryCache::kRegistryRootKey,
270 E : registry_cache_.module_key_name_.c_str(), KEY_ALL_ACCESS);
271 E : ASSERT_TRUE(key_.Valid());
272 :
273 E : const TestRegistryCache::StackId stack_id = 4567890;
274 : key_.WriteValue(base::Int64ToString16(recent_time.ToInternalValue()).c_str(),
275 E : &stack_id, sizeof(stack_id), REG_BINARY);
276 :
277 : // Called a 2nd time to force the loading of the new value from registry.
278 E : registry_cache_.Init();
279 :
280 E : EXPECT_TRUE(registry_cache_.DoesIdExist(stack_id));
281 E : }
282 :
283 E : TEST_F(RegistryCacheTest, AddOrUpdateStackId) {
284 E : const TestRegistryCache::StackId stack_id_1 = 123456;
285 E : const TestRegistryCache::StackId stack_id_2 = 3456236;
286 :
287 E : registry_cache_.Init();
288 : key_.Create(TestRegistryCache::kRegistryRootKey,
289 E : registry_cache_.module_key_name_.c_str(), KEY_ALL_ACCESS);
290 E : ASSERT_TRUE(key_.Valid());
291 E : ASSERT_EQ(0, key_.GetValueCount());
292 E : registry_cache_.AddOrUpdateStackId(stack_id_1);
293 : TestRegistryCache::RegValueIter iter(
294 : TestRegistryCache::kRegistryRootKey,
295 E : registry_cache_.module_key_name_.c_str());
296 E : ASSERT_TRUE(iter.Valid());
297 E : std::wstring original_name = iter.Name();
298 E : ASSERT_EQ(1, key_.GetValueCount());
299 E : registry_cache_.AddOrUpdateStackId(stack_id_2);
300 E : ASSERT_EQ(2, key_.GetValueCount());
301 E : registry_cache_.AddOrUpdateStackId(stack_id_1);
302 E : ASSERT_EQ(2, key_.GetValueCount());
303 :
304 : // Validate that the original value corresponding to |stack_id_1| doesn't
305 : // exist anymore (meaning that it was updated), while validating that the two
306 : // existing values correspond to both stack_ids.
307 : TestRegistryCache::RegValueIter iter2(
308 : TestRegistryCache::kRegistryRootKey,
309 E : registry_cache_.module_key_name_.c_str());
310 E : ASSERT_TRUE(iter2.Valid());
311 E : bool stack_id_1_exists = false;
312 E : bool stack_id_2_exists = false;
313 E : for (; iter2.Valid(); ++iter2) {
314 E : ASSERT_EQ(sizeof(TestRegistryCache::StackId), iter2.ValueSize());
315 E : ASSERT_NE(original_name, iter2.Name());
316 : const TestRegistryCache::StackId* ptr_value =
317 E : reinterpret_cast<const TestRegistryCache::StackId*>(iter2.Value());
318 E : if (*ptr_value == stack_id_1) {
319 E : EXPECT_FALSE(stack_id_1_exists);
320 E : stack_id_1_exists = true;
321 E : } else if (*ptr_value == stack_id_2) {
322 E : EXPECT_FALSE(stack_id_2_exists);
323 E : stack_id_2_exists = true;
324 : }
325 E : }
326 E : EXPECT_TRUE(stack_id_1_exists);
327 E : EXPECT_TRUE(stack_id_2_exists);
328 E : }
329 :
330 E : TEST_F(RegistryCacheTest, RemoveStackId) {
331 : // Called a 1st time to initialize |module_key_name_|.
332 E : registry_cache_.Init();
333 :
334 E : base::Time recent_time = RecentTime();
335 : key_.Create(TestRegistryCache::kRegistryRootKey,
336 E : registry_cache_.module_key_name_.c_str(), KEY_ALL_ACCESS);
337 E : ASSERT_TRUE(key_.Valid());
338 :
339 E : const TestRegistryCache::StackId stack_id = 4567890;
340 : key_.WriteValue(base::Int64ToString16(recent_time.ToInternalValue()).c_str(),
341 E : &stack_id, sizeof(stack_id), REG_BINARY);
342 :
343 : // Called a 2nd time to force the loading of the new value from registry.
344 E : registry_cache_.Init();
345 :
346 E : EXPECT_FALSE(registry_cache_.RemoveStackId(123456));
347 E : EXPECT_TRUE(registry_cache_.RemoveStackId(stack_id));
348 E : EXPECT_FALSE(registry_cache_.RemoveStackId(stack_id));
349 E : }
350 :
351 E : TEST_F(RegistryCacheTest, DeleteRegistryTree) {
352 E : RegistryCache registry_cache2(L"AnotherRegistry");
353 E : RegistryCache registry_cache3(L"YetAnotherName");
354 E : registry_cache_.Init();
355 E : registry_cache2.Init();
356 E : registry_cache3.Init();
357 :
358 : key_.Create(TestRegistryCache::kRegistryRootKey,
359 : TestRegistryCache::kRegistryBaseKey,
360 E : KEY_ALL_ACCESS);
361 :
362 E : ASSERT_TRUE(key_.Valid());
363 : ASSERT_EQ(3U, GetKeyCount(TestRegistryCache::kRegistryRootKey,
364 E : TestRegistryCache::kRegistryBaseKey));
365 E : RegistryCache::DeleteRegistryTree(L"AnotherRegistry");
366 : ASSERT_EQ(2U, GetKeyCount(TestRegistryCache::kRegistryRootKey,
367 E : TestRegistryCache::kRegistryBaseKey));
368 :
369 : TestRegistryCache::RegKeyIter iter(TestRegistryCache::kRegistryRootKey,
370 E : TestRegistryCache::kRegistryBaseKey);
371 E : ASSERT_TRUE(iter.Valid());
372 E : EXPECT_EQ(L"YetAnotherName", std::wstring(iter.Name()));
373 E : ++iter;
374 E : ASSERT_TRUE(iter.Valid());
375 E : EXPECT_EQ(L"TEST", std::wstring(iter.Name()));
376 E : }
377 :
378 : } // namespace asan
379 : } // namespace agent
|