bug 1372656 - load loadable roots on a background thread r=Cykesiopka,jcj

In a profile, loading the loadable roots PKCS#11 module (i.e. the built-in root
CA module) accounted for about 60% of the time to initialize PSM/NSS. Since we
only need the roots module loaded when we're actually looking for an issuing
certificate or querying a certificate's trust, we can do the load
asynchronously (where it hopefully finishes before we actually need it, because
otherwise we'll have to wait anyway).

MozReview-Commit-ID: JyY6NtpQAUj

--HG--
extra : rebase_source : f63a697b18a409dd042289afa2b727b09f81f19f
This commit is contained in:
David Keeler 2017-06-08 16:10:00 -07:00
Родитель 8b8a999a38
Коммит 8b85837b61
13 изменённых файлов: 336 добавлений и 93 удалений

Просмотреть файл

@ -137,6 +137,10 @@ IsCertChainRootBuiltInRoot(const UniqueCERTCertList& chain, bool& result)
Result
IsCertBuiltInRoot(CERTCertificate* cert, bool& result)
{
if (NS_FAILED(BlockUntilLoadableRootsLoaded())) {
return Result::FATAL_ERROR_LIBRARY_FAILURE;
}
result = false;
#ifdef DEBUG
nsCOMPtr<nsINSSComponent> component(do_GetService(PSM_COMPONENT_CONTRACTID));
@ -464,6 +468,10 @@ CertVerifier::VerifyCert(CERTCertificate* cert, SECCertificateUsage usage,
MOZ_ASSERT(usage == certificateUsageSSLServer || !keySizeStatus);
MOZ_ASSERT(usage == certificateUsageSSLServer || !sha1ModeResult);
if (NS_FAILED(BlockUntilLoadableRootsLoaded())) {
return Result::FATAL_ERROR_LIBRARY_FAILURE;
}
if (evOidPolicy) {
*evOidPolicy = SEC_OID_UNKNOWN;
}

Просмотреть файл

@ -1176,7 +1176,7 @@ CertIsAuthoritativeForEVPolicy(const UniqueCERTCertificate& cert,
}
nsresult
LoadExtendedValidationInfo()
LoadExtendedValidationInfo(const nsNSSShutDownPreventionLock& /*proofOfLock*/)
{
static const char* sCABForumOIDString = "2.23.140.1.1";
static const char* sCABForumOIDDescription = "CA/Browser Forum EV OID";

Просмотреть файл

@ -8,12 +8,15 @@
#include "ScopedNSSTypes.h"
#include "certt.h"
#include "nsNSSShutDown.h"
namespace mozilla { namespace pkix { struct CertPolicyId; } }
namespace mozilla { namespace psm {
nsresult LoadExtendedValidationInfo();
nsresult LoadExtendedValidationInfo(
const nsNSSShutDownPreventionLock& proofOfLock);
/**
* Finds the first policy OID in the given cert that is known to be an EV policy
* OID.

Просмотреть файл

@ -21,6 +21,7 @@
#include "mozilla/PodOperations.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/Unused.h"
#include "nsCRTGlue.h"
#include "nsNSSCertificate.h"
#include "nsServiceManagerUtils.h"
#include "nss.h"
@ -1260,32 +1261,27 @@ DisableMD5()
bool
LoadLoadableRoots(const nsCString& dir, const nsCString& modNameUTF8)
{
UniquePRLibraryName fullLibraryPath(
PR_GetLibraryName(dir.IsEmpty() ? nullptr : dir.get(), "nssckbi"));
if (!fullLibraryPath) {
return false;
}
// Escape the \ and " characters.
nsAutoCString escapedFullLibraryPath(fullLibraryPath.get());
escapedFullLibraryPath.ReplaceSubstring("\\", "\\\\");
escapedFullLibraryPath.ReplaceSubstring("\"", "\\\"");
if (escapedFullLibraryPath.IsEmpty()) {
return false;
}
// If a module exists with the same name, make a best effort attempt to delete
// it. Note that it isn't possible to delete the internal module, so checking
// the return value would be detrimental in that case.
int unusedModType;
Unused << SECMOD_DeleteModule(modNameUTF8.get(), &unusedModType);
nsAutoCString pkcs11ModuleSpec;
pkcs11ModuleSpec.AppendPrintf("name=\"%s\" library=\"%s\"", modNameUTF8.get(),
escapedFullLibraryPath.get());
if (pkcs11ModuleSpec.IsEmpty()) {
return false;
nsAutoCString fullLibraryPath;
if (!dir.IsEmpty()) {
fullLibraryPath.Assign(dir);
fullLibraryPath.AppendLiteral(FILE_PATH_SEPARATOR);
}
fullLibraryPath.Append(DLL_PREFIX "nssckbi" DLL_SUFFIX);
// Escape the \ and " characters.
fullLibraryPath.ReplaceSubstring("\\", "\\\\");
fullLibraryPath.ReplaceSubstring("\"", "\\\"");
nsAutoCString pkcs11ModuleSpec("name=\"");
pkcs11ModuleSpec.Append(modNameUTF8);
pkcs11ModuleSpec.AppendLiteral("\" library=\"");
pkcs11ModuleSpec.Append(fullLibraryPath);
pkcs11ModuleSpec.AppendLiteral("\"");
UniqueSECMODModule rootsModule(
SECMOD_LoadUserModule(const_cast<char*>(pkcs11ModuleSpec.get()), nullptr,

Просмотреть файл

@ -40,6 +40,9 @@ if not CONFIG['NSS_NO_EV_CERTS']:
'ExtendedValidation.cpp',
]
for var in ('DLL_PREFIX', 'DLL_SUFFIX'):
DEFINES[var] = '"%s"' % CONFIG[var]
LOCAL_INCLUDES += [
'/security/manager/ssl',
'/security/pkix/include',

Просмотреть файл

@ -26,6 +26,7 @@
#include "pkcs12.h"
#include "prerror.h"
#include "prio.h"
#include "prmem.h"
#include "sechash.h"
#include "secmod.h"
#include "secpkcs7.h"
@ -327,9 +328,9 @@ MOZ_TYPE_SPECIFIC_UNIQUE_PTR_TEMPLATE(UniquePORTString,
MOZ_TYPE_SPECIFIC_UNIQUE_PTR_TEMPLATE(UniquePRFileDesc,
PRFileDesc,
PR_Close)
MOZ_TYPE_SPECIFIC_UNIQUE_PTR_TEMPLATE(UniquePRLibraryName,
MOZ_TYPE_SPECIFIC_UNIQUE_PTR_TEMPLATE(UniquePRString,
char,
PR_FreeLibraryName)
PR_Free)
MOZ_TYPE_SPECIFIC_UNIQUE_PTR_TEMPLATE(UniqueSECAlgorithmID,
SECAlgorithmID,

Просмотреть файл

@ -896,6 +896,11 @@ nsNSSCertificate::ExportAsCMS(uint32_t chainMode,
if (isAlreadyShutDown())
return NS_ERROR_NOT_AVAILABLE;
nsresult rv = BlockUntilLoadableRootsLoaded();
if (NS_FAILED(rv)) {
return rv;
}
if (!mCert)
return NS_ERROR_FAILURE;

Просмотреть файл

@ -108,8 +108,13 @@ nsNSSCertificateDB::FindCertByDBKey(const nsACString& aDBKey,
return NS_ERROR_NOT_AVAILABLE;
}
nsresult rv = BlockUntilLoadableRootsLoaded();
if (NS_FAILED(rv)) {
return rv;
}
UniqueCERTCertificate cert;
nsresult rv = FindCertByDBKey(aDBKey, cert);
rv = FindCertByDBKey(aDBKey, cert);
if (NS_FAILED(rv)) {
return rv;
}
@ -892,6 +897,12 @@ nsNSSCertificateDB::IsCertTrusted(nsIX509Cert *cert,
if (isAlreadyShutDown()) {
return NS_ERROR_NOT_AVAILABLE;
}
nsresult rv = BlockUntilLoadableRootsLoaded();
if (NS_FAILED(rv)) {
return rv;
}
SECStatus srv;
UniqueCERTCertificate nsscert(cert->GetCert());
CERTCertTrust nsstrust;
@ -1002,6 +1013,10 @@ nsNSSCertificateDB::ImportPKCS12File(nsIFile* aFile)
if (isAlreadyShutDown()) {
return NS_ERROR_NOT_AVAILABLE;
}
nsresult rv = BlockUntilLoadableRootsLoaded();
if (NS_FAILED(rv)) {
return rv;
}
NS_ENSURE_ARG(aFile);
nsPKCS12Blob blob;
@ -1019,6 +1034,10 @@ nsNSSCertificateDB::ExportPKCS12File(nsIFile* aFile, uint32_t count,
if (isAlreadyShutDown()) {
return NS_ERROR_NOT_AVAILABLE;
}
nsresult rv = BlockUntilLoadableRootsLoaded();
if (NS_FAILED(rv)) {
return rv;
}
NS_ENSURE_ARG(aFile);
if (count == 0) {
@ -1037,6 +1056,11 @@ nsNSSCertificateDB::FindCertByEmailAddress(const nsACString& aEmailAddress,
return NS_ERROR_NOT_AVAILABLE;
}
nsresult rv = BlockUntilLoadableRootsLoaded();
if (NS_FAILED(rv)) {
return rv;
}
RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
NS_ENSURE_TRUE(certVerifier, NS_ERROR_UNEXPECTED);
@ -1157,6 +1181,10 @@ nsNSSCertificateDB::get_default_nickname(CERTCertificate *cert,
nsresult rv;
CK_OBJECT_HANDLE keyHandle;
if (NS_FAILED(BlockUntilLoadableRootsLoaded())) {
return;
}
CERTCertDBHandle *defaultcertdb = CERT_GetDefaultCertDB();
nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
if (NS_FAILED(rv))

Просмотреть файл

@ -199,7 +199,10 @@ GetRevocationBehaviorFromPrefs(/*out*/ CertVerifier::OcspDownloadConfig* odc,
}
nsNSSComponent::nsNSSComponent()
: mMutex("nsNSSComponent.mMutex")
: mLoadableRootsLoadedMonitor("nsNSSComponent.mLoadableRootsLoadedMonitor")
, mLoadableRootsLoaded(false)
, mLoadableRootsLoadedResult(NS_ERROR_FAILURE)
, mMutex("nsNSSComponent.mMutex")
, mNSSInitialized(false)
#ifndef MOZ_NO_SMART_CARDS
, mThreadList(nullptr)
@ -1049,15 +1052,173 @@ nsNSSComponent::ImportEnterpriseRootsForLocation(
}
#endif // XP_WIN
void
nsNSSComponent::LoadLoadableRoots()
class LoadLoadableRootsTask final : public Runnable
, public nsNSSShutDownObject
{
public:
explicit LoadLoadableRootsTask(nsNSSComponent* nssComponent)
: Runnable("LoadLoadableRootsTask")
, mNSSComponent(nssComponent)
{
MOZ_ASSERT(nssComponent);
}
~LoadLoadableRootsTask();
nsresult Dispatch();
void virtualDestroyNSSReference() override {} // nothing to release
private:
NS_IMETHOD Run() override;
nsresult LoadLoadableRoots(const nsNSSShutDownPreventionLock& proofOfLock);
RefPtr<nsNSSComponent> mNSSComponent;
nsCOMPtr<nsIThread> mThread;
};
LoadLoadableRootsTask::~LoadLoadableRootsTask()
{
nsNSSShutDownPreventionLock lock;
if (isAlreadyShutDown()) {
return;
}
shutdown(ShutdownCalledFrom::Object);
}
nsresult
LoadLoadableRootsTask::Dispatch()
{
// Can't add 'this' as the event to run, since mThread may not be set yet
nsresult rv = NS_NewNamedThread("LoadRoots", getter_AddRefs(mThread),
nullptr,
nsIThreadManager::DEFAULT_STACK_SIZE);
if (NS_FAILED(rv)) {
return rv;
}
// Note: event must not null out mThread!
return mThread->Dispatch(this, NS_DISPATCH_NORMAL);
}
NS_IMETHODIMP
LoadLoadableRootsTask::Run()
{
nsNSSShutDownPreventionLock lock;
if (isAlreadyShutDown()) {
return NS_ERROR_NOT_AVAILABLE;
}
nsresult rv = LoadLoadableRoots(lock);
if (NS_FAILED(rv)) {
MOZ_LOG(gPIPNSSLog, LogLevel::Error, ("LoadLoadableRoots failed"));
// We don't return rv here because then BlockUntilLoadableRootsLoaded will
// just wait forever. Instead we'll save its value (below) so we can inform
// code that relies on the roots module being present that loading it
// failed.
}
if (NS_SUCCEEDED(rv)) {
if (NS_FAILED(LoadExtendedValidationInfo(lock))) {
// This isn't a show-stopper in the same way that failing to load the
// roots module is.
MOZ_LOG(gPIPNSSLog, LogLevel::Error, ("failed to load EV info"));
}
}
{
MonitorAutoLock rootsLoadedLock(mNSSComponent->mLoadableRootsLoadedMonitor);
mNSSComponent->mLoadableRootsLoaded = true;
// Cache the result of LoadLoadableRoots so BlockUntilLoadableRootsLoaded
// can return it to all callers later.
mNSSComponent->mLoadableRootsLoadedResult = rv;
rv = mNSSComponent->mLoadableRootsLoadedMonitor.NotifyAll();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
return NS_OK;
}
nsresult
nsNSSComponent::BlockUntilLoadableRootsLoaded()
{
MonitorAutoLock rootsLoadedLock(mLoadableRootsLoadedMonitor);
while (!mLoadableRootsLoaded) {
nsresult rv = rootsLoadedLock.Wait();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
MOZ_ASSERT(mLoadableRootsLoaded);
return mLoadableRootsLoadedResult;
}
// Returns by reference the path to the directory containing the file that has
// been loaded as DLL_PREFIX nss3 DLL_SUFFIX.
static nsresult
GetNSS3Directory(nsCString& result)
{
UniquePRString nss3Path(
PR_GetLibraryFilePathname(DLL_PREFIX "nss3" DLL_SUFFIX,
reinterpret_cast<PRFuncPtr>(NSS_Initialize)));
if (!nss3Path) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nss not loaded?"));
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIFile> nss3File(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
if (!nss3File) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("couldn't create a file?"));
return NS_ERROR_FAILURE;
}
nsAutoCString nss3PathAsString(nss3Path.get());
nsresult rv = nss3File->InitWithNativePath(nss3PathAsString);
if (NS_FAILED(rv)) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("couldn't initialize file with path '%s'", nss3Path.get()));
return rv;
}
nsCOMPtr<nsIFile> nss3Directory;
rv = nss3File->GetParent(getter_AddRefs(nss3Directory));
if (NS_FAILED(rv)) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("couldn't get parent directory?"));
return rv;
}
return nss3Directory->GetNativePath(result);
}
// Returns by reference the path to the desired directory, based on the current
// settings in the directory service.
static nsresult
GetDirectoryPath(const char* directoryKey, nsCString& result)
{
nsCOMPtr<nsIProperties> directoryService(
do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
if (!directoryService) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("could not get directory service"));
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIFile> directory;
nsresult rv = directoryService->Get(directoryKey, NS_GET_IID(nsIFile),
getter_AddRefs(directory));
if (NS_FAILED(rv)) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("could not get '%s' from directory service", directoryKey));
return rv;
}
return directory->GetNativePath(result);
}
nsresult
LoadLoadableRootsTask::LoadLoadableRoots(
const nsNSSShutDownPreventionLock& /*proofOfLock*/)
{
// Find the best Roots module for our purposes.
// Prefer the application's installation directory,
// but also ensure the library is at least the version we expect.
nsAutoString modName;
nsresult rv = GetPIPNSSBundleString("RootCertModuleName", modName);
nsresult rv = mNSSComponent->GetPIPNSSBundleString("RootCertModuleName",
modName);
if (NS_FAILED(rv)) {
// When running Cpp unit tests on Android, this will fail because string
// bundles aren't available (see bug 1311077, bug 1228175 comment 12, and
@ -1068,66 +1229,58 @@ nsNSSComponent::LoadLoadableRoots()
// user, so this is a step in that direction anyway.
modName.AssignLiteral("Builtin Roots Module");
}
NS_ConvertUTF16toUTF8 modNameUTF8(modName);
nsCOMPtr<nsIProperties> directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
if (!directoryService)
return;
static const char nss_lib[] = "nss3";
const char* possible_ckbi_locations[] = {
nss_lib, // This special value means: search for ckbi in the directory
// where nss3 is.
NS_XPCOM_CURRENT_PROCESS_DIR,
NS_GRE_DIR,
0 // This special value means:
// search for ckbi in the directories on the shared
// library/DLL search path
};
for (size_t il = 0; il < sizeof(possible_ckbi_locations)/sizeof(const char*); ++il) {
nsAutoCString libDir;
if (possible_ckbi_locations[il]) {
nsCOMPtr<nsIFile> mozFile;
if (possible_ckbi_locations[il] == nss_lib) {
// Get the location of the nss3 library.
char* nss_path = PR_GetLibraryFilePathname(DLL_PREFIX "nss3" DLL_SUFFIX,
(PRFuncPtr) NSS_Initialize);
if (!nss_path) {
continue;
}
// Get the directory containing the nss3 library.
nsCOMPtr<nsIFile> nssLib(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv));
if (NS_SUCCEEDED(rv)) {
rv = nssLib->InitWithNativePath(nsDependentCString(nss_path));
}
PR_Free(nss_path); // PR_GetLibraryFilePathname() uses PR_Malloc().
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIFile> file;
if (NS_SUCCEEDED(nssLib->GetParent(getter_AddRefs(file)))) {
mozFile = do_QueryInterface(file);
}
}
} else {
directoryService->Get( possible_ckbi_locations[il],
NS_GET_IID(nsIFile),
getter_AddRefs(mozFile));
}
if (!mozFile) {
continue;
}
if (NS_FAILED(mozFile->GetNativePath(libDir))) {
continue;
}
Vector<nsCString> possibleCKBILocations;
// First try in the directory where we've already loaded
// DLL_PREFIX nss3 DLL_SUFFIX, since that's likely to be correct.
nsAutoCString nss3Dir;
rv = GetNSS3Directory(nss3Dir);
if (NS_SUCCEEDED(rv)) {
if (!possibleCKBILocations.append(Move(nss3Dir))) {
return NS_ERROR_OUT_OF_MEMORY;
}
} else {
// For some reason this fails on android. In any case, we should try with
// the other potential locations we have.
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("could not determine where nss was loaded from"));
}
nsAutoCString currentProcessDir;
rv = GetDirectoryPath(NS_XPCOM_CURRENT_PROCESS_DIR, currentProcessDir);
if (NS_SUCCEEDED(rv)) {
if (!possibleCKBILocations.append(Move(currentProcessDir))) {
return NS_ERROR_OUT_OF_MEMORY;
}
} else {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("could not get current process directory"));
}
nsAutoCString greDir;
rv = GetDirectoryPath(NS_GRE_DIR, greDir);
if (NS_SUCCEEDED(rv)) {
if (!possibleCKBILocations.append(Move(greDir))) {
return NS_ERROR_OUT_OF_MEMORY;
}
} else {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("could not get gre directory"));
}
// As a last resort, this will cause the library loading code to use the OS'
// default library search path.
nsAutoCString emptyString;
if (!possibleCKBILocations.append(Move(emptyString))) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ConvertUTF16toUTF8 modNameUTF8(modName);
if (mozilla::psm::LoadLoadableRoots(libDir, modNameUTF8)) {
break;
for (const auto& possibleCKBILocation : possibleCKBILocations) {
if (mozilla::psm::LoadLoadableRoots(possibleCKBILocation, modNameUTF8)) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("loaded CKBI from %s",
possibleCKBILocation.get()));
return NS_OK;
}
}
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("could not load loadable roots"));
return NS_ERROR_FAILURE;
}
void
@ -1851,13 +2004,6 @@ nsNSSComponent::InitializeNSS()
}
DisableMD5();
LoadLoadableRoots();
rv = LoadExtendedValidationInfo();
if (NS_FAILED(rv)) {
MOZ_LOG(gPIPNSSLog, LogLevel::Error, ("failed to load EV info"));
return rv;
}
MaybeEnableFamilySafetyCompatibility();
MaybeImportEnterpriseRoots();
@ -1923,6 +2069,9 @@ nsNSSComponent::InitializeNSS()
Telemetry::Accumulate(Telemetry::FIPS_ENABLED, true);
}
// Gather telemetry on any PKCS#11 modules we have loaded. Note that because
// we load the built-in root module asynchronously after this, the telemetry
// will not include it.
{ // Introduce scope for the AutoSECMODListReadLock.
AutoSECMODListReadLock lock;
for (SECMODModuleList* list = SECMOD_GetDefaultModuleList(); list;
@ -1959,7 +2108,9 @@ nsNSSComponent::InitializeNSS()
mNSSInitialized = true;
}
return NS_OK;
RefPtr<LoadLoadableRootsTask> loadLoadableRootsTask(
new LoadLoadableRootsTask(this));
return loadLoadableRootsTask->Dispatch();
}
void

Просмотреть файл

@ -10,6 +10,7 @@
#include "ScopedNSSTypes.h"
#include "SharedCertVerifier.h"
#include "mozilla/Attributes.h"
#include "mozilla/Monitor.h"
#include "mozilla/Mutex.h"
#include "mozilla/RefPtr.h"
#include "nsCOMPtr.h"
@ -82,6 +83,8 @@ public:
NS_IMETHOD GetEnterpriseRoots(nsIX509CertList** enterpriseRoots) = 0;
#endif
NS_IMETHOD BlockUntilLoadableRootsLoaded() = 0;
virtual ::already_AddRefed<mozilla::psm::SharedCertVerifier>
GetDefaultCertVerifier() = 0;
};
@ -95,6 +98,10 @@ class nsNSSComponent final : public nsINSSComponent
, public nsIObserver
{
public:
// LoadLoadableRootsTask updates mLoadableRootsLoaded and
// mLoadableRootsLoadedResult and then signals mLoadableRootsLoadedMonitor.
friend class LoadLoadableRootsTask;
NS_DEFINE_STATIC_CID_ACCESSOR( NS_NSSCOMPONENT_CID )
nsNSSComponent();
@ -135,6 +142,8 @@ public:
NS_IMETHOD GetEnterpriseRoots(nsIX509CertList** enterpriseRoots) override;
#endif
NS_IMETHOD BlockUntilLoadableRootsLoaded() override;
::already_AddRefed<mozilla::psm::SharedCertVerifier>
GetDefaultCertVerifier() override;
@ -154,7 +163,6 @@ private:
nsresult InitializeNSS();
void ShutdownNSS();
void LoadLoadableRoots();
void UnloadLoadableRoots();
void setValidationOptions(bool isInitialSetting);
nsresult setEnabledTLSVersions();
@ -175,6 +183,11 @@ private:
void UnloadEnterpriseRoots(const mozilla::MutexAutoLock& proofOfLock);
#endif // XP_WIN
// mLoadableRootsLoadedMonitor protects mLoadableRootsLoaded.
mozilla::Monitor mLoadableRootsLoadedMonitor;
bool mLoadableRootsLoaded;
nsresult mLoadableRootsLoadedResult;
// mMutex protects all members that are accessed from more than one thread.
// While this lock is held, the same thread must not attempt to acquire a
// nsNSSShutDownPreventionLock (acquiring a nsNSSShutDownPreventionLock and
@ -202,6 +215,16 @@ private:
static int mInstanceCount;
};
inline nsresult
BlockUntilLoadableRootsLoaded()
{
nsCOMPtr<nsINSSComponent> component(do_GetService(PSM_COMPONENT_CONTRACTID));
if (!component) {
return NS_ERROR_FAILURE;
}
return component->BlockUntilLoadableRootsLoaded();
}
class nsNSSErrors
{
public:

Просмотреть файл

@ -453,6 +453,11 @@ nsPK11TokenDB::FindTokenByName(const nsACString& tokenName,
return NS_ERROR_NOT_AVAILABLE;
}
nsresult rv = BlockUntilLoadableRootsLoaded();
if (NS_FAILED(rv)) {
return rv;
}
if (tokenName.IsEmpty()) {
return NS_ERROR_ILLEGAL_VALUE;
}
@ -479,6 +484,11 @@ nsPK11TokenDB::ListTokens(nsISimpleEnumerator** _retval)
return NS_ERROR_NOT_AVAILABLE;
}
nsresult rv = BlockUntilLoadableRootsLoaded();
if (NS_FAILED(rv)) {
return rv;
}
nsCOMPtr<nsIMutableArray> array = do_CreateInstance(NS_ARRAY_CONTRACTID);
if (!array) {
return NS_ERROR_FAILURE;

Просмотреть файл

@ -12,6 +12,7 @@
#include "mozilla/Unused.h"
#include "nsCOMPtr.h"
#include "nsIMutableArray.h"
#include "nsNSSComponent.h"
#include "nsPK11TokenDB.h"
#include "nsPromiseFlatString.h"
#include "secmod.h"
@ -429,6 +430,11 @@ nsPKCS11ModuleDB::FindModuleByName(const nsACString& name,
return NS_ERROR_NOT_AVAILABLE;
}
nsresult rv = BlockUntilLoadableRootsLoaded();
if (NS_FAILED(rv)) {
return rv;
}
UniqueSECMODModule mod(SECMOD_FindModule(PromiseFlatCString(name).get()));
if (!mod) {
return NS_ERROR_FAILURE;
@ -453,6 +459,11 @@ nsPKCS11ModuleDB::FindSlotByName(const nsACString& name,
return NS_ERROR_NOT_AVAILABLE;
}
nsresult rv = BlockUntilLoadableRootsLoaded();
if (NS_FAILED(rv)) {
return rv;
}
if (name.IsEmpty()) {
return NS_ERROR_ILLEGAL_VALUE;
}
@ -478,6 +489,11 @@ nsPKCS11ModuleDB::ListModules(nsISimpleEnumerator** _retval)
return NS_ERROR_NOT_AVAILABLE;
}
nsresult rv = BlockUntilLoadableRootsLoaded();
if (NS_FAILED(rv)) {
return rv;
}
nsCOMPtr<nsIMutableArray> array = do_CreateInstance(NS_ARRAY_CONTRACTID);
if (!array) {
return NS_ERROR_FAILURE;

Просмотреть файл

@ -61,7 +61,6 @@ function checkTestModuleExists() {
function checkModuleTelemetry(additionalExpectedModule = undefined) {
let expectedModules = [
"NSS Internal PKCS #11 Module",
`${AppConstants.DLL_PREFIX}nssckbi${AppConstants.DLL_SUFFIX}`,
];
if (additionalExpectedModule) {
expectedModules.push(additionalExpectedModule);