From 3da4f9d7d502aa544542c3f469b57faa8c23c49b Mon Sep 17 00:00:00 2001 From: "John \"Juce\" Bruce" Date: Mon, 13 Oct 2014 13:40:44 -0700 Subject: [PATCH] Protect Session ID List With a Lock (This is a merge of https://widevine-internal-review.googlesource.com/#/c/11405 from the Widevine CDM Repo.) AUPT is revealing a crash when destructing WVDrmPlugin due to multi-threaded contention over the session map. As a fix, we are now protecting access to the map via a mutex. Bug: 17761616 Change-Id: Iddeca657effd3c7f3ff35ce334d7979291667cef --- libwvdrmengine/mediadrm/include/WVDrmPlugin.h | 3 ++ libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp | 31 ++++++++++++++++--- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/libwvdrmengine/mediadrm/include/WVDrmPlugin.h b/libwvdrmengine/mediadrm/include/WVDrmPlugin.h index 3054d339..3817d308 100644 --- a/libwvdrmengine/mediadrm/include/WVDrmPlugin.h +++ b/libwvdrmengine/mediadrm/include/WVDrmPlugin.h @@ -16,6 +16,7 @@ #include "utils/Errors.h" #include "utils/KeyedVector.h" #include "utils/List.h" +#include "utils/Mutex.h" #include "utils/String8.h" #include "utils/Vector.h" #include "wv_cdm_event_listener.h" @@ -26,6 +27,7 @@ namespace wvdrm { using android::KeyedVector; using android::List; +using android::Mutex; using android::status_t; using android::String8; using android::Vector; @@ -229,6 +231,7 @@ class WVDrmPlugin : public android::DrmPlugin, WvContentDecryptionModule* mCDM; WVGenericCryptoInterface* mCrypto; + Mutex mCryptoSessionsMutex; map mCryptoSessions; status_t mapAndNotifyOfCdmResponseType(const Vector& sessionId, diff --git a/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp b/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp index 7cef174a..a28a00ff 100644 --- a/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp +++ b/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp @@ -35,17 +35,18 @@ using namespace wvcdm; WVDrmPlugin::WVDrmPlugin(WvContentDecryptionModule* cdm, WVGenericCryptoInterface* crypto) - : mCDM(cdm), mCrypto(crypto) {} + : mCDM(cdm), mCrypto(crypto), mCryptoSessionsMutex(), mCryptoSessions() {} WVDrmPlugin::~WVDrmPlugin() { typedef map::iterator mapIterator; + Mutex::Autolock lock(mCryptoSessionsMutex); for (mapIterator iter = mCryptoSessions.begin(); iter != mCryptoSessions.end(); ++iter) { bool bRes = mCDM->DetachEventListener(iter->first, this); if (!bRes) { - ALOGE("Received failure when trying to detach WVDrmPlugin as an event" + ALOGE("Received failure when trying to detach WVDrmPlugin as an event " "listener."); } @@ -82,7 +83,10 @@ status_t WVDrmPlugin::openSession(Vector& sessionId) { OEMCrypto_SESSION oecSessionId; istringstream(info[QUERY_KEY_OEMCRYPTO_SESSION_ID]) >> oecSessionId; - mCryptoSessions[cdmSessionId] = CryptoSession(oecSessionId); + { + Mutex::Autolock lock(mCryptoSessionsMutex); + mCryptoSessions[cdmSessionId] = CryptoSession(oecSessionId); + } success = true; } else { @@ -123,6 +127,7 @@ status_t WVDrmPlugin::closeSession(const Vector& sessionId) { CdmResponseType res = mCDM->CloseSession(cdmSessionId); if (isCdmResponseTypeSuccess(res)) { + Mutex::Autolock lock(mCryptoSessionsMutex); mCryptoSessions.erase(cdmSessionId); } @@ -559,7 +564,12 @@ status_t WVDrmPlugin::getPropertyByteArray(const String8& name, status_t WVDrmPlugin::setPropertyString(const String8& name, const String8& value) { if (name == "securityLevel") { - if (mCryptoSessions.size() == 0) { + size_t sessionCount = 0; + { + Mutex::Autolock lock(mCryptoSessionsMutex); + sessionCount = mCryptoSessions.size(); + } + if (sessionCount == 0) { if (value == QUERY_VALUE_SECURITY_LEVEL_L3.c_str()) { mPropertySet.set_security_level(QUERY_VALUE_SECURITY_LEVEL_L3); } else if (value == QUERY_VALUE_SECURITY_LEVEL_L1.c_str()) { @@ -600,7 +610,12 @@ status_t WVDrmPlugin::setPropertyString(const String8& name, return android::BAD_VALUE; } } else if (name == "sessionSharing") { - if (mCryptoSessions.size() == 0) { + size_t sessionCount = 0; + { + Mutex::Autolock lock(mCryptoSessionsMutex); + sessionCount = mCryptoSessions.size(); + } + if (sessionCount == 0) { if (value == kEnable) { mPropertySet.set_is_session_sharing_enabled(true); } else if (value == kDisable) { @@ -637,6 +652,7 @@ status_t WVDrmPlugin::setPropertyByteArray(const String8& name, status_t WVDrmPlugin::setCipherAlgorithm(const Vector& sessionId, const String8& algorithm) { CdmSessionId cdmSessionId(sessionId.begin(), sessionId.end()); + Mutex::Autolock lock(mCryptoSessionsMutex); if (!mCryptoSessions.count(cdmSessionId)) { return android::ERROR_DRM_SESSION_NOT_OPENED; @@ -656,6 +672,7 @@ status_t WVDrmPlugin::setCipherAlgorithm(const Vector& sessionId, status_t WVDrmPlugin::setMacAlgorithm(const Vector& sessionId, const String8& algorithm) { CdmSessionId cdmSessionId(sessionId.begin(), sessionId.end()); + Mutex::Autolock lock(mCryptoSessionsMutex); if (!mCryptoSessions.count(cdmSessionId)) { return android::ERROR_DRM_SESSION_NOT_OPENED; @@ -678,6 +695,7 @@ status_t WVDrmPlugin::encrypt(const Vector& sessionId, const Vector& iv, Vector& output) { CdmSessionId cdmSessionId(sessionId.begin(), sessionId.end()); + Mutex::Autolock lock(mCryptoSessionsMutex); if (!mCryptoSessions.count(cdmSessionId)) { return android::ERROR_DRM_SESSION_NOT_OPENED; @@ -717,6 +735,7 @@ status_t WVDrmPlugin::decrypt(const Vector& sessionId, const Vector& iv, Vector& output) { CdmSessionId cdmSessionId(sessionId.begin(), sessionId.end()); + Mutex::Autolock lock(mCryptoSessionsMutex); if (!mCryptoSessions.count(cdmSessionId)) { return android::ERROR_DRM_SESSION_NOT_OPENED; @@ -755,6 +774,7 @@ status_t WVDrmPlugin::sign(const Vector& sessionId, const Vector& message, Vector& signature) { CdmSessionId cdmSessionId(sessionId.begin(), sessionId.end()); + Mutex::Autolock lock(mCryptoSessionsMutex); if (!mCryptoSessions.count(cdmSessionId)) { return android::ERROR_DRM_SESSION_NOT_OPENED; @@ -810,6 +830,7 @@ status_t WVDrmPlugin::verify(const Vector& sessionId, const Vector& signature, bool& match) { CdmSessionId cdmSessionId(sessionId.begin(), sessionId.end()); + Mutex::Autolock lock(mCryptoSessionsMutex); if (!mCryptoSessions.count(cdmSessionId)) { return android::ERROR_DRM_SESSION_NOT_OPENED;