Commit 89224288 authored by Patrick Monette's avatar Patrick Monette Committed by Commit Bot

Track modules that bypass the blocking in chrome_elf

Also render them valid to trigger an incompatible applications warning.

Bug: 846953
Change-Id: I6fa9951043d19a44a820aeaf44cab1c0e9b981e2
Reviewed-on: https://chromium-review.googlesource.com/1158986Reviewed-by: default avatarChris Hamilton <chrisha@chromium.org>
Commit-Queue: Chris Hamilton <chrisha@chromium.org>
Cr-Commit-Position: refs/heads/master@{#581393}
parent fb4e7fd6
...@@ -156,10 +156,13 @@ ModuleBlacklistCacheUpdater::ModuleBlacklistCacheUpdater( ...@@ -156,10 +156,13 @@ ModuleBlacklistCacheUpdater::ModuleBlacklistCacheUpdater(
ModuleDatabaseEventSource* module_database_event_source, ModuleDatabaseEventSource* module_database_event_source,
const CertificateInfo& exe_certificate_info, const CertificateInfo& exe_certificate_info,
scoped_refptr<ModuleListFilter> module_list_filter, scoped_refptr<ModuleListFilter> module_list_filter,
const std::vector<third_party_dlls::PackedListModule>&
initial_blacklisted_modules,
OnCacheUpdatedCallback on_cache_updated_callback) OnCacheUpdatedCallback on_cache_updated_callback)
: module_database_event_source_(module_database_event_source), : module_database_event_source_(module_database_event_source),
exe_certificate_info_(exe_certificate_info), exe_certificate_info_(exe_certificate_info),
module_list_filter_(std::move(module_list_filter)), module_list_filter_(std::move(module_list_filter)),
initial_blacklisted_modules_(initial_blacklisted_modules),
on_cache_updated_callback_(std::move(on_cache_updated_callback)), on_cache_updated_callback_(std::move(on_cache_updated_callback)),
background_sequence_(base::CreateSequencedTaskRunnerWithTraits( background_sequence_(base::CreateSequencedTaskRunnerWithTraits(
{base::MayBlock(), base::TaskPriority::BEST_EFFORT, {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
...@@ -283,12 +286,26 @@ void ModuleBlacklistCacheUpdater::OnNewModuleFound( ...@@ -283,12 +286,26 @@ void ModuleBlacklistCacheUpdater::OnNewModuleFound(
return; return;
} }
// Now it has been determined that the module should be blocked. // Now it has been determined that the module should be blocked. So make sure
// it gets added to the blacklist cache.
InsertPackedListModule(module_key, &newly_blacklisted_modules_);
// Check if a blacklisted module was able to bypass the blocking.
if (std::binary_search(std::begin(initial_blacklisted_modules_),
std::end(initial_blacklisted_modules_),
newly_blacklisted_modules_.back(),
internal::ModuleLess())) {
module_blocking_decisions_[module_key.module_id] = module_blocking_decisions_[module_key.module_id] =
ModuleBlockingDecision::kBlacklisted; ModuleBlockingDecision::kBypassedBlocking;
// Insert the blacklisted module. // Return here and don't notify the ModuleDatabase that the module was added
InsertPackedListModule(module_key, &newly_blacklisted_modules_); // to the blacklist so that it can trigger an incompatible applications
// warning.
return;
}
module_blocking_decisions_[module_key.module_id] =
ModuleBlockingDecision::kBlacklisted;
// Signal the module database that this module will be added to the cache. // Signal the module database that this module will be added to the cache.
// Note that observers that care about this information should register to // Note that observers that care about this information should register to
......
...@@ -100,6 +100,8 @@ class ModuleBlacklistCacheUpdater : public ModuleDatabaseObserver { ...@@ -100,6 +100,8 @@ class ModuleBlacklistCacheUpdater : public ModuleDatabaseObserver {
kBlacklisted, kBlacklisted,
// The module was blocked from loading into the process. // The module was blocked from loading into the process.
kBlocked, kBlocked,
// This module should have been blocked but wasn't.
kBypassedBlocking,
}; };
struct CacheUpdateResult { struct CacheUpdateResult {
...@@ -123,6 +125,8 @@ class ModuleBlacklistCacheUpdater : public ModuleDatabaseObserver { ...@@ -123,6 +125,8 @@ class ModuleBlacklistCacheUpdater : public ModuleDatabaseObserver {
ModuleDatabaseEventSource* module_database_event_source, ModuleDatabaseEventSource* module_database_event_source,
const CertificateInfo& exe_certificate_info, const CertificateInfo& exe_certificate_info,
scoped_refptr<ModuleListFilter> module_list_filter, scoped_refptr<ModuleListFilter> module_list_filter,
const std::vector<third_party_dlls::PackedListModule>&
initial_blacklisted_modules,
OnCacheUpdatedCallback on_cache_updated_callback); OnCacheUpdatedCallback on_cache_updated_callback);
~ModuleBlacklistCacheUpdater() override; ~ModuleBlacklistCacheUpdater() override;
...@@ -161,6 +165,8 @@ class ModuleBlacklistCacheUpdater : public ModuleDatabaseObserver { ...@@ -161,6 +165,8 @@ class ModuleBlacklistCacheUpdater : public ModuleDatabaseObserver {
const CertificateInfo& exe_certificate_info_; const CertificateInfo& exe_certificate_info_;
scoped_refptr<ModuleListFilter> module_list_filter_; scoped_refptr<ModuleListFilter> module_list_filter_;
const std::vector<third_party_dlls::PackedListModule>&
initial_blacklisted_modules_;
OnCacheUpdatedCallback on_cache_updated_callback_; OnCacheUpdatedCallback on_cache_updated_callback_;
......
...@@ -117,6 +117,7 @@ class ModuleBlacklistCacheUpdaterTest : public testing::Test, ...@@ -117,6 +117,7 @@ class ModuleBlacklistCacheUpdaterTest : public testing::Test,
CreateModuleBlacklistCacheUpdater() { CreateModuleBlacklistCacheUpdater() {
return std::make_unique<ModuleBlacklistCacheUpdater>( return std::make_unique<ModuleBlacklistCacheUpdater>(
this, exe_certificate_info_, module_list_filter_, this, exe_certificate_info_, module_list_filter_,
initial_blacklisted_modules_,
base::BindRepeating( base::BindRepeating(
&ModuleBlacklistCacheUpdaterTest::OnModuleBlacklistCacheUpdated, &ModuleBlacklistCacheUpdaterTest::OnModuleBlacklistCacheUpdated,
base::Unretained(this))); base::Unretained(this)));
...@@ -184,6 +185,7 @@ class ModuleBlacklistCacheUpdaterTest : public testing::Test, ...@@ -184,6 +185,7 @@ class ModuleBlacklistCacheUpdaterTest : public testing::Test,
CertificateInfo exe_certificate_info_; CertificateInfo exe_certificate_info_;
scoped_refptr<ModuleListFilter> module_list_filter_; scoped_refptr<ModuleListFilter> module_list_filter_;
std::vector<third_party_dlls::PackedListModule> initial_blacklisted_modules_;
base::FilePath module_blacklist_cache_path_; base::FilePath module_blacklist_cache_path_;
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "chrome/browser/conflicts/incompatible_applications_updater_win.h" #include "chrome/browser/conflicts/incompatible_applications_updater_win.h"
#include "chrome/browser/conflicts/installed_applications_win.h" #include "chrome/browser/conflicts/installed_applications_win.h"
#include "chrome/browser/conflicts/module_blacklist_cache_updater_win.h" #include "chrome/browser/conflicts/module_blacklist_cache_updater_win.h"
#include "chrome/browser/conflicts/module_blacklist_cache_util_win.h"
#include "chrome/browser/conflicts/module_info_util_win.h" #include "chrome/browser/conflicts/module_info_util_win.h"
#include "chrome/browser/conflicts/module_list_filter_win.h" #include "chrome/browser/conflicts/module_list_filter_win.h"
#include "chrome/common/chrome_features.h" #include "chrome/common/chrome_features.h"
...@@ -53,6 +54,26 @@ scoped_refptr<ModuleListFilter> CreateModuleListFilter( ...@@ -53,6 +54,26 @@ scoped_refptr<ModuleListFilter> CreateModuleListFilter(
return module_list_filter; return module_list_filter;
} }
std::unique_ptr<std::vector<third_party_dlls::PackedListModule>>
ReadInitialBlacklistedModules() {
base::FilePath path =
ModuleBlacklistCacheUpdater::GetModuleBlacklistCachePath();
third_party_dlls::PackedListMetadata metadata;
std::vector<third_party_dlls::PackedListModule> blacklisted_modules;
base::MD5Digest md5_digest;
ReadResult read_result = ReadModuleBlacklistCache(
path, &metadata, &blacklisted_modules, &md5_digest);
// Return an empty vector on failure.
auto initial_blacklisted_modules =
std::make_unique<std::vector<third_party_dlls::PackedListModule>>();
if (read_result == ReadResult::kSuccess)
*initial_blacklisted_modules = std::move(blacklisted_modules);
return initial_blacklisted_modules;
}
} // namespace } // namespace
ThirdPartyConflictsManager::ThirdPartyConflictsManager( ThirdPartyConflictsManager::ThirdPartyConflictsManager(
...@@ -123,9 +144,7 @@ void ThirdPartyConflictsManager::OnModuleDatabaseIdle() { ...@@ -123,9 +144,7 @@ void ThirdPartyConflictsManager::OnModuleDatabaseIdle() {
// The InstalledApplications instance is only needed for the incompatible // The InstalledApplications instance is only needed for the incompatible
// applications warning. // applications warning.
if (!IncompatibleApplicationsUpdater::IsWarningEnabled()) if (IncompatibleApplicationsUpdater::IsWarningEnabled()) {
return;
base::PostTaskAndReplyWithResult( base::PostTaskAndReplyWithResult(
background_sequence_.get(), FROM_HERE, base::BindOnce([]() { background_sequence_.get(), FROM_HERE, base::BindOnce([]() {
return std::make_unique<InstalledApplications>(); return std::make_unique<InstalledApplications>();
...@@ -133,6 +152,18 @@ void ThirdPartyConflictsManager::OnModuleDatabaseIdle() { ...@@ -133,6 +152,18 @@ void ThirdPartyConflictsManager::OnModuleDatabaseIdle() {
base::BindOnce( base::BindOnce(
&ThirdPartyConflictsManager::OnInstalledApplicationsCreated, &ThirdPartyConflictsManager::OnInstalledApplicationsCreated,
weak_ptr_factory_.GetWeakPtr())); weak_ptr_factory_.GetWeakPtr()));
}
// And the initial blacklisted modules are only needed for the third-party
// modules blocking.
if (base::FeatureList::IsEnabled(features::kThirdPartyModulesBlocking)) {
base::PostTaskAndReplyWithResult(
background_sequence_.get(), FROM_HERE,
base::BindOnce(&ReadInitialBlacklistedModules),
base::BindOnce(
&ThirdPartyConflictsManager::OnInitialBlacklistedModulesRead,
weak_ptr_factory_.GetWeakPtr()));
}
} }
void ThirdPartyConflictsManager::OnModuleListComponentRegistered( void ThirdPartyConflictsManager::OnModuleListComponentRegistered(
...@@ -270,23 +301,43 @@ void ThirdPartyConflictsManager::OnInstalledApplicationsCreated( ...@@ -270,23 +301,43 @@ void ThirdPartyConflictsManager::OnInstalledApplicationsCreated(
InitializeIfReady(); InitializeIfReady();
} }
void ThirdPartyConflictsManager::OnInitialBlacklistedModulesRead(
std::unique_ptr<std::vector<third_party_dlls::PackedListModule>>
initial_blacklisted_modules) {
initial_blacklisted_modules_ = std::move(initial_blacklisted_modules);
InitializeIfReady();
}
void ThirdPartyConflictsManager::InitializeIfReady() { void ThirdPartyConflictsManager::InitializeIfReady() {
DCHECK(!terminal_state_.has_value()); DCHECK(!terminal_state_.has_value());
// Check if this instance is ready to initialize. // Check if this instance is ready to initialize. First look at dependencies
if (!exe_certificate_info_ || !module_list_filter_ || // that both features need.
(!installed_applications_ && if (!exe_certificate_info_ || !module_list_filter_)
IncompatibleApplicationsUpdater::IsWarningEnabled())) { return;
// Then look at the dependency needed only for the
// IncompatibleApplicationsWarning feature.
if (IncompatibleApplicationsUpdater::IsWarningEnabled() &&
!installed_applications_) {
return;
}
// And the dependency needed only for the ThirdPartyModulesBlocking feature.
if (base::FeatureList::IsEnabled(features::kThirdPartyModulesBlocking) &&
!initial_blacklisted_modules_) {
return; return;
} }
// Now both features are ready to be initialized.
if (base::FeatureList::IsEnabled(features::kThirdPartyModulesBlocking)) { if (base::FeatureList::IsEnabled(features::kThirdPartyModulesBlocking)) {
// It is safe to use base::Unretained() since the callback will not be // It is safe to use base::Unretained() since the callback will not be
// invoked if the updater is freed. // invoked if the updater is freed.
module_blacklist_cache_updater_ = module_blacklist_cache_updater_ =
std::make_unique<ModuleBlacklistCacheUpdater>( std::make_unique<ModuleBlacklistCacheUpdater>(
module_database_event_source_, *exe_certificate_info_, module_database_event_source_, *exe_certificate_info_,
module_list_filter_, module_list_filter_, *initial_blacklisted_modules_,
base::BindRepeating( base::BindRepeating(
&ThirdPartyConflictsManager::OnModuleBlacklistCacheUpdated, &ThirdPartyConflictsManager::OnModuleBlacklistCacheUpdated,
base::Unretained(this))); base::Unretained(this)));
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector>
#include "base/callback.h" #include "base/callback.h"
#include "base/macros.h" #include "base/macros.h"
...@@ -17,6 +18,7 @@ ...@@ -17,6 +18,7 @@
#include "base/strings/string_piece_forward.h" #include "base/strings/string_piece_forward.h"
#include "chrome/browser/conflicts/module_blacklist_cache_updater_win.h" #include "chrome/browser/conflicts/module_blacklist_cache_updater_win.h"
#include "chrome/browser/conflicts/module_database_observer_win.h" #include "chrome/browser/conflicts/module_database_observer_win.h"
#include "chrome_elf/third_party_dlls/packed_list_format.h"
#include "components/component_updater/component_updater_service.h" #include "components/component_updater/component_updater_service.h"
class IncompatibleApplicationsUpdater; class IncompatibleApplicationsUpdater;
...@@ -31,12 +33,31 @@ class SequencedTaskRunner; ...@@ -31,12 +33,31 @@ class SequencedTaskRunner;
class TaskRunner; class TaskRunner;
} }
// This class owns all the third-party conflicts-related classes and is // This class is responsible for the initialization of the
// responsible for their initialization. // IncompatibleApplicationsWarning and ThirdPartyModulesBlocking features. Each
// feature requires a set of dependencies to be initialized on a background
// sequence because their main class can be created
// (IncompatibleApplicationsUpdater and ModuleBlacklistCacheUpdater
// respectively).
//
// Dependencies list
// For both features:
// 1. |exe_certificate_info_| contains info about the certificate of the current
// executable.
// 2. |module_list_filter_| is used to determine if a module should be blocked
// or allowed. The Module List component is received from the component
// update service, which invokes OnModuleListComponentRegister() and
// LoadModuleList() when appropriate.
//
// For the IncompatibleApplicationsWarning feature only:
// 3. |installed_applications_| allows to tie a loaded module to an application
// installed on the computer.
//
// For the ThirdPartyModulesBlocking feature only:
// 4. |initial_blacklisted_modules_| contains the list of modules that were
// blacklisted at the time the browser was launched. Modifications to that
// list do not take effect until a restart.
// //
// The Module List component is received from the component update service,
// which invokes OnModuleListComponentRegister() and LoadModuleList() when
// appropriate.
class ThirdPartyConflictsManager class ThirdPartyConflictsManager
: public ModuleDatabaseObserver, : public ModuleDatabaseObserver,
public component_updater::ComponentUpdateService::Observer { public component_updater::ComponentUpdateService::Observer {
...@@ -130,6 +151,11 @@ class ThirdPartyConflictsManager ...@@ -130,6 +151,11 @@ class ThirdPartyConflictsManager
void OnInstalledApplicationsCreated( void OnInstalledApplicationsCreated(
std::unique_ptr<InstalledApplications> installed_applications); std::unique_ptr<InstalledApplications> installed_applications);
// Called when |initial_blacklisted_modules_| finishes its initialization.
void OnInitialBlacklistedModulesRead(
std::unique_ptr<std::vector<third_party_dlls::PackedListModule>>
initial_blacklisted_modules);
// Initializes either or both |incompatible_applications_updater_| and // Initializes either or both |incompatible_applications_updater_| and
// |module_blacklist_cache_updater_| when the exe_certificate_info_, the // |module_blacklist_cache_updater_| when the exe_certificate_info_, the
// module_list_filter_ and the installed_applications_ are available. // module_list_filter_ and the installed_applications_ are available.
...@@ -185,6 +211,11 @@ class ThirdPartyConflictsManager ...@@ -185,6 +211,11 @@ class ThirdPartyConflictsManager
// use it on a background sequence. // use it on a background sequence.
scoped_refptr<ModuleListFilter> module_list_filter_; scoped_refptr<ModuleListFilter> module_list_filter_;
// The blacklisted modules contained in the cache used to initialize the
// blocking in chrome_elf.
std::unique_ptr<std::vector<third_party_dlls::PackedListModule>>
initial_blacklisted_modules_;
// Retrieves the list of installed applications. // Retrieves the list of installed applications.
std::unique_ptr<InstalledApplications> installed_applications_; std::unique_ptr<InstalledApplications> installed_applications_;
......
...@@ -75,6 +75,8 @@ std::string GetModuleStatusString( ...@@ -75,6 +75,8 @@ std::string GetModuleStatusString(
return "Disallowed - Added to the blacklist"; return "Disallowed - Added to the blacklist";
case BlockingDecision::kBlocked: case BlockingDecision::kBlocked:
return "Disallowed - Blocked"; return "Disallowed - Blocked";
case BlockingDecision::kBypassedBlocking:
return "Disallowed - Bypassed blocking";
case BlockingDecision::kUnknown: case BlockingDecision::kUnknown:
NOTREACHED(); NOTREACHED();
break; break;
......
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