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
diff --git a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
index 0c74a6c..71bb218 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
@@ -797,38 +797,55 @@
}
Return<Status> 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<uint8_t> 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<char*>(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<uint8_t> id(buffer, buffer + kSecureStopIdSize);
+ // A secureStop contains id+data, we only use the id for removal
+ std::vector<uint8_t> id(buffer, buffer + kSecureStopIdSize);
status = removeSecureStop(toHidlVec(id));
if (Status::OK != status) break;
}
+ delete[] buffer;
return status;
}