15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file. 45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <stdint.h> 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <windows.h> 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <algorithm> 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <vector> 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/base_paths.h" 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/basictypes.h" 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/compiler_specific.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/files/file_path.h" 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/files/memory_mapped_file.h" 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/path_service.h" 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/string_util.h" 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/win/pe_image.h" 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class ELFImportsTest : public testing::Test { 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) protected: 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static bool ImportsCallback(const base::win::PEImage &image, 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LPCSTR module, 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PIMAGE_THUNK_DATA name_table, 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PIMAGE_THUNK_DATA iat, 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PVOID cookie) { 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<std::string>* import_list = 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) reinterpret_cast<std::vector<std::string>*>(cookie); 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) import_list->push_back(module); 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void GetImports(const base::FilePath& module_path, 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<std::string>* imports) { 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_TRUE(imports != NULL); 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::MemoryMappedFile module_mmap; 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_TRUE(module_mmap.Initialize(module_path)); 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::win::PEImageAsData pe_image_data( 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) reinterpret_cast<HMODULE>(const_cast<uint8*>(module_mmap.data()))); 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pe_image_data.EnumImportChunks(ELFImportsTest::ImportsCallback, imports); 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(ELFImportsTest, ChromeElfSanityCheck) { 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<std::string> elf_imports; 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::FilePath dll; 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_TRUE(PathService::Get(base::DIR_EXE, &dll)); 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dll = dll.Append(L"chrome_elf.dll"); 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetImports(dll, &elf_imports); 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Check that ELF has imports. 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_LT(0u, elf_imports.size()) << "Ensure the chrome_elf_unittests " 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "target was built, instead of chrome_elf_unittests.exe"; 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<std::string>::iterator it(elf_imports.begin()); 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const char* const kValidFilePatterns[] = { 64effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch "KERNEL32.dll", 65effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch "MSVC*", 66effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#if defined(SYZYASAN) 67effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch "syzyasan_rtl.dll", 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif 69effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch "ADVAPI32.dll" 70effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch }; 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Make sure all of ELF's imports are in the valid imports list. 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (; it != elf_imports.end(); it++) { 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool match = false; 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (int i = 0; i < arraysize(kValidFilePatterns); ++i) { 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (MatchPattern(*it, kValidFilePatterns[i])) 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) match = true; 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_TRUE(match) << "Illegal import in chrome_elf.dll."; 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(ELFImportsTest, ChromeExeSanityCheck) { 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<std::string> exe_imports; 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::FilePath exe; 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_TRUE(PathService::Get(base::DIR_EXE, &exe)); 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) exe = exe.Append(L"chrome.exe"); 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetImports(exe, &exe_imports); 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Check that chrome.exe has imports. 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_LT(0u, exe_imports.size()) << "Ensure the chrome_elf_unittests " 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "target was built, instead of chrome_elf_unittests.exe"; 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Chrome.exe's first import must be ELF. 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("chrome_elf.dll", exe_imports[0]) << 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Illegal import order in chrome.exe (ensure the chrome_elf_unittest " 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "target was built, instead of just chrome_elf_unittests.exe)"; 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace 102