Commit 18126c18 authored by Penny MacNeil's avatar Penny MacNeil Committed by Commit Bot

[chrome_elf whitelist] Adjust whitelist file support.

- kFileNotFound and kArraySizeZero now treated as kSuccess.
- Updated shared definitions in whitelist_packed_format source set.  New timestamp
to track last load attempt in local cache.  Added relative path and file name too.
- Decision made to check is_sorted on array during init.
The array will be smaller than in original design, so speed hit will be minimal.
- New tests.

BUG=769590
TEST=chrome_elf_unittests.exe, WhitelistFileTest.*

Change-Id: I45c4321ccdf89d8768509c0dad21c9c15f73c4e3
Reviewed-on: https://chromium-review.googlesource.com/794551
Commit-Queue: Penny MacNeil <pennymac@chromium.org>
Reviewed-by: default avatarGreg Thompson <grt@chromium.org>
Cr-Commit-Position: refs/heads/master@{#523544}
parent 792de922
...@@ -137,6 +137,13 @@ source_set("sha1") { ...@@ -137,6 +137,13 @@ source_set("sha1") {
] ]
} }
source_set("whitelist_packed_format") {
sources = [
"whitelist/whitelist_packed_format.cc",
"whitelist/whitelist_packed_format.h",
]
}
##------------------------------------------------------------------------------ ##------------------------------------------------------------------------------
## chrome_elf sub targets ## chrome_elf sub targets
##------------------------------------------------------------------------------ ##------------------------------------------------------------------------------
...@@ -231,13 +238,13 @@ static_library("whitelist") { ...@@ -231,13 +238,13 @@ static_library("whitelist") {
"whitelist/whitelist.h", "whitelist/whitelist.h",
"whitelist/whitelist_file.cc", "whitelist/whitelist_file.cc",
"whitelist/whitelist_file.h", "whitelist/whitelist_file.h",
"whitelist/whitelist_file_format.h",
"whitelist/whitelist_ime.cc", "whitelist/whitelist_ime.cc",
"whitelist/whitelist_ime.h", "whitelist/whitelist_ime.h",
] ]
deps = [ deps = [
":nt_registry", ":nt_registry",
":sha1", ":sha1",
":whitelist_packed_format",
"//chrome/install_static:install_static_util", "//chrome/install_static:install_static_util",
] ]
} }
...@@ -270,6 +277,7 @@ test("chrome_elf_unittests") { ...@@ -270,6 +277,7 @@ test("chrome_elf_unittests") {
":security", ":security",
":sha1", ":sha1",
":whitelist", ":whitelist",
":whitelist_packed_format",
"//base", "//base",
"//base/test:test_support", "//base/test:test_support",
"//chrome/common:version_header", "//chrome/common:version_header",
......
...@@ -14,32 +14,22 @@ ...@@ -14,32 +14,22 @@
#include "chrome/install_static/user_data_dir.h" #include "chrome/install_static/user_data_dir.h"
#include "chrome_elf/sha1/sha1.h" #include "chrome_elf/sha1/sha1.h"
#include "chrome_elf/whitelist/whitelist_file_format.h" #include "chrome_elf/whitelist/whitelist_packed_format.h"
namespace whitelist { namespace whitelist {
namespace { namespace {
// TODO(pennymac): update subdir and filename with final shared defines.
constexpr wchar_t kFileSubdir[] =
L"\\ThirdPartyModuleList"
#if defined(_WIN64)
L"64";
#else
L"32";
#endif
constexpr wchar_t kFileName[] = L"\\dbfile";
// No concern about concurrency control in chrome_elf. // No concern about concurrency control in chrome_elf.
bool g_initialized = false; bool g_initialized = false;
// This will hold a packed whitelist module array, read directly from a // This will hold a packed blacklist module array, read directly from a
// component-update file during InitComponent(). // data file during InitComponent().
PackedWhitelistModule* g_module_array = nullptr; PackedWhitelistModule* g_bl_module_array = nullptr;
size_t g_module_array_size = 0; size_t g_bl_module_array_size = 0;
// NOTE: this "global" is only initialized once during InitComponent(). // NOTE: this "global" is only initialized once during InitComponent().
// NOTE: this is wrapped in a function to prevent exit-time dtors. // NOTE: it is wrapped in a function to prevent exit-time dtors.
std::wstring& GetFilePath() { std::wstring& GetBlFilePath() {
static std::wstring* const file_path = new std::wstring(); static std::wstring* const file_path = new std::wstring();
return *file_path; return *file_path;
} }
...@@ -71,10 +61,12 @@ bool HashBinaryPredicate(const PackedWhitelistModule& lhs, ...@@ -71,10 +61,12 @@ bool HashBinaryPredicate(const PackedWhitelistModule& lhs,
return CompareHashes(lhs.basename_hash, rhs.basename_hash) < 0; return CompareHashes(lhs.basename_hash, rhs.basename_hash) < 0;
} }
// Given a file opened for read, pull in the packed whitelist. // Given a file opened for read, pull in the packed list.
// //
// - Returns kSuccess or kArraySizeZero on success. // - Returns kSuccess or kArraySizeZero on success.
FileStatus ReadInArray(HANDLE file) { FileStatus ReadInArray(HANDLE file,
size_t* array_size,
PackedWhitelistModule** array_ptr) {
PackedWhitelistMetadata metadata; PackedWhitelistMetadata metadata;
DWORD bytes_read = 0; DWORD bytes_read = 0;
...@@ -88,71 +80,98 @@ FileStatus ReadInArray(HANDLE file) { ...@@ -88,71 +80,98 @@ FileStatus ReadInArray(HANDLE file) {
if (metadata.version != PackedWhitelistVersion::kCurrent) if (metadata.version != PackedWhitelistVersion::kCurrent)
return FileStatus::kInvalidFormatVersion; return FileStatus::kInvalidFormatVersion;
g_module_array_size = metadata.module_count; *array_size = metadata.module_count;
// Check for size 0. // Check for size 0.
if (!g_module_array_size) if (!*array_size)
return FileStatus::kArraySizeZero; return FileStatus::kArraySizeZero;
// Sanity check the array fits in a DWORD. // Sanity check the array fits in a DWORD.
if (g_module_array_size > if (*array_size >
(std::numeric_limits<DWORD>::max() / sizeof(PackedWhitelistModule))) { (std::numeric_limits<DWORD>::max() / sizeof(PackedWhitelistModule))) {
assert(false); assert(false);
return FileStatus::kArrayTooBig; return FileStatus::kArrayTooBig;
} }
DWORD buffer_size = DWORD buffer_size =
static_cast<DWORD>(g_module_array_size * sizeof(PackedWhitelistModule)); static_cast<DWORD>(*array_size * sizeof(PackedWhitelistModule));
g_module_array = *array_ptr =
reinterpret_cast<PackedWhitelistModule*>(new uint8_t[buffer_size]); reinterpret_cast<PackedWhitelistModule*>(new uint8_t[buffer_size]);
// Read in the array. // Read in the array.
// NOTE: Ignore the rest of the file - other data could be stored at the end. // NOTE: Ignore the rest of the file - other data could be stored at the end.
if (!::ReadFile(file, g_module_array, buffer_size, &bytes_read, FALSE) || if (!::ReadFile(file, *array_ptr, buffer_size, &bytes_read, FALSE) ||
bytes_read != buffer_size) { bytes_read != buffer_size) {
delete[] g_module_array; delete[] * array_ptr;
g_module_array = nullptr; *array_ptr = nullptr;
g_module_array_size = 0; *array_size = 0;
return FileStatus::kArrayReadFail; return FileStatus::kArrayReadFail;
} }
// TODO(pennymac): calculate cost of is_sorted() call against real database
// array. Is it too expensive for startup? Maybe do a delayed check? // Ensure array is sorted (as expected).
if (!std::is_sorted(g_module_array, g_module_array + g_module_array_size, if (!std::is_sorted(*array_ptr, *array_ptr + *array_size,
HashBinaryPredicate)) { HashBinaryPredicate)) {
delete[] g_module_array; delete[] * array_ptr;
g_module_array = nullptr; *array_ptr = nullptr;
g_module_array_size = 0; *array_size = 0;
return FileStatus::kArrayNotSorted; return FileStatus::kArrayNotSorted;
} }
return FileStatus::kSuccess; return FileStatus::kSuccess;
} }
// Example file location, relative to user data dir. // Open a packed data file.
// %localappdata% / Google / Chrome SxS / User Data / ThirdPartyModuleList64 /
// //
// TODO(pennymac): Missing or malformed component file shouldn't happen. // - Returns kSuccess or kFileNotFound on success.
// Possible UMA log in future. FileStatus OpenDataFile(HANDLE* file_handle) {
FileStatus InitInternal() { *file_handle = INVALID_HANDLE_VALUE;
std::wstring& file_path = GetFilePath(); std::wstring& file_path = GetBlFilePath();
// The path may have been overridden for testing. // The path may have been overridden for testing.
if (file_path.empty()) { if (file_path.empty()) {
if (!install_static::GetUserDataDirectory(&file_path, nullptr)) if (!install_static::GetUserDataDirectory(&file_path, nullptr))
return FileStatus::kUserDataDirFail; return FileStatus::kUserDataDirFail;
file_path.append(kFileSubdir); file_path.append(kFileSubdir);
file_path.append(kFileName); file_path.append(kBlFileName);
} }
// See if file exists. INVALID_HANDLE_VALUE alert! // See if file exists. INVALID_HANDLE_VALUE alert!
HANDLE file = *file_handle =
::CreateFileW(file_path.c_str(), FILE_READ_DATA, ::CreateFileW(file_path.c_str(), FILE_READ_DATA,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
if (file == INVALID_HANDLE_VALUE) if (*file_handle == INVALID_HANDLE_VALUE) {
return FileStatus::kFileNotFound; switch (::GetLastError()) {
case ERROR_FILE_NOT_FOUND:
case ERROR_PATH_NOT_FOUND:
return FileStatus::kFileNotFound;
case ERROR_ACCESS_DENIED:
return FileStatus::kFileAccessDenied;
default:
return FileStatus::kFileUnexpectedFailure;
}
}
FileStatus status = ReadInArray(file); return FileStatus::kSuccess;
::CloseHandle(file); }
// Example file location, relative to user data dir.
// %localappdata% / Google / Chrome SxS / User Data / ThirdPartyModuleList64 /
//
// - NOTE: kFileNotFound and kArraySizeZero are treated as kSuccess.
FileStatus InitInternal() {
// blacklist
// ---------
HANDLE handle = INVALID_HANDLE_VALUE;
FileStatus status = OpenDataFile(&handle);
if (status == FileStatus::kFileNotFound)
return FileStatus::kSuccess;
if (status == FileStatus::kSuccess) {
status = ReadInArray(handle, &g_bl_module_array_size, &g_bl_module_array);
::CloseHandle(handle);
}
if (status == FileStatus::kArraySizeZero)
return FileStatus::kSuccess;
return status; return status;
} }
...@@ -162,11 +181,11 @@ FileStatus InitInternal() { ...@@ -162,11 +181,11 @@ FileStatus InitInternal() {
// Public defines & functions // Public defines & functions
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool IsModuleWhitelisted(const std::string& basename, bool IsModuleListed(const std::string& basename,
DWORD image_size, DWORD image_size,
DWORD time_date_stamp) { DWORD time_date_stamp) {
assert(g_initialized); assert(g_initialized);
if (!g_module_array_size) if (!g_bl_module_array_size)
return false; return false;
// Max hex 32-bit value is 8 characters long. 2*8+1. // Max hex 32-bit value is 8 characters long. 2*8+1.
...@@ -181,9 +200,9 @@ bool IsModuleWhitelisted(const std::string& basename, ...@@ -181,9 +200,9 @@ bool IsModuleWhitelisted(const std::string& basename,
// Binary search for primary hash (basename). There can be more than one // Binary search for primary hash (basename). There can be more than one
// match. // match.
auto pair = auto pair = std::equal_range(g_bl_module_array,
std::equal_range(g_module_array, g_module_array + g_module_array_size, g_bl_module_array + g_bl_module_array_size,
target, HashBinaryPredicate); target, HashBinaryPredicate);
// Search for secondary hash. // Search for secondary hash.
for (PackedWhitelistModule* i = pair.first; i != pair.second; ++i) { for (PackedWhitelistModule* i = pair.first; i != pair.second; ++i) {
...@@ -195,16 +214,16 @@ bool IsModuleWhitelisted(const std::string& basename, ...@@ -195,16 +214,16 @@ bool IsModuleWhitelisted(const std::string& basename,
return false; return false;
} }
std::wstring GetFilePathUsed() { std::wstring GetBlFilePathUsed() {
return GetFilePath(); return GetBlFilePath();
} }
// Grab the latest whitelist file. // Grab the latest whitelist and blacklist.
FileStatus InitFromFile() { FileStatus InitFromFile() {
// Debug check: InitFromFile should not be called more than once. // Debug check: InitFromFile should not be called more than once.
assert(!g_initialized); assert(!g_initialized);
// TODO(pennymac): Should kArraySizeZero be a failure? Or just UMA? // TODO(pennymac): Possible UMA log for unexpected failures.
FileStatus status = InitInternal(); FileStatus status = InitInternal();
if (status == FileStatus::kSuccess) if (status == FileStatus::kSuccess)
...@@ -213,8 +232,8 @@ FileStatus InitFromFile() { ...@@ -213,8 +232,8 @@ FileStatus InitFromFile() {
return status; return status;
} }
void OverrideFilePathForTesting(const std::wstring& new_path) { void OverrideFilePathForTesting(const std::wstring& new_bl_path) {
GetFilePath().assign(new_path); GetBlFilePath().assign(new_bl_path);
} }
} // namespace whitelist } // namespace whitelist
...@@ -16,29 +16,31 @@ enum class FileStatus { ...@@ -16,29 +16,31 @@ enum class FileStatus {
kSuccess = 0, kSuccess = 0,
kUserDataDirFail = 1, kUserDataDirFail = 1,
kFileNotFound = 2, kFileNotFound = 2,
kMetadataReadFail = 3, kFileAccessDenied = 3,
kInvalidFormatVersion = 4, kFileUnexpectedFailure = 4,
kArraySizeZero = 5, kMetadataReadFail = 5,
kArrayTooBig = 6, kInvalidFormatVersion = 6,
kArrayReadFail = 7, kArraySizeZero = 7,
kArrayNotSorted = 8, kArrayTooBig = 8,
kArrayReadFail = 9,
kArrayNotSorted = 10,
COUNT COUNT
}; };
// Look up a binary based on the required data points. // Look up a binary based on the required data points.
// - Returns true if match found in whitelist. I.E. Allow module load. // - Returns true if match found in the blacklist. I.E. Block if true.
bool IsModuleWhitelisted(const std::string& basename, bool IsModuleListed(const std::string& basename,
DWORD image_size, DWORD image_size,
DWORD time_date_stamp); DWORD time_date_stamp);
// Get the full path of the whitelist file used. // Get the full path of the blacklist file used.
std::wstring GetFilePathUsed(); std::wstring GetBlFilePathUsed();
// Initialize internal whitelist from file. // Initialize internal whitelist from file.
FileStatus InitFromFile(); FileStatus InitFromFile();
// Sets the path to the whitelist file for use by tests. // Overrides the blacklist path for use by tests.
void OverrideFilePathForTesting(const std::wstring& new_path); void OverrideFilePathForTesting(const std::wstring& new_bl_path);
} // namespace whitelist } // namespace whitelist
......
...@@ -17,13 +17,13 @@ ...@@ -17,13 +17,13 @@
#include "base/win/pe_image.h" #include "base/win/pe_image.h"
#include "chrome/install_static/user_data_dir.h" #include "chrome/install_static/user_data_dir.h"
#include "chrome_elf/sha1/sha1.h" #include "chrome_elf/sha1/sha1.h"
#include "chrome_elf/whitelist/whitelist_file_format.h" #include "chrome_elf/whitelist/whitelist_packed_format.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
namespace whitelist { namespace whitelist {
namespace { namespace {
constexpr wchar_t kFileName[] = L"dbfile"; constexpr wchar_t kTestBlFileName[] = L"blfile";
constexpr DWORD kPageSize = 4096; constexpr DWORD kPageSize = 4096;
struct TestModule { struct TestModule {
...@@ -87,7 +87,7 @@ bool GetTestModules(std::vector<TestModule>* test_modules, ...@@ -87,7 +87,7 @@ bool GetTestModules(std::vector<TestModule>* test_modules,
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// WhitelistComponentTest class // WhitelistFileTest class
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
class WhitelistFileTest : public testing::Test { class WhitelistFileTest : public testing::Test {
...@@ -95,74 +95,113 @@ class WhitelistFileTest : public testing::Test { ...@@ -95,74 +95,113 @@ class WhitelistFileTest : public testing::Test {
WhitelistFileTest() = default; WhitelistFileTest() = default;
void SetUp() override { void SetUp() override {
std::vector<PackedWhitelistModule> test_file_array; ASSERT_TRUE(GetTestModules(&test_array_, &test_packed_array_));
ASSERT_TRUE(GetTestModules(&test_array_, &test_file_array));
// Setup test component file. // Setup temp test dir.
ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir()); ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir());
// Store full path to test file (without creating it yet).
base::FilePath path = scoped_temp_dir_.GetPath(); base::FilePath path = scoped_temp_dir_.GetPath();
path = path.Append(kTestBlFileName);
bl_test_file_path_ = std::move(path.value());
// Create the component file. It will be cleaned up with // Override the file paths in the live code for testing.
// |scoped_temp_dir_|. OverrideFilePathForTesting(bl_test_file_path_);
path = path.Append(kFileName); }
base::File file(path, base::File::FLAG_CREATE_ALWAYS |
base::File::FLAG_WRITE |
base::File::FLAG_SHARE_DELETE |
base::File::FLAG_DELETE_ON_CLOSE);
ASSERT_TRUE(file.IsValid());
// Store the path for tests to use. void CreateTestFile() {
test_file_path_ = std::move(path.value()); base::File file(base::FilePath(bl_test_file_path_),
base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
base::File::FLAG_SHARE_DELETE |
base::File::FLAG_DELETE_ON_CLOSE);
ASSERT_TRUE(file.IsValid());
// Write content {metadata}{array_of_modules}. // Write content {metadata}{array_of_modules}.
PackedWhitelistMetadata meta = { PackedWhitelistMetadata meta = {
kInitialVersion, static_cast<uint32_t>(test_file_array.size())}; kInitialVersion, static_cast<uint32_t>(test_packed_array_.size())};
ASSERT_TRUE(file.Write(0, reinterpret_cast<const char*>(&meta), ASSERT_EQ(file.Write(0, reinterpret_cast<const char*>(&meta), sizeof(meta)),
sizeof(meta)) == sizeof(meta)); static_cast<int>(sizeof(meta)));
int size = static_cast<int>(test_file_array.size() * int size = static_cast<int>(test_packed_array_.size() *
sizeof(PackedWhitelistModule)); sizeof(PackedWhitelistModule));
ASSERT_TRUE( ASSERT_EQ(
file.Write(sizeof(PackedWhitelistMetadata), file.Write(sizeof(PackedWhitelistMetadata),
reinterpret_cast<const char*>(test_file_array.data()), reinterpret_cast<const char*>(test_packed_array_.data()),
size) == size); size),
size);
// Leave file handle open for DELETE_ON_CLOSE. // Leave file handle open for DELETE_ON_CLOSE.
file_ = std::move(file); bl_file_ = std::move(file);
} }
const base::string16& GetTestFilePath() { return test_file_path_; } const base::string16& GetBlTestFilePath() { return bl_test_file_path_; }
base::File* GetBlFile() { return &bl_file_; }
const std::vector<TestModule>& GetTestArray() { return test_array_; } const std::vector<TestModule>& GetTestArray() { return test_array_; }
private: private:
base::ScopedTempDir scoped_temp_dir_; base::ScopedTempDir scoped_temp_dir_;
base::File file_; base::File bl_file_;
base::string16 test_file_path_; base::string16 bl_test_file_path_;
std::vector<TestModule> test_array_; std::vector<TestModule> test_array_;
std::vector<PackedWhitelistModule> test_packed_array_;
DISALLOW_COPY_AND_ASSIGN(WhitelistFileTest); DISALLOW_COPY_AND_ASSIGN(WhitelistFileTest);
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Whitelist component tests // Whitelist file tests
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Test initialization of the whitelist from file. // Test successful initialization and module lookup.
TEST_F(WhitelistFileTest, Init) { TEST_F(WhitelistFileTest, Success) {
// Override the component file path for testing. // Create blacklist data file.
OverrideFilePathForTesting(GetTestFilePath()); CreateTestFile();
// Init component whitelist! // Init.
ASSERT_EQ(InitFromFile(), FileStatus::kSuccess); ASSERT_EQ(InitFromFile(), FileStatus::kSuccess);
// Test matching. // Test matching.
for (const auto& test_module : GetTestArray()) { for (const auto& test_module : GetTestArray()) {
ASSERT_TRUE(IsModuleWhitelisted(test_module.basename, test_module.imagesize, EXPECT_TRUE(IsModuleListed(test_module.basename, test_module.imagesize,
test_module.timedatestamp)); test_module.timedatestamp));
} }
// Test a failure to match. // Test a failure to match.
ASSERT_FALSE(IsModuleWhitelisted("booya.dll", 1337, 0x12345678)); EXPECT_FALSE(IsModuleListed("booya.dll", 1337, 0x12345678));
}
// Test successful initialization with no packed files.
TEST_F(WhitelistFileTest, NoFiles) {
ASSERT_EQ(InitFromFile(), FileStatus::kSuccess);
EXPECT_FALSE(IsModuleListed("booya.dll", 1337, 0x12345678));
}
TEST_F(WhitelistFileTest, CorruptFile) {
CreateTestFile();
base::File* file = GetBlFile();
ASSERT_TRUE(file->IsValid());
// 1) Not enough data for array size
PackedWhitelistMetadata meta = {kCurrent, static_cast<uint32_t>(50)};
ASSERT_EQ(file->Write(0, reinterpret_cast<const char*>(&meta), sizeof(meta)),
static_cast<int>(sizeof(meta)));
EXPECT_EQ(InitFromFile(), FileStatus::kArrayReadFail);
// 2) Corrupt data or just unsupported metadata version.
meta = {kUnsupported, static_cast<uint32_t>(50)};
ASSERT_EQ(file->Write(0, reinterpret_cast<const char*>(&meta), sizeof(meta)),
static_cast<int>(sizeof(meta)));
EXPECT_EQ(InitFromFile(), FileStatus::kInvalidFormatVersion);
// 3) Not enough data for metadata.
meta = {kCurrent, static_cast<uint32_t>(10)};
ASSERT_EQ(
file->Write(0, reinterpret_cast<const char*>(&meta), sizeof(meta) / 2),
static_cast<int>(sizeof(meta) / 2));
ASSERT_TRUE(file->SetLength(sizeof(meta) / 2));
EXPECT_EQ(InitFromFile(), FileStatus::kMetadataReadFail);
} }
} // namespace } // namespace
......
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome_elf/whitelist/whitelist_packed_format.h"
namespace whitelist {
// Subdir relative to install_static::GetUserDataDirectory().
const wchar_t kFileSubdir[] =
L"\\ThirdPartyModuleList"
#if defined(_WIN64)
L"64";
#else
L"32";
#endif
// Packed module data cache file.
const wchar_t kBlFileName[] = L"\\bldata";
} // namespace whitelist
...@@ -14,14 +14,23 @@ ...@@ -14,14 +14,23 @@
// second by code_id hash (there can be multiple of the same basename hash). // second by code_id hash (there can be multiple of the same basename hash).
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#ifndef CHROME_ELF_WHITELIST_WHITELIST_FILE_FORMAT_H_ #ifndef CHROME_ELF_WHITELIST_WHITELIST_PACKED_FORMAT_H_
#define CHROME_ELF_WHITELIST_WHITELIST_FILE_FORMAT_H_ #define CHROME_ELF_WHITELIST_WHITELIST_PACKED_FORMAT_H_
#include <stdint.h>
namespace whitelist { namespace whitelist {
// Subdir relative to install_static::GetUserDataDirectory().
extern const wchar_t kFileSubdir[];
// Packed module data cache file.
extern const wchar_t kBlFileName[];
enum PackedWhitelistVersion : uint32_t { enum PackedWhitelistVersion : uint32_t {
kInitialVersion = 1, kInitialVersion = 1,
kCurrent = kInitialVersion, kCurrent = kInitialVersion,
kUnsupported
}; };
struct PackedWhitelistMetadata { struct PackedWhitelistMetadata {
...@@ -40,6 +49,9 @@ struct PackedWhitelistModule { ...@@ -40,6 +49,9 @@ struct PackedWhitelistModule {
// the FileHeader.TimeDateStamp and OptionalHeader.SizeOfImage with the // the FileHeader.TimeDateStamp and OptionalHeader.SizeOfImage with the
// formatting string %08X%x. Then SHA1 the string. // formatting string %08X%x. Then SHA1 the string.
uint8_t code_id_hash[20]; uint8_t code_id_hash[20];
// A timestamp used for tracking "last attempted load". Used to manage
// lifetime of entries in the local caches.
uint32_t time_date_stamp;
}; };
// These struct are directly written to a file. Therefore the padding should // These struct are directly written to a file. Therefore the padding should
...@@ -47,10 +59,10 @@ struct PackedWhitelistModule { ...@@ -47,10 +59,10 @@ struct PackedWhitelistModule {
static_assert(sizeof(PackedWhitelistMetadata) == 8, static_assert(sizeof(PackedWhitelistMetadata) == 8,
"The actual padding of the PackedWhitelistMetadata struct " "The actual padding of the PackedWhitelistMetadata struct "
"doesn't match the expected padding"); "doesn't match the expected padding");
static_assert(sizeof(PackedWhitelistModule) == 40, static_assert(sizeof(PackedWhitelistModule) == 44,
"The actual padding of the PackedWhitelistModule struct doesn't " "The actual padding of the PackedWhitelistModule struct doesn't "
"match the expected padding"); "match the expected padding");
} // namespace whitelist } // namespace whitelist
#endif // CHROME_ELF_WHITELIST_WHITELIST_FILE_FORMAT_H_ #endif // CHROME_ELF_WHITELIST_WHITELIST_PACKED_FORMAT_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment