#include "chrome/chrome_elf/chrome_elf_security.h"
#include <windows.h>
#include <versionhelpers.h>
#include <assert.h>
#include <ntstatus.h>
#include <optional>
#include "base/check.h"
#include "base/file_version_info.h"
#include "base/logging.h"
#include "base/threading/thread_checker.h"
#include "base/win/current_module.h"
#include "chrome/chrome_elf/chrome_elf_constants.h"
#include "chrome/chrome_elf/nt_registry/nt_registry.h"
#include "chrome/install_static/install_util.h"
namespace elf_security {
namespace {
static bool g_validate_not_exe_for_testing = true;
void MaybeValidateNotCallingFromExe() {
HMODULE module;
DCHECK(::GetModuleHandleExW(0, NULL, &module));
DCHECK(CURRENT_MODULE() != module);
}
class ExtensionPointDisableSet {
public:
~ExtensionPointDisableSet() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
}
ExtensionPointDisableSet(const ExtensionPointDisableSet&) = delete;
ExtensionPointDisableSet& operator=(const ExtensionPointDisableSet&) = delete;
static ExtensionPointDisableSet* GetInstance() {
static ExtensionPointDisableSet* instance = nullptr;
if (!instance) {
instance = new ExtensionPointDisableSet();
}
return instance;
}
void SetExtensionPointDisabled(bool set) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
CHECK(!extension_point_disable_set_.has_value());
extension_point_disable_set_ = set;
}
bool GetExtensionPointDisabled() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (extension_point_disable_set_.has_value())
return extension_point_disable_set_.value();
return false;
}
private:
ExtensionPointDisableSet() { DETACH_FROM_THREAD(thread_checker_); }
THREAD_CHECKER(thread_checker_);
std::optional<bool> extension_point_disable_set_
GUARDED_BY_CONTEXT(thread_checker_);
};
}
void EarlyBrowserSecurity() {
NTSTATUS ret_val = STATUS_SUCCESS;
HANDLE handle = INVALID_HANDLE_VALUE;
if (!nt::OpenRegKey(nt::HKCU,
install_static::GetRegistryPath()
.append(elf_sec::kRegBrowserExtensionPointKeyName)
.c_str(),
KEY_QUERY_VALUE, &handle, &ret_val)) {
#ifdef _DEBUG
if (ret_val != STATUS_OBJECT_NAME_NOT_FOUND)
assert(false);
#endif
return;
}
nt::CloseRegKey(handle);
PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY policy = {};
policy.DisableExtensionPoints = true;
SetProcessMitigationPolicy(ProcessExtensionPointDisablePolicy, &policy,
sizeof(policy));
ExtensionPointDisableSet::GetInstance()->SetExtensionPointDisabled(true);
return;
}
void ValidateExeForTesting(bool on) {
g_validate_not_exe_for_testing = on;
}
bool IsExtensionPointDisableSet() {
if (g_validate_not_exe_for_testing)
MaybeValidateNotCallingFromExe();
return ExtensionPointDisableSet::GetInstance()->GetExtensionPointDisabled();
}
}