зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1705360 - "hide" NSS DBs from meddling third party software r=jschanck,bbeurdouche
Some crash reports appear to be indicating that initializing NSS' certificate and key databases is taking on the order of minutes in some cases, which is unexpected. One hypothesis is that third-party software is opening these DBs at the same time that NSS is operating on them, causing contention and thus slowness. This patch experimentally (in Nightly only) renames these DBs in the hopes that third-party software might not recognize them as the DBs it's looking for, and will thus leave them alone. Differential Revision: https://phabricator.services.mozilla.com/D126028
This commit is contained in:
Родитель
33e8e81aa8
Коммит
9aa0ad981f
|
@ -33,6 +33,8 @@ const LINUX = AppConstants.platform == "linux";
|
|||
const WIN = AppConstants.platform == "win";
|
||||
const MAC = AppConstants.platform == "macosx";
|
||||
|
||||
const kNSSDBPrefix = AppConstants.NIGHTLY_BUILD ? "gecko-no-share-" : "";
|
||||
|
||||
const kSharedFontList = SpecialPowers.getBoolPref("gfx.e10s.font-list.shared");
|
||||
|
||||
/* This is an object mapping string phases of startup to lists of known cases
|
||||
|
@ -357,14 +359,20 @@ const startupPhases = {
|
|||
},
|
||||
{
|
||||
// bug 1370516 - NSS should be initialized off main thread.
|
||||
path: "ProfD:cert9.db",
|
||||
condition: WIN,
|
||||
read: 5,
|
||||
stat: 4,
|
||||
path: `ProfD:cert9.db`,
|
||||
condition: WIN && AppConstants.NIGHTLY_BUILD,
|
||||
stat: 1,
|
||||
},
|
||||
{
|
||||
// bug 1370516 - NSS should be initialized off main thread.
|
||||
path: "ProfD:cert9.db",
|
||||
path: `ProfD:${kNSSDBPrefix}cert9.db`,
|
||||
condition: WIN,
|
||||
read: 5,
|
||||
stat: AppConstants.NIGHTLY_BUILD ? 5 : 4,
|
||||
},
|
||||
{
|
||||
// bug 1370516 - NSS should be initialized off main thread.
|
||||
path: `ProfD:${kNSSDBPrefix}cert9.db`,
|
||||
condition: WIN,
|
||||
ignoreIfUnused: true, // if canonicalize(ProfD) == ProfD, we'll use the previous entry.
|
||||
canonicalize: true,
|
||||
|
@ -372,14 +380,14 @@ const startupPhases = {
|
|||
},
|
||||
{
|
||||
// bug 1370516 - NSS should be initialized off main thread.
|
||||
path: "ProfD:cert9.db-journal",
|
||||
path: `ProfD:${kNSSDBPrefix}cert9.db-journal`,
|
||||
condition: WIN,
|
||||
canonicalize: true,
|
||||
stat: 3,
|
||||
},
|
||||
{
|
||||
// bug 1370516 - NSS should be initialized off main thread.
|
||||
path: "ProfD:cert9.db-wal",
|
||||
path: `ProfD:${kNSSDBPrefix}cert9.db-wal`,
|
||||
condition: WIN,
|
||||
canonicalize: true,
|
||||
stat: 3,
|
||||
|
@ -392,14 +400,20 @@ const startupPhases = {
|
|||
},
|
||||
{
|
||||
// bug 1370516 - NSS should be initialized off main thread.
|
||||
path: "ProfD:key4.db",
|
||||
condition: WIN,
|
||||
read: 8,
|
||||
stat: 4,
|
||||
path: `ProfD:key4.db`,
|
||||
condition: WIN && AppConstants.NIGHTLY_BUILD,
|
||||
stat: 1,
|
||||
},
|
||||
{
|
||||
// bug 1370516 - NSS should be initialized off main thread.
|
||||
path: "ProfD:key4.db",
|
||||
path: `ProfD:${kNSSDBPrefix}key4.db`,
|
||||
condition: WIN,
|
||||
read: 8,
|
||||
stat: AppConstants.NIGHTLY_BUILD ? 5 : 4,
|
||||
},
|
||||
{
|
||||
// bug 1370516 - NSS should be initialized off main thread.
|
||||
path: `ProfD:${kNSSDBPrefix}key4.db`,
|
||||
condition: WIN,
|
||||
ignoreIfUnused: true, // if canonicalize(ProfD) == ProfD, we'll use the previous entry.
|
||||
canonicalize: true,
|
||||
|
@ -407,14 +421,14 @@ const startupPhases = {
|
|||
},
|
||||
{
|
||||
// bug 1370516 - NSS should be initialized off main thread.
|
||||
path: "ProfD:key4.db-journal",
|
||||
path: `ProfD:${kNSSDBPrefix}key4.db-journal`,
|
||||
condition: WIN,
|
||||
canonicalize: true,
|
||||
stat: 5,
|
||||
},
|
||||
{
|
||||
// bug 1370516 - NSS should be initialized off main thread.
|
||||
path: "ProfD:key4.db-wal",
|
||||
path: `ProfD:${kNSSDBPrefix}key4.db-wal`,
|
||||
condition: WIN,
|
||||
canonicalize: true,
|
||||
stat: 5,
|
||||
|
@ -527,13 +541,13 @@ const startupPhases = {
|
|||
write: 1300,
|
||||
},
|
||||
{
|
||||
path: "ProfD:key4.db-journal",
|
||||
path: `ProfD:${kNSSDBPrefix}key4.db-journal`,
|
||||
condition: WIN,
|
||||
canonicalize: true,
|
||||
stat: 2,
|
||||
},
|
||||
{
|
||||
path: "ProfD:key4.db-wal",
|
||||
path: `ProfD:${kNSSDBPrefix}key4.db-wal`,
|
||||
condition: WIN,
|
||||
canonicalize: true,
|
||||
stat: 2,
|
||||
|
|
|
@ -171,6 +171,7 @@ FirefoxProfileMigrator.prototype._getResourcesInternal = function(
|
|||
"logins.json",
|
||||
"key3.db",
|
||||
"key4.db",
|
||||
"gecko-no-share-key4.db",
|
||||
]);
|
||||
let formData = getFileResource(types.FORMDATA, [
|
||||
"formhistory.sqlite",
|
||||
|
|
|
@ -1548,7 +1548,8 @@ void NSSCertDBTrustDomain::NoteAuxiliaryExtension(AuxiliaryExtension extension,
|
|||
}
|
||||
|
||||
SECStatus InitializeNSS(const nsACString& dir, NSSDBConfig nssDbConfig,
|
||||
PKCS11DBConfig pkcs11DbConfig) {
|
||||
PKCS11DBConfig pkcs11DbConfig,
|
||||
const char* nssDBPrefix) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// The NSS_INIT_NOROOTINIT flag turns off the loading of the root certs
|
||||
|
@ -1568,8 +1569,8 @@ SECStatus InitializeNSS(const nsACString& dir, NSSDBConfig nssDbConfig,
|
|||
MOZ_LOG(gCertVerifierLog, LogLevel::Debug,
|
||||
("InitializeNSS(%s, %d, %d)", dbTypeAndDirectory.get(),
|
||||
(int)nssDbConfig, (int)pkcs11DbConfig));
|
||||
SECStatus srv =
|
||||
NSS_Initialize(dbTypeAndDirectory.get(), "", "", SECMOD_DB, flags);
|
||||
SECStatus srv = NSS_Initialize(dbTypeAndDirectory.get(), nssDBPrefix,
|
||||
nssDBPrefix, SECMOD_DB, flags);
|
||||
if (srv != SECSuccess) {
|
||||
return srv;
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ enum class NetscapeStepUpPolicy : uint32_t {
|
|||
};
|
||||
|
||||
SECStatus InitializeNSS(const nsACString& dir, NSSDBConfig nssDbConfig,
|
||||
PKCS11DBConfig pkcs11DbConfig);
|
||||
PKCS11DBConfig pkcs11DbConfig, const char* nssDBPrefix);
|
||||
|
||||
void DisableMD5();
|
||||
|
||||
|
|
|
@ -1757,7 +1757,8 @@ static nsresult AttemptToRenamePKCS11ModuleDB(const nsACString& profilePath) {
|
|||
// there anyway.
|
||||
// |profilePath| is encoded in UTF-8.
|
||||
static nsresult InitializeNSSWithFallbacks(const nsACString& profilePath,
|
||||
bool nocertdb, bool safeMode) {
|
||||
bool nocertdb, bool safeMode,
|
||||
const char* nssDBPrefix) {
|
||||
if (nocertdb || profilePath.IsEmpty()) {
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
|
||||
("nocertdb mode or empty profile path -> NSS_NoDB_Init"));
|
||||
|
@ -1778,7 +1779,7 @@ static nsresult InitializeNSSWithFallbacks(const nsACString& profilePath,
|
|||
PKCS11DBConfig safeModeDBConfig =
|
||||
safeMode ? PKCS11DBConfig::DoNotLoadModules : PKCS11DBConfig::LoadModules;
|
||||
SECStatus srv = ::mozilla::psm::InitializeNSS(
|
||||
profilePath, NSSDBConfig::ReadWrite, safeModeDBConfig);
|
||||
profilePath, NSSDBConfig::ReadWrite, safeModeDBConfig, nssDBPrefix);
|
||||
if (srv == SECSuccess) {
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("initialized NSS in r/w mode"));
|
||||
return NS_OK;
|
||||
|
@ -1789,7 +1790,7 @@ static nsresult InitializeNSSWithFallbacks(const nsACString& profilePath,
|
|||
#endif // ifndef ANDROID
|
||||
// That failed. Try read-only mode.
|
||||
srv = ::mozilla::psm::InitializeNSS(profilePath, NSSDBConfig::ReadOnly,
|
||||
safeModeDBConfig);
|
||||
safeModeDBConfig, nssDBPrefix);
|
||||
if (srv == SECSuccess) {
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("initialized NSS in r-o mode"));
|
||||
return NS_OK;
|
||||
|
@ -1817,7 +1818,8 @@ static nsresult InitializeNSSWithFallbacks(const nsACString& profilePath,
|
|||
// flags causes NSS initialization to fail, so unfortunately we have to use
|
||||
// read-write mode.
|
||||
srv = ::mozilla::psm::InitializeNSS(profilePath, NSSDBConfig::ReadWrite,
|
||||
PKCS11DBConfig::DoNotLoadModules);
|
||||
PKCS11DBConfig::DoNotLoadModules,
|
||||
nssDBPrefix);
|
||||
if (srv == SECSuccess) {
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("FIPS may be the problem"));
|
||||
// Unload NSS so we can attempt to fix this situation for the user.
|
||||
|
@ -1844,13 +1846,15 @@ static nsresult InitializeNSSWithFallbacks(const nsACString& profilePath,
|
|||
return rv;
|
||||
}
|
||||
srv = ::mozilla::psm::InitializeNSS(profilePath, NSSDBConfig::ReadWrite,
|
||||
PKCS11DBConfig::LoadModules);
|
||||
PKCS11DBConfig::LoadModules,
|
||||
nssDBPrefix);
|
||||
if (srv == SECSuccess) {
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("initialized in r/w mode"));
|
||||
return NS_OK;
|
||||
}
|
||||
srv = ::mozilla::psm::InitializeNSS(profilePath, NSSDBConfig::ReadOnly,
|
||||
PKCS11DBConfig::LoadModules);
|
||||
PKCS11DBConfig::LoadModules,
|
||||
nssDBPrefix);
|
||||
if (srv == SECSuccess) {
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("initialized in r-o mode"));
|
||||
return NS_OK;
|
||||
|
@ -1870,6 +1874,60 @@ static nsresult InitializeNSSWithFallbacks(const nsACString& profilePath,
|
|||
return srv == SECSuccess ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
#ifdef NIGHTLY_BUILD
|
||||
const char* sGeckoNSSDBPrefix = "gecko-no-share-";
|
||||
#else
|
||||
const char* sGeckoNSSDBPrefix = "";
|
||||
#endif
|
||||
|
||||
#ifdef NIGHTLY_BUILD
|
||||
// dbType is either "cert9.db" or "key4.db"
|
||||
void MigrateOneCertDB(const nsCOMPtr<nsIFile>& profileDirectory,
|
||||
const nsACString& dbType) {
|
||||
nsCOMPtr<nsIFile> newDBFile;
|
||||
nsresult rv = profileDirectory->Clone(getter_AddRefs(newDBFile));
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
nsAutoCString newDBFilename(sGeckoNSSDBPrefix);
|
||||
newDBFilename.Append(dbType);
|
||||
rv = newDBFile->AppendNative(newDBFilename);
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
bool exists;
|
||||
rv = newDBFile->Exists(&exists);
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
// If the prefixed DB already exists, don't overwrite it.
|
||||
if (exists) {
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIFile> oldDBFile;
|
||||
rv = profileDirectory->Clone(getter_AddRefs(oldDBFile));
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
rv = oldDBFile->AppendNative(dbType);
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
Unused << oldDBFile->MoveToNative(nullptr, newDBFilename);
|
||||
}
|
||||
|
||||
void MigrateToPrefixedCertDBs() {
|
||||
nsCOMPtr<nsIFile> profileDirectory;
|
||||
nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
|
||||
getter_AddRefs(profileDirectory));
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
MigrateOneCertDB(profileDirectory, "cert9.db"_ns);
|
||||
MigrateOneCertDB(profileDirectory, "key4.db"_ns);
|
||||
}
|
||||
#endif // NIGHTLY_BUILD
|
||||
|
||||
nsresult nsNSSComponent::InitializeNSS() {
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nsNSSComponent::InitializeNSS\n"));
|
||||
AUTO_PROFILER_LABEL("nsNSSComponent::InitializeNSS", OTHER);
|
||||
|
@ -1891,6 +1949,12 @@ nsresult nsNSSComponent::InitializeNSS() {
|
|||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
#ifdef NIGHTLY_BUILD
|
||||
if (!profileStr.IsEmpty()) {
|
||||
MigrateToPrefixedCertDBs();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(XP_WIN) || (defined(XP_LINUX) && !defined(ANDROID))
|
||||
SetNSSDatabaseCacheModeAsAppropriate();
|
||||
#endif
|
||||
|
@ -1910,7 +1974,8 @@ nsresult nsNSSComponent::InitializeNSS() {
|
|||
}
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("inSafeMode: %u\n", inSafeMode));
|
||||
|
||||
rv = InitializeNSSWithFallbacks(profileStr, nocertdb, inSafeMode);
|
||||
rv = InitializeNSSWithFallbacks(profileStr, nocertdb, inSafeMode,
|
||||
sGeckoNSSDBPrefix);
|
||||
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("failed to initialize NSS"));
|
||||
|
|
|
@ -10,13 +10,25 @@
|
|||
function run_test() {
|
||||
let profileDir = do_get_profile();
|
||||
let certificateDBFile = profileDir.clone();
|
||||
certificateDBFile.append("cert9.db");
|
||||
ok(!certificateDBFile.exists(), "cert9.db should not exist beforehand");
|
||||
let certificateDBName = AppConstants.NIGHTLY_BUILD
|
||||
? "gecko-no-share-cert9.db"
|
||||
: "cert9.db";
|
||||
certificateDBFile.append(certificateDBName);
|
||||
ok(
|
||||
!certificateDBFile.exists(),
|
||||
`${certificateDBName} should not exist beforehand`
|
||||
);
|
||||
let keyDBFile = profileDir.clone();
|
||||
keyDBFile.append("key4.db");
|
||||
ok(!keyDBFile.exists(), "key4.db should not exist beforehand");
|
||||
let keyDBName = AppConstants.NIGHTLY_BUILD
|
||||
? "gecko-no-share-key4.db"
|
||||
: "key4.db";
|
||||
keyDBFile.append(keyDBName);
|
||||
ok(!keyDBFile.exists(), `${keyDBName} should not exist beforehand`);
|
||||
// This should start PSM.
|
||||
Cc["@mozilla.org/psm;1"].getService(Ci.nsISupports);
|
||||
ok(certificateDBFile.exists(), "cert9.db should exist in the profile");
|
||||
ok(keyDBFile.exists(), "key4.db should exist in the profile");
|
||||
ok(
|
||||
certificateDBFile.exists(),
|
||||
`${certificateDBName} should exist in the profile`
|
||||
);
|
||||
ok(keyDBFile.exists(), `${keyDBName} should exist in the profile`);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче