1 // Copyright 2018 The Chromium Authors. All rights reserved.
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 "chrome/chrome_elf/third_party_dlls/main.h"
6
7 #include <windows.h>
8
9 #include <string>
10
11 #include "base/command_line.h"
12 #include "base/files/file_util.h"
13 #include "base/files/scoped_temp_dir.h"
14 #include "base/hash/sha1.h"
15 #include "base/path_service.h"
16 #include "base/process/launch.h"
17 #include "base/scoped_native_library.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/stringprintf.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "base/test/test_reg_util_win.h"
22 #include "base/test/test_timeouts.h"
23 #include "build/build_config.h"
24 #include "chrome/chrome_elf/nt_registry/nt_registry.h"
25 #include "chrome/chrome_elf/sha1/sha1.h"
26 #include "chrome/chrome_elf/third_party_dlls/hook.h"
27 #include "chrome/chrome_elf/third_party_dlls/main_unittest_exe.h"
28 #include "chrome/chrome_elf/third_party_dlls/packed_list_file.h"
29 #include "chrome/chrome_elf/third_party_dlls/packed_list_format.h"
30 #include "chrome/install_static/install_util.h"
31 #include "testing/gtest/include/gtest/gtest.h"
32
33 namespace third_party_dlls {
34 namespace {
35
36 constexpr wchar_t kTestExeFilename[] = L"third_party_dlls_test_exe.exe";
37 constexpr wchar_t kTestBlFileName[] = L"blfile";
38 constexpr wchar_t kTestDllName1[] = L"main_unittest_dll_1.dll";
39 constexpr wchar_t kTestDllName1MixedCase[] = L"MaiN_uniTtest_dLL_1.Dll";
40 constexpr wchar_t kTestDllName2[] = L"main_unittest_dll_2.dll";
41 constexpr wchar_t kChineseUnicode[] = {0x68D5, 0x8272, 0x72D0, 0x72F8, 0x002E,
42 0x0064, 0x006C, 0x006C, 0x0000};
43 constexpr wchar_t kOldBlacklistDllName[] = L"libapi2hook.dll";
44
45 struct TestModuleData {
46 std::string image_name;
47 std::string section_path;
48 std::string section_basename;
49 DWORD timedatestamp;
50 DWORD imagesize;
51 };
52
53 // NOTE: TestTimeouts::action_max_timeout() is not long enough here.
54 base::TimeDelta g_timeout = ::IsDebuggerPresent()
55 ? base::TimeDelta::FromMilliseconds(INFINITE)
56 : base::TimeDelta::FromMilliseconds(5000);
57
58 // Centralize child test process control.
LaunchChildAndWait(const base::CommandLine & command_line,int * exit_code)59 void LaunchChildAndWait(const base::CommandLine& command_line, int* exit_code) {
60 base::Process proc =
61 base::LaunchProcess(command_line, base::LaunchOptionsForTest());
62 ASSERT_TRUE(proc.IsValid());
63
64 *exit_code = 0;
65 if (!proc.WaitForExitWithTimeout(g_timeout, exit_code)) {
66 // Timeout while waiting. Try to cleanup.
67 proc.Terminate(1, false);
68 ADD_FAILURE();
69 }
70
71 return;
72 }
73
74 // Given the name and path of a test DLL, mine the data of interest out of it
75 // and return it via |test_module|.
76 // - Note: the DLL must be loaded into memory by NTLoader to mine all of the
77 // desired data (not just read from disk).
GetTestModuleData(const std::wstring & file_name,const std::wstring & file_path,TestModuleData * test_module)78 bool GetTestModuleData(const std::wstring& file_name,
79 const std::wstring& file_path,
80 TestModuleData* test_module) {
81 base::FilePath path(file_path);
82 path = path.Append(file_name);
83
84 // Map the target DLL into memory just long enough to mine data out of it.
85 base::ScopedNativeLibrary test_dll(path);
86 if (!test_dll.is_valid())
87 return false;
88
89 return GetDataFromImageForTesting(
90 test_dll.get(), &test_module->timedatestamp, &test_module->imagesize,
91 &test_module->image_name, &test_module->section_path,
92 &test_module->section_basename);
93 }
94
95 // Turn given data into a PackedListModule structure.
96 // - |image_name| should be utf-8 at this point.
GeneratePackedListModule(const std::string & image_name,DWORD timedatestamp,DWORD imagesize)97 PackedListModule GeneratePackedListModule(const std::string& image_name,
98 DWORD timedatestamp,
99 DWORD imagesize) {
100 // Internally, an empty string should not be passed in here.
101 assert(!image_name.empty());
102
103 // SHA1 hash the two strings into the new struct.
104 PackedListModule packed_module;
105 packed_module.code_id_hash =
106 elf_sha1::SHA1HashString(GetFingerprintString(timedatestamp, imagesize));
107 packed_module.basename_hash = elf_sha1::SHA1HashString(image_name);
108
109 return packed_module;
110 }
111
MakePath(const std::wstring & path,const std::wstring & name)112 inline std::wstring MakePath(const std::wstring& path,
113 const std::wstring& name) {
114 std::wstring full_path(path);
115 full_path.push_back(L'\\');
116 full_path.append(name);
117 return full_path;
118 }
119
MakeFileCopy(const std::wstring & old_path,const std::wstring & old_name,const std::wstring & new_path,const std::wstring & new_name)120 inline bool MakeFileCopy(const std::wstring& old_path,
121 const std::wstring& old_name,
122 const std::wstring& new_path,
123 const std::wstring& new_name) {
124 base::FilePath source(MakePath(old_path, old_name));
125 base::FilePath destination(MakePath(new_path, new_name));
126 return base::CopyFileW(source, destination);
127 }
128
129 // Utility function for protecting local registry.
RegRedirect(nt::ROOT_KEY key,registry_util::RegistryOverrideManager * rom)130 void RegRedirect(nt::ROOT_KEY key,
131 registry_util::RegistryOverrideManager* rom) {
132 ASSERT_NE(key, nt::AUTO);
133 HKEY root = (key == nt::HKCU ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE);
134 base::string16 temp;
135
136 ASSERT_NO_FATAL_FAILURE(rom->OverrideRegistry(root, &temp));
137 ASSERT_TRUE(nt::SetTestingOverride(key, temp));
138 }
139
140 // Utility function to disable local registry protection.
CancelRegRedirect(nt::ROOT_KEY key)141 void CancelRegRedirect(nt::ROOT_KEY key) {
142 ASSERT_NE(key, nt::AUTO);
143 ASSERT_TRUE(nt::SetTestingOverride(key, base::string16()));
144 }
145
146 // Use NtRegistry to query status codes (it's more handy than base).
147 // - Returns true if the key value exists and is type REG_BINARY.
QueryStatusCodes(std::vector<ThirdPartyStatus> * status_array)148 bool QueryStatusCodes(std::vector<ThirdPartyStatus>* status_array) {
149 HANDLE handle = nullptr;
150 if (!nt::OpenRegKey(nt::HKCU,
151 install_static::GetRegistryPath()
152 .append(kThirdPartyRegKeyName)
153 .c_str(),
154 KEY_QUERY_VALUE, &handle, nullptr)) {
155 return false;
156 }
157
158 ULONG type = REG_NONE;
159 std::vector<uint8_t> temp_buffer;
160 bool success =
161 nt::QueryRegKeyValue(handle, kStatusCodesRegValue, &type, &temp_buffer);
162 nt::CloseRegKey(handle);
163
164 if (!success || type != REG_BINARY)
165 return false;
166
167 ConvertBufferToStatusCodes(temp_buffer, status_array);
168
169 return true;
170 }
171
172 //------------------------------------------------------------------------------
173 // ThirdPartyTest class
174 //------------------------------------------------------------------------------
175
176 class ThirdPartyTest : public testing::Test {
177 protected:
178 ThirdPartyTest() = default;
179
SetUp()180 void SetUp() override {
181 // Setup temp test dir.
182 ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir());
183
184 // Store full path to test file.
185 base::FilePath path = scoped_temp_dir_.GetPath();
186 path = path.Append(kTestBlFileName);
187 bl_test_file_path_ = std::move(path.value());
188
189 // Also store a copy of current exe directory for efficiency.
190 base::FilePath exe;
191 ASSERT_TRUE(base::PathService::Get(base::DIR_EXE, &exe));
192 exe_dir_ = std::move(exe.value());
193
194 // Create the blacklist file empty.
195 base::File file(base::FilePath(bl_test_file_path_),
196 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
197 base::File::FLAG_SHARE_DELETE |
198 base::File::FLAG_DELETE_ON_CLOSE);
199 ASSERT_TRUE(file.IsValid());
200
201 // Leave file handle open for DELETE_ON_CLOSE.
202 bl_file_ = std::move(file);
203 }
204
TearDown()205 void TearDown() override {}
206
207 // Overwrite the content of the blacklist file.
WriteModulesToBlacklist(const std::vector<PackedListModule> & list)208 bool WriteModulesToBlacklist(const std::vector<PackedListModule>& list) {
209 bl_file_.SetLength(0);
210
211 // Write content {metadata}{array_of_modules}.
212 PackedListMetadata meta = {kInitialVersion,
213 static_cast<uint32_t>(list.size())};
214
215 if (bl_file_.Write(0, reinterpret_cast<const char*>(&meta), sizeof(meta)) !=
216 static_cast<int>(sizeof(meta))) {
217 return false;
218 }
219 int size = static_cast<int>(list.size() * sizeof(PackedListModule));
220 if (bl_file_.Write(sizeof(PackedListMetadata),
221 reinterpret_cast<const char*>(list.data()),
222 size) != size) {
223 return false;
224 }
225
226 return true;
227 }
228
GetBlTestFilePath()229 const base::string16& GetBlTestFilePath() { return bl_test_file_path_; }
GetExeDir()230 const base::string16& GetExeDir() { return exe_dir_; }
GetScopedTempDirValue()231 const std::wstring& GetScopedTempDirValue() {
232 return scoped_temp_dir_.GetPath().value();
233 }
234
235 private:
236 base::ScopedTempDir scoped_temp_dir_;
237 base::File bl_file_;
238 base::string16 bl_test_file_path_;
239 base::string16 exe_dir_;
240
241 DISALLOW_COPY_AND_ASSIGN(ThirdPartyTest);
242 };
243
244 //------------------------------------------------------------------------------
245 // Third-party tests
246 //
247 // These tests spawn a child test process to keep the hooking contained to a
248 // separate process. This prevents test clashes in certain testing
249 // configurations.
250 //------------------------------------------------------------------------------
251
252 #if defined(OS_WIN)
253 #define MAYBE_Base DISABLED_Base
254 #else
255 #define MAYBE_Base Base
256 #endif
257 // Note: The test module used in this unittest has no export table.
TEST_F(ThirdPartyTest,MAYBE_Base)258 TEST_F(ThirdPartyTest, MAYBE_Base) {
259 // 1. Spawn the test process with NO blacklist. Expect successful
260 // initialization.
261 base::CommandLine cmd_line1 = base::CommandLine::FromString(kTestExeFilename);
262 cmd_line1.AppendArgNative(GetBlTestFilePath());
263 cmd_line1.AppendArgNative(base::NumberToString16(kTestOnlyInitialization));
264
265 int exit_code = 0;
266 LaunchChildAndWait(cmd_line1, &exit_code);
267 ASSERT_EQ(kDllLoadSuccess, exit_code);
268
269 //----------------------------------------------------------------------------
270 // 2. Spawn the test process with NO blacklist. Expect successful DLL load.
271 base::CommandLine cmd_line2 = base::CommandLine::FromString(kTestExeFilename);
272 cmd_line2.AppendArgNative(GetBlTestFilePath());
273 cmd_line2.AppendArgNative(base::NumberToString16(kTestSingleDllLoad));
274 cmd_line2.AppendArgNative(MakePath(GetExeDir(), kTestDllName1));
275
276 LaunchChildAndWait(cmd_line2, &exit_code);
277 ASSERT_EQ(kDllLoadSuccess, exit_code);
278
279 //----------------------------------------------------------------------------
280 // 3. Spawn the test process with blacklist. Expect failed DLL load.
281 TestModuleData module_data = {};
282 ASSERT_TRUE(GetTestModuleData(kTestDllName1, GetExeDir(), &module_data));
283
284 // Note: image_name will be empty, as there is no export table in this test
285 // module.
286 EXPECT_TRUE(module_data.image_name.empty());
287
288 std::vector<PackedListModule> vector(1);
289 vector.emplace_back(GeneratePackedListModule(module_data.section_basename,
290 module_data.timedatestamp,
291 module_data.imagesize));
292 ASSERT_TRUE(WriteModulesToBlacklist(vector));
293
294 base::CommandLine cmd_line3 = base::CommandLine::FromString(kTestExeFilename);
295 cmd_line3.AppendArgNative(GetBlTestFilePath());
296 cmd_line3.AppendArgNative(base::NumberToString16(kTestSingleDllLoad));
297 cmd_line3.AppendArgNative(MakePath(GetExeDir(), kTestDllName1));
298
299 LaunchChildAndWait(cmd_line3, &exit_code);
300 ASSERT_EQ(kDllLoadFailed, exit_code);
301
302 //----------------------------------------------------------------------------
303 // 4. Spawn the test process with blacklist. Expect failed DLL load.
304 // ** Rename the module with some upper-case characters to test that
305 // the hook matching handles case properly.
306 ASSERT_TRUE(MakeFileCopy(GetExeDir(), kTestDllName1, GetScopedTempDirValue(),
307 kTestDllName1MixedCase));
308
309 // Note: the blacklist is already set from the previous test.
310 // Note: using the module with no export table for this test, to ensure that
311 // the section name (the rename) is used in the comparison.
312
313 base::CommandLine cmd_line4 = base::CommandLine::FromString(kTestExeFilename);
314 cmd_line4.AppendArgNative(GetBlTestFilePath());
315 cmd_line4.AppendArgNative(base::NumberToString16(kTestSingleDllLoad));
316 cmd_line4.AppendArgNative(
317 MakePath(GetScopedTempDirValue(), kTestDllName1MixedCase));
318
319 LaunchChildAndWait(cmd_line4, &exit_code);
320 ASSERT_EQ(kDllLoadFailed, exit_code);
321 }
322
323 // Note: The test module used in this unittest has no export table.
TEST_F(ThirdPartyTest,WideCharEncoding)324 TEST_F(ThirdPartyTest, WideCharEncoding) {
325 // Rename module to chinese unicode (kChineseUnicode). Be sure to handle
326 // any conversions to UTF8 appropriately here. No ASCII.
327 ASSERT_TRUE(MakeFileCopy(GetExeDir(), kTestDllName1, GetScopedTempDirValue(),
328 kChineseUnicode));
329
330 // 1) Test a successful DLL load with no blacklist.
331 base::CommandLine cmd_line1 = base::CommandLine::FromString(kTestExeFilename);
332 cmd_line1.AppendArgNative(GetBlTestFilePath());
333 cmd_line1.AppendArgNative(base::NumberToString16(kTestSingleDllLoad));
334 cmd_line1.AppendArgNative(MakePath(GetScopedTempDirValue(), kChineseUnicode));
335
336 int exit_code = 0;
337 LaunchChildAndWait(cmd_line1, &exit_code);
338 ASSERT_EQ(kDllLoadSuccess, exit_code);
339
340 //----------------------------------------------------------------------------
341 // 2) Test a failed DLL load with blacklist.
342 TestModuleData module_data = {};
343 ASSERT_TRUE(GetTestModuleData(kChineseUnicode, GetScopedTempDirValue(),
344 &module_data));
345
346 // Note: image_name will be empty, as there is no export table in this test
347 // module.
348 EXPECT_TRUE(module_data.image_name.empty());
349
350 std::vector<PackedListModule> vector;
351 vector.emplace_back(GeneratePackedListModule(module_data.section_basename,
352 module_data.timedatestamp,
353 module_data.imagesize));
354 ASSERT_TRUE(WriteModulesToBlacklist(vector));
355
356 base::CommandLine cmd_line2 = base::CommandLine::FromString(kTestExeFilename);
357 cmd_line2.AppendArgNative(GetBlTestFilePath());
358 cmd_line2.AppendArgNative(base::NumberToString16(kTestSingleDllLoad));
359 cmd_line2.AppendArgNative(MakePath(GetScopedTempDirValue(), kChineseUnicode));
360
361 LaunchChildAndWait(cmd_line2, &exit_code);
362 ASSERT_EQ(kDllLoadFailed, exit_code);
363 }
364
365 // Note: The test module used in this unittest has an export table.
TEST_F(ThirdPartyTest,WideCharEncodingWithExportDir)366 TEST_F(ThirdPartyTest, WideCharEncodingWithExportDir) {
367 // Rename module to chinese unicode (kChineseUnicode). Be sure to handle
368 // any conversions to UTF8 appropriately here. No ASCII.
369 ASSERT_TRUE(MakeFileCopy(GetExeDir(), kTestDllName2, GetScopedTempDirValue(),
370 kChineseUnicode));
371
372 // 1) Test a successful DLL load with no blacklist.
373 base::CommandLine cmd_line1 = base::CommandLine::FromString(kTestExeFilename);
374 cmd_line1.AppendArgNative(GetBlTestFilePath());
375 cmd_line1.AppendArgNative(base::NumberToString16(kTestSingleDllLoad));
376 cmd_line1.AppendArgNative(MakePath(GetScopedTempDirValue(), kChineseUnicode));
377
378 int exit_code = 0;
379 LaunchChildAndWait(cmd_line1, &exit_code);
380 ASSERT_EQ(kDllLoadSuccess, exit_code);
381
382 //----------------------------------------------------------------------------
383 // 2) Test a failed DLL load with blacklist.
384 TestModuleData module_data = {};
385 ASSERT_TRUE(GetTestModuleData(kChineseUnicode, GetScopedTempDirValue(),
386 &module_data));
387 // Ensure the export section was found as expected.
388 EXPECT_FALSE(module_data.image_name.empty());
389
390 // NOTE: a file rename does not affect the module name mined from the export
391 // table in the PE. So image_name and section_basename will be
392 // different. Ensure blacklisting both section name and image name
393 // works!
394
395 // 2a) Only blacklist the original DLL name, which should be mined out of the
396 // export table by the hook, and the load should be blocked.
397 std::vector<PackedListModule> vector;
398 vector.emplace_back(GeneratePackedListModule(
399 base::UTF16ToASCII(kTestDllName2), module_data.timedatestamp,
400 module_data.imagesize));
401 ASSERT_TRUE(WriteModulesToBlacklist(vector));
402
403 base::CommandLine cmd_line2 = base::CommandLine::FromString(kTestExeFilename);
404 cmd_line2.AppendArgNative(GetBlTestFilePath());
405 cmd_line2.AppendArgNative(base::NumberToString16(kTestSingleDllLoad));
406 cmd_line2.AppendArgNative(MakePath(GetScopedTempDirValue(), kChineseUnicode));
407
408 LaunchChildAndWait(cmd_line2, &exit_code);
409 ASSERT_EQ(kDllLoadFailed, exit_code);
410
411 // 2b) Only blacklist the new DLL file name, which should be mined out of the
412 // section by the hook, and the load should be blocked.
413 vector.clear();
414 vector.emplace_back(GeneratePackedListModule(
415 base::UTF16ToUTF8(kChineseUnicode), module_data.timedatestamp,
416 module_data.imagesize));
417 ASSERT_TRUE(WriteModulesToBlacklist(vector));
418
419 base::CommandLine cmd_line3 = base::CommandLine::FromString(kTestExeFilename);
420 cmd_line3.AppendArgNative(GetBlTestFilePath());
421 cmd_line3.AppendArgNative(base::NumberToString16(kTestSingleDllLoad));
422 cmd_line3.AppendArgNative(MakePath(GetScopedTempDirValue(), kChineseUnicode));
423
424 LaunchChildAndWait(cmd_line3, &exit_code);
425 ASSERT_EQ(kDllLoadFailed, exit_code);
426 }
427
428 // Note: The test module used in this unittest has no export table.
TEST_F(ThirdPartyTest,DeprecatedBlacklistSanityCheck)429 TEST_F(ThirdPartyTest, DeprecatedBlacklistSanityCheck) {
430 // Rename module to something on the old, deprecated, hard-coded blacklist.
431 ASSERT_TRUE(MakeFileCopy(GetExeDir(), kTestDllName1, GetScopedTempDirValue(),
432 kOldBlacklistDllName));
433
434 // 1) Test a failed DLL load with no blacklist (the old, hard-coded blacklist
435 // should trigger a block).
436 base::CommandLine cmd_line1 = base::CommandLine::FromString(kTestExeFilename);
437 cmd_line1.AppendArgNative(GetBlTestFilePath());
438 cmd_line1.AppendArgNative(base::NumberToString16(kTestSingleDllLoad));
439 cmd_line1.AppendArgNative(
440 MakePath(GetScopedTempDirValue(), kOldBlacklistDllName));
441
442 int exit_code = 0;
443 LaunchChildAndWait(cmd_line1, &exit_code);
444 ASSERT_EQ(kDllLoadFailed, exit_code);
445 }
446
447 // Note: This test only sanity checks the two SHA1 libraries used on either side
448 // of the Third-Party block.
449 // This Side: chrome/chrome_elf\third_party_dlls\*,
450 // elf_sha1::SHA1HashString().
451 // The Other Side: chrome\browser\conflicts\module_list_filter_win.cc,
452 // base::SHA1HashString().
TEST_F(ThirdPartyTest,SHA1SanityCheck)453 TEST_F(ThirdPartyTest, SHA1SanityCheck) {
454 // Rename module to chinese unicode (kChineseUnicode). Be sure to handle
455 // any conversions to UTF8 appropriately here. No ASCII.
456 ASSERT_TRUE(MakeFileCopy(GetExeDir(), kTestDllName1, GetScopedTempDirValue(),
457 kChineseUnicode));
458
459 TestModuleData module_data = {};
460 ASSERT_TRUE(GetTestModuleData(kChineseUnicode, GetScopedTempDirValue(),
461 &module_data));
462
463 // Get hashes from elf_sha1.
464 PackedListModule elf_sha1_generated = GeneratePackedListModule(
465 base::UTF16ToUTF8(kChineseUnicode), module_data.timedatestamp,
466 module_data.imagesize);
467
468 // Get hashes from base_sha1.
469 const std::string module_basename_hash =
470 base::SHA1HashString(base::UTF16ToUTF8(kChineseUnicode));
471 const std::string module_code_id_hash = base::SHA1HashString(
472 GetFingerprintString(module_data.timedatestamp, module_data.imagesize));
473
474 // Compare the hashes.
475 EXPECT_EQ(::memcmp(&elf_sha1_generated.basename_hash[0],
476 module_basename_hash.data(), elf_sha1::kSHA1Length),
477 0);
478 EXPECT_EQ(::memcmp(&elf_sha1_generated.code_id_hash[0],
479 module_code_id_hash.data(), elf_sha1::kSHA1Length),
480 0);
481 }
482
483 // Flaky: crbug.com/868233
484 #if defined(OS_WIN)
485 #define MAYBE_PathCaseSensitive DISABLED_PathCaseSensitive
486 #else
487 #define MAYBE_PathCaseSensitive PathCaseSensitive
488 #endif
489
490 // Test that full section path is left alone, in terms of case.
TEST_F(ThirdPartyTest,MAYBE_PathCaseSensitive)491 TEST_F(ThirdPartyTest, MAYBE_PathCaseSensitive) {
492 // Rename module to have mixed case.
493 ASSERT_TRUE(MakeFileCopy(GetExeDir(), kTestDllName2, GetScopedTempDirValue(),
494 kTestDllName1MixedCase));
495
496 // 1) Sanity check that the hook GetDataFromImage() mining leaves the
497 // section path alone.
498 TestModuleData module_data = {};
499 ASSERT_TRUE(GetTestModuleData(kTestDllName1MixedCase, GetScopedTempDirValue(),
500 &module_data));
501 // Reminder: this string is actually UTF-8, but this test ensures it is ascii.
502 // Also, |section_path| will be a device path, so convert to drive letter
503 // before comparing.
504 base::FilePath drive;
505 ASSERT_TRUE(base::DevicePathToDriveLetterPath(
506 base::FilePath(base::ASCIIToUTF16(module_data.section_path)), &drive));
507
508 EXPECT_EQ(drive.value().compare(
509 MakePath(GetScopedTempDirValue(), kTestDllName1MixedCase)),
510 0);
511
512 // 2) Now check an actual log. Successful DLL load with no blacklist is fine
513 // for this test.
514 base::CommandLine cmd_line1 = base::CommandLine::FromString(kTestExeFilename);
515 cmd_line1.AppendArgNative(GetBlTestFilePath());
516 cmd_line1.AppendArgNative(base::NumberToString16(kTestSingleDllLoad));
517 cmd_line1.AppendArgNative(
518 MakePath(GetScopedTempDirValue(), kTestDllName1MixedCase));
519
520 int exit_code = 0;
521 LaunchChildAndWait(cmd_line1, &exit_code);
522 ASSERT_EQ(kDllLoadSuccess, exit_code);
523 }
524
525 // Test the status-code passing in registry.
TEST_F(ThirdPartyTest,StatusCodes)526 TEST_F(ThirdPartyTest, StatusCodes) {
527 // 1. Enable reg override for test net.
528 registry_util::RegistryOverrideManager override_manager;
529 ASSERT_NO_FATAL_FAILURE(RegRedirect(nt::HKCU, &override_manager));
530
531 // 2. Reset the registry key and value to empty.
532 ASSERT_TRUE(ResetStatusCodesForTesting());
533
534 // 3. Confirm key and empty value.
535 std::vector<ThirdPartyStatus> code_array;
536 EXPECT_TRUE(QueryStatusCodes(&code_array));
537 EXPECT_EQ(0u, code_array.size());
538
539 // 4. Add status codes, then verify.
540 ASSERT_NO_FATAL_FAILURE(
541 AddStatusCodeForTesting(ThirdPartyStatus::kFileEmpty));
542 ASSERT_NO_FATAL_FAILURE(
543 AddStatusCodeForTesting(ThirdPartyStatus::kLogsCreateMutexFailure));
544 ASSERT_NO_FATAL_FAILURE(
545 AddStatusCodeForTesting(ThirdPartyStatus::kHookVirtualProtectFailure));
546 EXPECT_TRUE(QueryStatusCodes(&code_array));
547 ASSERT_EQ(3u, code_array.size());
548 EXPECT_EQ(ThirdPartyStatus::kFileEmpty, code_array[0]);
549 EXPECT_EQ(ThirdPartyStatus::kLogsCreateMutexFailure, code_array[1]);
550 EXPECT_EQ(ThirdPartyStatus::kHookVirtualProtectFailure, code_array[2]);
551
552 // 5. Reset the registry value to empty.
553 EXPECT_TRUE(ResetStatusCodesForTesting());
554 EXPECT_TRUE(QueryStatusCodes(&code_array));
555 EXPECT_EQ(0u, code_array.size());
556
557 // 6. Disable reg override.
558 ASSERT_NO_FATAL_FAILURE(CancelRegRedirect(nt::HKCU));
559 }
560
561 } // namespace
562 } // namespace third_party_dlls
563