| Index: chrome/browser/prefs/tracked/pref_hash_browsertest.cc
|
| diff --git a/chrome/browser/prefs/tracked/pref_hash_browsertest.cc b/chrome/browser/prefs/tracked/pref_hash_browsertest.cc
|
| index 7703e89b68c07dd46165d956894f66885c52b3b6..9177b8230e2390e3d8e88e419d01d71b4ca50a70 100644
|
| --- a/chrome/browser/prefs/tracked/pref_hash_browsertest.cc
|
| +++ b/chrome/browser/prefs/tracked/pref_hash_browsertest.cc
|
| @@ -38,11 +38,19 @@
|
| #include "chromeos/chromeos_switches.h"
|
| #endif
|
|
|
| +#if defined(OS_WIN)
|
| +#include "base/test/test_reg_util_win.h"
|
| +#endif
|
| +
|
| namespace {
|
|
|
| // Extension ID of chrome/test/data/extensions/good.crx
|
| const char kGoodCrxId[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
|
|
|
| +// Prefix for the registry path.
|
| +constexpr base::char16 kRegistryTestPathPrefix[] =
|
| + L"SOFTWARE\\Chromium\\PrefHashBrowserTest\\";
|
| +
|
| // Explicit expectations from the caller of GetTrackedPrefHistogramCount(). This
|
| // enables detailed reporting of the culprit on failure.
|
| enum AllowedBuckets {
|
| @@ -56,14 +64,24 @@ enum AllowedBuckets {
|
| ALLOW_ANY
|
| };
|
|
|
| +base::string16 GetRegistryPathForTestProfile() {
|
| + base::FilePath profile_dir;
|
| + EXPECT_TRUE(PathService::Get(chrome::DIR_USER_DATA, &profile_dir));
|
| + return kRegistryTestPathPrefix + profile_dir.BaseName().value();
|
| +}
|
| +
|
| // Returns the number of times |histogram_name| was reported so far; adding the
|
| // results of the first 100 buckets (there are only ~19 reporting IDs as of this
|
| // writing; varies depending on the platform). |allowed_buckets| hints at extra
|
| // requirements verified in this method (see AllowedBuckets for details).
|
| int GetTrackedPrefHistogramCount(const char* histogram_name,
|
| + const char* histogram_suffix,
|
| int allowed_buckets) {
|
| + std::string full_histogram_name(histogram_name);
|
| + if (*histogram_suffix != 0)
|
| + full_histogram_name.append(".").append(histogram_suffix);
|
| const base::HistogramBase* histogram =
|
| - base::StatisticsRecorder::FindHistogram(histogram_name);
|
| + base::StatisticsRecorder::FindHistogram(full_histogram_name);
|
| if (!histogram)
|
| return 0;
|
|
|
| @@ -82,6 +100,13 @@ int GetTrackedPrefHistogramCount(const char* histogram_name,
|
| return sum;
|
| }
|
|
|
| +// Helper function to call GetTrackedPrefHistogramCount with no external
|
| +// validation suffix.
|
| +int GetTrackedPrefHistogramCount(const char* histogram_name,
|
| + int allowed_buckets) {
|
| + return GetTrackedPrefHistogramCount(histogram_name, "", allowed_buckets);
|
| +}
|
| +
|
| std::unique_ptr<base::DictionaryValue> ReadPrefsDictionary(
|
| const base::FilePath& pref_file) {
|
| JSONFileValueDeserializer deserializer(pref_file);
|
| @@ -101,6 +126,16 @@ std::unique_ptr<base::DictionaryValue> ReadPrefsDictionary(
|
| static_cast<base::DictionaryValue*>(prefs.release()));
|
| }
|
|
|
| +// Returns whether external validation is supported on the platform through
|
| +// storing MACs in the registry.
|
| +bool SupportsRegistryValidation() {
|
| +#if defined(OS_WIN)
|
| + return true;
|
| +#else
|
| + return false;
|
| +#endif
|
| +}
|
| +
|
| #define PREF_HASH_BROWSER_TEST(fixture, test_name) \
|
| IN_PROC_BROWSER_TEST_P(fixture, PRE_##test_name) { \
|
| SetupPreferences(); \
|
| @@ -233,6 +268,43 @@ class PrefHashBrowserTestBase
|
| // Bots are on a domain, turn off the domain check for settings hardening in
|
| // order to be able to test all SettingsEnforcement groups.
|
| chrome_prefs::DisableDomainCheckForTesting();
|
| +
|
| +#if defined(OS_WIN)
|
| + // Avoid polluting prefs for the user and the bots by writing to a specific
|
| + // testing registry path.
|
| + base::string16 registry_key = GetRegistryPathForTestProfile();
|
| + ProfilePrefStoreManager::SetPreferenceValidationRegistryPathForTesting(
|
| + registry_key);
|
| +
|
| + // For PRE tests, delete the Registry key to avoid collisions.
|
| + if (IsPRETest()) {
|
| + base::win::RegKey key;
|
| + if (key.Open(HKEY_CURRENT_USER, registry_key.c_str(),
|
| + KEY_SET_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) {
|
| + LONG result = key.DeleteKey(L"");
|
| + ASSERT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
|
| + }
|
| + }
|
| +#endif
|
| + }
|
| +
|
| + void TearDown() override {
|
| +#if defined(OS_WIN)
|
| + // For non-PRE tests, delete the Registry key to avoid polluting the
|
| + // registry.
|
| + // TODO(proberge): it would be nice to delete keys from interrupted tests
|
| + // as well.
|
| + if (!IsPRETest()) {
|
| + base::string16 registry_key = GetRegistryPathForTestProfile();
|
| + base::win::RegKey key;
|
| + if (key.Open(HKEY_CURRENT_USER, registry_key.c_str(),
|
| + KEY_SET_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) {
|
| + LONG result = key.DeleteKey(L"");
|
| + ASSERT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
|
| + }
|
| + }
|
| +#endif
|
| + ExtensionBrowserTest::TearDown();
|
| }
|
|
|
| // In the PRE_ test, find the number of tracked preferences that were
|
| @@ -266,6 +338,23 @@ class PrefHashBrowserTestBase
|
| EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0,
|
| num_split_tracked_prefs);
|
|
|
| + if (SupportsRegistryValidation()) {
|
| + // Same checks as above, but for the registry.
|
| + num_tracked_prefs_ = GetTrackedPrefHistogramCount(
|
| + user_prefs::tracked::kTrackedPrefHistogramNullInitialized,
|
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
|
| + ALLOW_ANY);
|
| + EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM,
|
| + num_tracked_prefs_ > 0);
|
| +
|
| + int num_split_tracked_prefs = GetTrackedPrefHistogramCount(
|
| + user_prefs::tracked::kTrackedPrefHistogramUnchanged,
|
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
|
| + BEGIN_ALLOW_SINGLE_BUCKET + 5);
|
| + EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0,
|
| + num_split_tracked_prefs);
|
| + }
|
| +
|
| num_tracked_prefs_ += num_split_tracked_prefs;
|
|
|
| std::string num_tracked_prefs_str = base::IntToString(num_tracked_prefs_);
|
| @@ -407,6 +496,17 @@ class PrefHashBrowserTestUnchangedDefault : public PrefHashBrowserTestBase {
|
| 0, GetTrackedPrefHistogramCount(
|
| user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId,
|
| ALLOW_NONE));
|
| +
|
| + if (SupportsRegistryValidation()) {
|
| + // Expect all prefs to be reported as Unchanged with no resets.
|
| + EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
|
| + ? num_tracked_prefs()
|
| + : 0,
|
| + GetTrackedPrefHistogramCount(
|
| + user_prefs::tracked::kTrackedPrefHistogramUnchanged,
|
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
|
| + ALLOW_ANY));
|
| + }
|
| }
|
| };
|
|
|
| @@ -497,6 +597,15 @@ class PrefHashBrowserTestClearedAtomic : public PrefHashBrowserTestBase {
|
| 0, GetTrackedPrefHistogramCount(
|
| user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId,
|
| ALLOW_NONE));
|
| +
|
| + if (SupportsRegistryValidation()) {
|
| + // Expect homepage to have been cleared.
|
| + EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0,
|
| + GetTrackedPrefHistogramCount(
|
| + user_prefs::tracked::kTrackedPrefHistogramCleared,
|
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
|
| + BEGIN_ALLOW_SINGLE_BUCKET + 2));
|
| + }
|
| }
|
| };
|
|
|
| @@ -619,6 +728,18 @@ class PrefHashBrowserTestUntrustedInitialized : public PrefHashBrowserTestBase {
|
| 0, GetTrackedPrefHistogramCount(
|
| user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId,
|
| ALLOW_NONE));
|
| +
|
| + if (SupportsRegistryValidation()) {
|
| + // The MACs have been cleared but the preferences have not been tampered.
|
| + // The registry should report all prefs as unchanged.
|
| + EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
|
| + ? num_tracked_prefs()
|
| + : 0,
|
| + GetTrackedPrefHistogramCount(
|
| + user_prefs::tracked::kTrackedPrefHistogramUnchanged,
|
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
|
| + ALLOW_ANY));
|
| + }
|
| }
|
| };
|
|
|
| @@ -709,6 +830,15 @@ class PrefHashBrowserTestChangedAtomic : public PrefHashBrowserTestBase {
|
| 0, GetTrackedPrefHistogramCount(
|
| user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId,
|
| ALLOW_NONE));
|
| +
|
| + if (SupportsRegistryValidation()) {
|
| + // Expect a single Changed event for tracked pref #4 (startup URLs).
|
| + EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0,
|
| + GetTrackedPrefHistogramCount(
|
| + user_prefs::tracked::kTrackedPrefHistogramChanged,
|
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
|
| + BEGIN_ALLOW_SINGLE_BUCKET + 4));
|
| + }
|
| }
|
| };
|
|
|
| @@ -806,6 +936,16 @@ class PrefHashBrowserTestChangedSplitPref : public PrefHashBrowserTestBase {
|
| 0, GetTrackedPrefHistogramCount(
|
| user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId,
|
| ALLOW_NONE));
|
| +
|
| + if (SupportsRegistryValidation()) {
|
| + // Expect a single split pref changed report with a count of 2 for tracked
|
| + // pref #5 (extensions).
|
| + EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0,
|
| + GetTrackedPrefHistogramCount(
|
| + user_prefs::tracked::kTrackedPrefHistogramChanged,
|
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
|
| + BEGIN_ALLOW_SINGLE_BUCKET + 5));
|
| + }
|
| }
|
| };
|
|
|
| @@ -879,6 +1019,17 @@ class PrefHashBrowserTestUntrustedAdditionToPrefs
|
| 0, GetTrackedPrefHistogramCount(
|
| user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId,
|
| ALLOW_NONE));
|
| +
|
| + if (SupportsRegistryValidation()) {
|
| + EXPECT_EQ((protection_level_ > PROTECTION_DISABLED_ON_PLATFORM &&
|
| + protection_level_ < PROTECTION_ENABLED_BASIC)
|
| + ? changed_expected
|
| + : 0,
|
| + GetTrackedPrefHistogramCount(
|
| + user_prefs::tracked::kTrackedPrefHistogramChanged,
|
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
|
| + BEGIN_ALLOW_SINGLE_BUCKET + 3));
|
| + }
|
| }
|
| };
|
|
|
| @@ -953,8 +1104,64 @@ class PrefHashBrowserTestUntrustedAdditionToPrefsAfterWipe
|
| 0, GetTrackedPrefHistogramCount(
|
| user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId,
|
| ALLOW_NONE));
|
| +
|
| + if (SupportsRegistryValidation()) {
|
| + EXPECT_EQ(changed_expected,
|
| + GetTrackedPrefHistogramCount(
|
| + user_prefs::tracked::kTrackedPrefHistogramChanged,
|
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
|
| + BEGIN_ALLOW_SINGLE_BUCKET + 2));
|
| + EXPECT_EQ(cleared_expected,
|
| + GetTrackedPrefHistogramCount(
|
| + user_prefs::tracked::kTrackedPrefHistogramCleared,
|
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
|
| + BEGIN_ALLOW_SINGLE_BUCKET + 2));
|
| + }
|
| }
|
| };
|
|
|
| PREF_HASH_BROWSER_TEST(PrefHashBrowserTestUntrustedAdditionToPrefsAfterWipe,
|
| UntrustedAdditionToPrefsAfterWipe);
|
| +
|
| +#if defined(OS_WIN)
|
| +class PrefHashBrowserTestRegistryValidationFailure
|
| + : public PrefHashBrowserTestBase {
|
| + public:
|
| + void SetupPreferences() override {
|
| + profile()->GetPrefs()->SetString(prefs::kHomePage, "http://example.com");
|
| + }
|
| +
|
| + void AttackPreferencesOnDisk(
|
| + base::DictionaryValue* unprotected_preferences,
|
| + base::DictionaryValue* protected_preferences) override {
|
| + base::string16 registry_key =
|
| + GetRegistryPathForTestProfile() + L"\\PreferenceMACs\\Default";
|
| + base::win::RegKey key;
|
| + ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, registry_key.c_str(),
|
| + KEY_SET_VALUE | KEY_WOW64_32KEY));
|
| + // An incorrect hash should still have the correct size.
|
| + ASSERT_EQ(ERROR_SUCCESS,
|
| + key.WriteValue(L"homepage", base::string16(64, 'A').c_str()));
|
| + }
|
| +
|
| + void VerifyReactionToPrefAttack() override {
|
| + EXPECT_EQ(
|
| + protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
|
| + ? num_tracked_prefs()
|
| + : 0,
|
| + GetTrackedPrefHistogramCount(
|
| + user_prefs::tracked::kTrackedPrefHistogramUnchanged, ALLOW_ANY));
|
| +
|
| + if (SupportsRegistryValidation()) {
|
| + EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0,
|
| + GetTrackedPrefHistogramCount(
|
| + user_prefs::tracked::kTrackedPrefHistogramChanged,
|
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
|
| + BEGIN_ALLOW_SINGLE_BUCKET + 2));
|
| + }
|
| + }
|
| +};
|
| +
|
| +PREF_HASH_BROWSER_TEST(PrefHashBrowserTestRegistryValidationFailure,
|
| + RegistryValidationFailure);
|
| +#endif
|
|
|