[RESTRICT AUTOMERGE] Fix CryptoPlugin 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. The crash was reproduced on the device before the fix. Verified the test passes after the fix. 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: I4c83c44873eef960b654f387a3574fcad49c41a9
This commit is contained in:
parent
e289b4aa83
commit
a4e76aab23
3 changed files with 23 additions and 11 deletions
|
@ -9,6 +9,7 @@ cc_library_static {
|
||||||
"-Werror",
|
"-Werror",
|
||||||
"-Wextra",
|
"-Wextra",
|
||||||
"-Wall",
|
"-Wall",
|
||||||
|
"-Wthread-safety",
|
||||||
],
|
],
|
||||||
shared_libs: [
|
shared_libs: [
|
||||||
"liblog",
|
"liblog",
|
||||||
|
@ -19,5 +20,5 @@ cc_library_static {
|
||||||
export_header_lib_headers: [
|
export_header_lib_headers: [
|
||||||
"libutils_headers",
|
"libutils_headers",
|
||||||
],
|
],
|
||||||
export_include_dirs : ["include"]
|
export_include_dirs: ["include"],
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,8 @@ namespace implementation {
|
||||||
uint32_t bufferId) {
|
uint32_t bufferId) {
|
||||||
sp<IMemory> hidlMemory = mapMemory(base);
|
sp<IMemory> hidlMemory = mapMemory(base);
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> shared_buffer_lock(mSharedBufferLock);
|
||||||
|
|
||||||
// allow mapMemory to return nullptr
|
// allow mapMemory to return nullptr
|
||||||
mSharedBufferMap[bufferId] = hidlMemory;
|
mSharedBufferMap[bufferId] = hidlMemory;
|
||||||
return Void();
|
return Void();
|
||||||
|
@ -65,7 +67,7 @@ namespace implementation {
|
||||||
const SharedBuffer& source, uint64_t offset,
|
const SharedBuffer& source, uint64_t offset,
|
||||||
const DestinationBuffer& destination,
|
const DestinationBuffer& destination,
|
||||||
decrypt_cb _hidl_cb) {
|
decrypt_cb _hidl_cb) {
|
||||||
|
std::unique_lock<std::mutex> shared_buffer_lock(mSharedBufferLock);
|
||||||
if (mSharedBufferMap.find(source.bufferId) == mSharedBufferMap.end()) {
|
if (mSharedBufferMap.find(source.bufferId) == mSharedBufferMap.end()) {
|
||||||
_hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "source decrypt buffer base not set");
|
_hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "source decrypt buffer base not set");
|
||||||
return Void();
|
return Void();
|
||||||
|
@ -79,7 +81,7 @@ namespace implementation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
android::CryptoPlugin::Mode legacyMode;
|
android::CryptoPlugin::Mode legacyMode = android::CryptoPlugin::kMode_Unencrypted;
|
||||||
switch(mode) {
|
switch(mode) {
|
||||||
case Mode::UNENCRYPTED:
|
case Mode::UNENCRYPTED:
|
||||||
legacyMode = android::CryptoPlugin::kMode_Unencrypted;
|
legacyMode = android::CryptoPlugin::kMode_Unencrypted;
|
||||||
|
@ -170,6 +172,10 @@ namespace implementation {
|
||||||
_hidl_cb(Status::BAD_VALUE, 0, "invalid destination type");
|
_hidl_cb(Status::BAD_VALUE, 0, "invalid destination type");
|
||||||
return Void();
|
return Void();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// release mSharedBufferLock
|
||||||
|
shared_buffer_lock.unlock();
|
||||||
|
|
||||||
ssize_t result = mLegacyPlugin->decrypt(secure, keyId.data(), iv.data(),
|
ssize_t result = mLegacyPlugin->decrypt(secure, keyId.data(), iv.data(),
|
||||||
legacyMode, legacyPattern, srcPtr, legacySubSamples.get(),
|
legacyMode, legacyPattern, srcPtr, legacySubSamples.get(),
|
||||||
subSamples.size(), destPtr, &detailMessage);
|
subSamples.size(), destPtr, &detailMessage);
|
||||||
|
|
|
@ -17,11 +17,14 @@
|
||||||
#ifndef ANDROID_HARDWARE_DRM_V1_0__CRYPTOPLUGIN_H
|
#ifndef ANDROID_HARDWARE_DRM_V1_0__CRYPTOPLUGIN_H
|
||||||
#define ANDROID_HARDWARE_DRM_V1_0__CRYPTOPLUGIN_H
|
#define ANDROID_HARDWARE_DRM_V1_0__CRYPTOPLUGIN_H
|
||||||
|
|
||||||
#include <android/hidl/memory/1.0/IMemory.h>
|
#include <android-base/thread_annotations.h>
|
||||||
#include <android/hardware/drm/1.0/ICryptoPlugin.h>
|
#include <android/hardware/drm/1.0/ICryptoPlugin.h>
|
||||||
|
#include <android/hidl/memory/1.0/IMemory.h>
|
||||||
#include <hidl/Status.h>
|
#include <hidl/Status.h>
|
||||||
#include <media/hardware/CryptoAPI.h>
|
#include <media/hardware/CryptoAPI.h>
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
namespace hardware {
|
namespace hardware {
|
||||||
namespace drm {
|
namespace drm {
|
||||||
|
@ -60,19 +63,21 @@ struct CryptoPlugin : public ICryptoPlugin {
|
||||||
Return<void> setSharedBufferBase(const ::android::hardware::hidl_memory& base,
|
Return<void> setSharedBufferBase(const ::android::hardware::hidl_memory& base,
|
||||||
uint32_t bufferId) override;
|
uint32_t bufferId) override;
|
||||||
|
|
||||||
Return<void> decrypt(bool secure, const hidl_array<uint8_t, 16>& keyId,
|
Return<void> decrypt(
|
||||||
const hidl_array<uint8_t, 16>& iv, Mode mode, const Pattern& pattern,
|
bool secure, const hidl_array<uint8_t, 16>& keyId, const hidl_array<uint8_t, 16>& iv,
|
||||||
const hidl_vec<SubSample>& subSamples, const SharedBuffer& source,
|
Mode mode, const Pattern& pattern, const hidl_vec<SubSample>& subSamples,
|
||||||
uint64_t offset, const DestinationBuffer& destination,
|
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:
|
private:
|
||||||
android::CryptoPlugin *mLegacyPlugin;
|
android::CryptoPlugin *mLegacyPlugin;
|
||||||
std::map<uint32_t, sp<IMemory> > mSharedBufferMap;
|
std::map<uint32_t, sp<IMemory>> mSharedBufferMap GUARDED_BY(mSharedBufferLock);
|
||||||
|
|
||||||
CryptoPlugin() = delete;
|
CryptoPlugin() = delete;
|
||||||
CryptoPlugin(const CryptoPlugin &) = delete;
|
CryptoPlugin(const CryptoPlugin &) = delete;
|
||||||
void operator=(const CryptoPlugin &) = delete;
|
void operator=(const CryptoPlugin &) = delete;
|
||||||
|
|
||||||
|
std::mutex mSharedBufferLock;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace implementation
|
} // namespace implementation
|
||||||
|
|
Loading…
Reference in a new issue