From 0ec6f56ea142285856dec8ac0ea35f3988621abc Mon Sep 17 00:00:00 2001 From: Edwin Wong Date: Tue, 24 Sep 2019 07:31:40 -0700 Subject: RESTRICT AUTOMERGE Harden Clearkey releaseSecureStops implementation. Perform more checking for invalid input. Test: CTS tests android.media.cts.MediaDrmClearkeyTest#testSecureStop android.media.cts.MediaDrmClearkeyTest Test: run drmpoc no signal 6 on clearkey service after the fix Test: adb shell ps | grep clearkey pid ID does not change after running drmpoc bug: 137284652 Change-Id: I971bb33eec6d37ef86fa1a53501c1e6bda50fa3b --- drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp | 31 ++++++++++++++++++------ 1 file changed, 24 insertions(+), 7 deletions(-) (limited to 'drm') diff --git a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp index 0c74a6ccad..71bb2185bd 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp +++ b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp @@ -797,38 +797,55 @@ Return DrmPlugin::getSecureStopIds(getSecureStopIds_cb _hidl_cb) { } Return DrmPlugin::releaseSecureStops(const SecureStopRelease& ssRelease) { - // minimum opaqueData contains the uint32_t count, see comment below - if (ssRelease.opaqueData.size() < sizeof(uint32_t)) { + // OpaqueData starts with 4 byte decimal integer string + const size_t kFourBytesOffset = 4; + if (ssRelease.opaqueData.size() < kFourBytesOffset) { + ALOGE("Invalid secureStopRelease length"); return Status::BAD_VALUE; } Status status = Status::OK; std::vector input = toVector(ssRelease.opaqueData); + if (input.size() < kSecureStopIdSize + kFourBytesOffset) { + // The minimum size of SecureStopRelease has to contain + // a 4 bytes count and one secureStop id + ALOGE("Total size of secureStops is too short"); + return Status::BAD_VALUE; + } + // The format of opaqueData is shared between the server // and the drm service. The clearkey implementation consists of: // count - number of secure stops // list of fixed length secure stops - size_t countBufferSize = sizeof(uint32_t); uint32_t count = 0; sscanf(reinterpret_cast(input.data()), "%04" PRIu32, &count); // Avoid divide by 0 below. if (count == 0) { + ALOGE("Invalid 0 secureStop count"); return Status::BAD_VALUE; } - size_t secureStopSize = (input.size() - countBufferSize) / count; - uint8_t buffer[secureStopSize]; - size_t offset = countBufferSize; // skip the count + // Computes the fixed length secureStop size + size_t secureStopSize = (input.size() - kFourBytesOffset) / count; + if (secureStopSize < kSecureStopIdSize) { + // A valid secureStop contains the id plus data + ALOGE("Invalid secureStop size"); + return Status::BAD_VALUE; + } + uint8_t* buffer = new uint8_t[secureStopSize]; + size_t offset = kFourBytesOffset; // skip the count for (size_t i = 0; i < count; ++i, offset += secureStopSize) { memcpy(buffer, input.data() + offset, secureStopSize); - std::vector id(buffer, buffer + kSecureStopIdSize); + // A secureStop contains id+data, we only use the id for removal + std::vector id(buffer, buffer + kSecureStopIdSize); status = removeSecureStop(toHidlVec(id)); if (Status::OK != status) break; } + delete[] buffer; return status; } -- cgit v1.2.3