From f49a3e5682b0f6cbe5b81467dc8792fb41e54632 Mon Sep 17 00:00:00 2001 From: Edwin Wong Date: Fri, 22 Jan 2021 22:46:42 -0800 Subject: [PATCH] [RESTRICT AUTOMERGE] Fix WVCryptoPlugin use after free vulnerability. The shared memory buffer used by srcPtr can be freed by another thread because it is not protected by a mutex. Subsequently, a use after free AIGABRT can occur in a race condition. SafetyNet logging is not added to avoid log spamming. The mutex lock is called to setup for decryption, which is called frequently. Test is run on rvc-dev branch, using target_hwasan-userdebug build. Test: sts sts-tradefed run sts-engbuild-no-spl-lock -m StsHostTestCases --test android.security.sts.Bug_176495665#testPocBug_176495665 Test: push to device with target_hwasan-userdebug build adb shell /data/local/tmp/Bug-176495665_sts64 Bug: 176495665 Bug: 176444161 Change-Id: Ie1aca0ceacb4b7a1b6e473b823541607a36d8cb4 --- libwvdrmengine/mediacrypto/Android.mk | 2 ++ libwvdrmengine/mediacrypto/include_hidl/WVCryptoPlugin.h | 9 +++++++-- libwvdrmengine/mediacrypto/src_hidl/WVCryptoPlugin.cpp | 7 ++++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/libwvdrmengine/mediacrypto/Android.mk b/libwvdrmengine/mediacrypto/Android.mk index 8cf087b6..a1955757 100644 --- a/libwvdrmengine/mediacrypto/Android.mk +++ b/libwvdrmengine/mediacrypto/Android.mk @@ -68,6 +68,8 @@ LOCAL_SHARED_LIBRARIES := \ libhidlmemory \ liblog +LOCAL_CFLAGS := -Wthread-safety + LOCAL_MODULE := libwvdrmcryptoplugin_hidl LOCAL_PROPRIETARY_MODULE := true diff --git a/libwvdrmengine/mediacrypto/include_hidl/WVCryptoPlugin.h b/libwvdrmengine/mediacrypto/include_hidl/WVCryptoPlugin.h index 1ea1fd4a..651c4a1a 100644 --- a/libwvdrmengine/mediacrypto/include_hidl/WVCryptoPlugin.h +++ b/libwvdrmengine/mediacrypto/include_hidl/WVCryptoPlugin.h @@ -5,9 +5,12 @@ #ifndef WV_CRYPTO_PLUGIN_H_ #define WV_CRYPTO_PLUGIN_H_ +#include #include #include +#include + #include "wv_content_decryption_module.h" #include "WVTypes.h" @@ -58,13 +61,13 @@ struct WVCryptoPlugin : public ICryptoPlugin { const SharedBuffer& source, uint64_t offset, const DestinationBuffer& destination, - decrypt_cb _hidl_cb) override; + decrypt_cb _hidl_cb) override NO_THREAD_SAFETY_ANALYSIS; // use unique_lock private: WVDRM_DISALLOW_COPY_AND_ASSIGN_AND_NEW(WVCryptoPlugin); wvcdm::CdmSessionId mSessionId; - std::map > mSharedBufferMap; + std::map > mSharedBufferMap GUARDED_BY(mSharedBufferLock); sp const mCDM; @@ -74,6 +77,8 @@ struct WVCryptoPlugin : public ICryptoPlugin { static wvcdm::CdmResponseType countEncryptedBlocksInPatternedRange( size_t range, const Pattern& pattern, uint64_t* result); static void incrementIV(uint64_t increaseBy, std::vector* ivPtr); + + std::mutex mSharedBufferLock; }; } // namespace widevine diff --git a/libwvdrmengine/mediacrypto/src_hidl/WVCryptoPlugin.cpp b/libwvdrmengine/mediacrypto/src_hidl/WVCryptoPlugin.cpp index 75b02259..b0b798d8 100644 --- a/libwvdrmengine/mediacrypto/src_hidl/WVCryptoPlugin.cpp +++ b/libwvdrmengine/mediacrypto/src_hidl/WVCryptoPlugin.cpp @@ -98,6 +98,8 @@ Return WVCryptoPlugin::setSharedBufferBase( sp hidlMemory = mapMemory(base); ALOGE_IF(hidlMemory == nullptr, "mapMemory returns nullptr"); + std::lock_guard shared_buffer_lock(mSharedBufferLock); + // allow mapMemory to return nullptr mSharedBufferMap[bufferId] = hidlMemory; return Void(); @@ -114,7 +116,7 @@ Return WVCryptoPlugin::decrypt( uint64_t offset, const DestinationBuffer& destination, decrypt_cb _hidl_cb) { - + std::unique_lock lock(mSharedBufferLock); if (mSharedBufferMap.find(source.bufferId) == mSharedBufferMap.end()) { _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "source decrypt buffer base not set"); @@ -182,6 +184,9 @@ Return WVCryptoPlugin::decrypt( destPtr = static_cast(handle); } + // release mSharedBufferLock + lock.unlock(); + // Calculate the output buffer size and determine if any subsamples are // encrypted. size_t destSize = 0;