| 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 6e73c5138ace73ce56853fbd8d6b9f1ce825553f..2895349879e125689b2473c231084f75efe1abcf 100644
|
| --- a/chrome/browser/prefs/tracked/pref_hash_browsertest.cc
|
| +++ b/chrome/browser/prefs/tracked/pref_hash_browsertest.cc
|
| @@ -40,11 +40,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 {
|
| @@ -58,14 +66,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;
|
|
|
| @@ -84,6 +102,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);
|
| @@ -103,6 +128,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(); \
|
| @@ -235,6 +270,42 @@ 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();
|
| +
|
| + // Avoid polluting prefs for the user and the bots by writing to a specific
|
| + // testing registry path.
|
| + base::string16 registry_key = GetRegistryPathForTestProfile();
|
| + chrome_prefs::SetPreferenceValidationRegistryPathForTesting(registry_key);
|
| +
|
| +#if defined(OS_WIN)
|
| + // 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.
|
| + base::string16 registry_key = GetRegistryPathForTestProfile();
|
| + 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
|
| + ExtensionBrowserTest::TearDown();
|
| }
|
|
|
| // In the PRE_ test, find the number of tracked preferences that were
|
| @@ -268,6 +339,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_);
|
| @@ -409,6 +497,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));
|
| + }
|
| }
|
| };
|
|
|
| @@ -499,6 +598,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));
|
| + }
|
| }
|
| };
|
|
|
| @@ -621,6 +729,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));
|
| + }
|
| }
|
| };
|
|
|
| @@ -711,6 +831,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));
|
| + }
|
| }
|
| };
|
|
|
| @@ -808,6 +937,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));
|
| + }
|
| }
|
| };
|
|
|
| @@ -881,6 +1020,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));
|
| + }
|
| }
|
| };
|
|
|
| @@ -955,8 +1105,71 @@ 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);
|
| +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 {
|
| + // See TearDown
|
| + }
|
| +
|
| + void TearDown() override {
|
| +// Modifying prefs in the registry while in AttackPreferencesOnDisk does not
|
| +// seem to work (despite returning ERROR_SUCCESS). Do it earlier, during the
|
| +// PRE test TearDown instead.
|
| +#if defined(OS_WIN)
|
| + 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()));
|
| +#endif
|
| + PrefHashBrowserTestBase::TearDown();
|
| + }
|
| +
|
| + 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);
|
|
|