Guard against double initialize

Merge from Widevine repo of http://go/wvgerrit/139498

If L1 OEMCrypto fails to initialize, we won't try again.

Bug: 206670307

Change-Id: I27474f7a23feeaf3fc58453ddb064e5afb49e117
This commit is contained in:
Fred Gylys-Colwell
2021-12-07 03:31:19 +00:00
parent 9ca983feb0
commit 4002d26703

View File

@@ -718,7 +718,7 @@ struct LevelSession {
level1_.Name = (L1_##Name##_t)dlsym(level1_library_, QUOTE(Function)); \
if (!level1_.Name) { \
LOGW("Could not load L1 %s. Falling back to L3.", QUOTE(Function)); \
if (level1_.Terminate) level1_.Terminate(); \
if (level1_.Terminate) Level1Terminate(); \
return false; \
} \
}
@@ -740,7 +740,7 @@ class Adapter {
public:
using map_iterator = std::map<OEMCrypto_SESSION, LevelSession>::iterator;
Adapter() : level1_valid_(false), level1_library_(nullptr) {}
Adapter() {}
// The adapter is only destroyed on certain errors, or when the process
// dies. It is NOT deleted after each OEMCrypto_Terminate.
@@ -819,9 +819,23 @@ class Adapter {
return result;
}
OEMCryptoResult Level1Terminate() {
OEMCryptoResult result = OEMCrypto_SUCCESS;
if (level1_.Terminate && level1_initialized_) {
LOGE("L1 Terminate");
result = level1_.Terminate();
} else {
LOGE("L1 Terminate not needed");
}
level1_initialized_ = false;
return result;
}
void FallBackToLevel3() {
Level1Terminate();
level1_ = FunctionPointers(); // revert to all null pointers.
level1_valid_ = false;
level1_failed_ = true;
// Note: if the function pointers are bad, we do not close the library and
// try again later. Instead, we permanently fall back to L3. This is a
// debatable choice: I decided the risk of a dlclose resource leak out
@@ -833,6 +847,12 @@ class Adapter {
if (metrics == nullptr) {
return false;
}
if (level1_failed_) {
// If we failed to initialize the level 1 library before, then we don't
// try again.
LOGE("Still falling back to L3.");
return false;
}
level1_valid_ = true;
const uint32_t kMinimumVersion = 8;
const uint32_t kMaximumVersion = 16;
@@ -864,6 +884,7 @@ class Adapter {
OEMCrypto_INITIALIZED_USING_L3_COULD_NOT_INITIALIZE_L1);
return false;
}
level1_initialized_ = true;
level1_.version = level1_.APIVersion();
level1_.security_level = wvcdm::kSecurityLevelUninitialized;
metrics->SetL1ApiVersion(level1_.version);
@@ -874,7 +895,7 @@ class Adapter {
level1_.version, kMinimumVersion);
metrics->OemCryptoDynamicAdapterMetrics::SetInitializationMode(
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_WRONG_L1_VERSION);
level1_.Terminate();
Level1Terminate();
return false;
}
@@ -996,7 +1017,6 @@ class Adapter {
level1_.security_level = wvcdm::kSecurityLevelUnknown;
}
}
return true;
}
@@ -1083,7 +1103,7 @@ class Adapter {
session_map_.clear();
OEMCryptoResult result = Level3_Terminate();
if (level1_valid_) {
result = level1_.Terminate();
result = Level1Terminate();
}
return result;
}
@@ -1154,8 +1174,7 @@ class Adapter {
if (!level1_.IsKeyboxOrOEMCertValid) {
// TODO(b/189989043): add metrics.
LOGE("L1 invalid function pointers. Falling back to L3");
if (level1_.Terminate) level1_.Terminate();
level1_valid_ = false;
FallBackToLevel3();
return level3_.IsKeyboxOrOEMCertValid ? level3_.IsKeyboxOrOEMCertValid()
: OEMCrypto_ERROR_NOT_IMPLEMENTED;
}
@@ -1205,15 +1224,17 @@ class Adapter {
wvcdm::metrics::
OEMCrypto_INITIALIZED_USING_L3_COULD_NOT_INSTALL_KEYBOX);
}
if (level1_.Terminate) level1_.Terminate();
level1_valid_ = false;
FallBackToLevel3();
return level3_.IsKeyboxOrOEMCertValid ? level3_.IsKeyboxOrOEMCertValid()
: OEMCrypto_ERROR_NOT_IMPLEMENTED;
}
private:
bool level1_valid_;
void* level1_library_;
bool level1_valid_ = false;
bool level1_initialized_ = false;
// If the level 1 fails to initialize once, we don't try again.
bool level1_failed_ = false;
void* level1_library_ = nullptr;
struct FunctionPointers level1_;
struct FunctionPointers level3_;
std::map<OEMCrypto_SESSION, LevelSession> session_map_;