From 8359c72f7f3fcb54fc36bed81cd805df42fd98fc Mon Sep 17 00:00:00 2001 From: kunal rai Date: Thu, 25 Apr 2024 15:30:53 +0530 Subject: [PATCH] Refactored mediametrics_service_fuzzer The following are updates to the fuzzer: 1. Randomised parameters 2. Improved code coverage of AudioAnalytics.cpp by 40% Test: ./mediametrics_service_fuzzer exec/s: 1148 Bug: 339558167 Change-Id: If29d348ab8033a5b8dbe0f2a4bab38d02135b6d5 --- .../fuzzer/mediametrics_service_fuzzer.cpp | 452 +++++++----------- 1 file changed, 183 insertions(+), 269 deletions(-) diff --git a/services/mediametrics/fuzzer/mediametrics_service_fuzzer.cpp b/services/mediametrics/fuzzer/mediametrics_service_fuzzer.cpp index c6793a9b69..c7b4297806 100644 --- a/services/mediametrics/fuzzer/mediametrics_service_fuzzer.cpp +++ b/services/mediametrics/fuzzer/mediametrics_service_fuzzer.cpp @@ -17,6 +17,7 @@ ***************************************************************************** * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore */ +#include #include #include #include @@ -26,210 +27,158 @@ #include #include #include +#include using namespace android; +static constexpr size_t STATSD_LOG_LINES_MAX = 48; +static unsigned long long kPackedCallingUid = (unsigned long long)AID_SYSTEM << 32; +constexpr int8_t kMaxBytes = 100; +constexpr int8_t kMinBytes = 0; +constexpr size_t kMaxItemLength = 16; // low water mark constexpr size_t kLogItemsLowWater = 1; // high water mark constexpr size_t kLogItemsHighWater = 2; -constexpr size_t kMaxItemLength = 16; -constexpr size_t kMaxApis = 64; + +/* + * Concatenating strings to generate keys in such a way that the + * lambda function inside AudioAnalytics() added in the 'mAction' object is covered + */ + +std::string keyMediaValues[] = { + "metrics.manager", + "mediadrm", + "audio.device.a2dp", + AMEDIAMETRICS_KEY_AUDIO_MIDI, + AMEDIAMETRICS_KEY_PREFIX_AUDIO_SPATIALIZER "*", + AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD "*", + AMEDIAMETRICS_KEY_AUDIO_FLINGER, + AMEDIAMETRICS_KEY_AUDIO_POLICY, + AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK "*", + AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD "*", + AMEDIAMETRICS_KEY_PREFIX_AUDIO_STREAM "*", + AMEDIAMETRICS_KEY_PREFIX_AUDIO_DEVICE + "postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent", +}; + +std::string keyMediaAction[] = { + "createAudioPatch", + "connected", + AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE, + AMEDIAMETRICS_PROP_EVENT_VALUE_TIMEOUT, + AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR, + AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM, + AMEDIAMETRICS_PROP_EVENT_VALUE_DEVICECLOSED, + AMEDIAMETRICS_PROP_EVENT_VALUE_SETVOICEVOLUME, + AMEDIAMETRICS_PROP_EVENT_VALUE_SETMODE, + AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP, +}; class MediaMetricsServiceFuzzer { - public: - void invokeStartsWith(const uint8_t *data, size_t size); - void invokeInstantiate(const uint8_t *data, size_t size); - void invokePackageInstallerCheck(const uint8_t *data, size_t size); - void invokeItemManipulation(const uint8_t *data, size_t size); - void invokeItemExpansion(const uint8_t *data, size_t size); - void invokeTimeMachineStorage(const uint8_t *data, size_t size); - void invokeTransactionLog(const uint8_t *data, size_t size); - void invokeAnalyticsAction(const uint8_t *data, size_t size); - void invokeAudioAnalytics(const uint8_t *data, size_t size); - void invokeTimedAction(const uint8_t *data, size_t size); - void process(const uint8_t *data, size_t size); + public: + MediaMetricsServiceFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){}; + void process(); + void invokeStartsWith(); + void invokeInstantiate(); + void invokePackageInstallerCheck(); + void invokeTimeMachineStorage(); + void invokeTransactionLog(); + void invokeAnalyticsAction(); + void invokeAudioAnalytics(); + void invokeTimedAction(); + void setKeyValues(std::shared_ptr& item, std::string keyValue); + std::shared_ptr CreateItem(); + sp mMediaMetricsService; + FuzzedDataProvider mFdp; std::atomic_int mValue = 0; }; -void MediaMetricsServiceFuzzer::invokeStartsWith(const uint8_t *data, size_t size) { - FuzzedDataProvider fdp = FuzzedDataProvider(data, size); - while (fdp.remaining_bytes()) { - android::mediametrics::startsWith(fdp.ConsumeRandomLengthString(), - fdp.ConsumeRandomLengthString()); - } -} - -void MediaMetricsServiceFuzzer::invokeInstantiate(const uint8_t *data, size_t size) { - FuzzedDataProvider fdp = FuzzedDataProvider(data, size); - sp mediaMetricsService = new MediaMetricsService(); - - while (fdp.remaining_bytes()) { - std::unique_ptr random_key( - mediametrics::Item::create(fdp.ConsumeRandomLengthString())); - mediaMetricsService->submit(random_key.get()); - random_key->setInt32(fdp.ConsumeRandomLengthString().c_str(), - fdp.ConsumeIntegral()); - mediaMetricsService->submit(random_key.get()); - - std::unique_ptr audiotrack_key( - mediametrics::Item::create("audiotrack")); - mediaMetricsService->submit(audiotrack_key.get()); - audiotrack_key->addInt32(fdp.ConsumeRandomLengthString().c_str(), - fdp.ConsumeIntegral()); - mediaMetricsService->submit(audiotrack_key.get()); - } +void MediaMetricsServiceFuzzer::setKeyValues(std::shared_ptr& item, + std::string keyValue) { + auto invokeActionAPIs = mFdp.PickValueInArray>({ + [&]() { item->setInt32(keyValue.c_str(), mFdp.ConsumeIntegral()); }, + [&]() { item->addInt32(keyValue.c_str(), mFdp.ConsumeIntegral()); }, + [&]() { item->setInt64(keyValue.c_str(), mFdp.ConsumeIntegral()); }, + [&]() { item->addInt64(keyValue.c_str(), mFdp.ConsumeIntegral()); }, + [&]() { item->setDouble(keyValue.c_str(), mFdp.ConsumeFloatingPoint()); }, + [&]() { item->addDouble(keyValue.c_str(), mFdp.ConsumeFloatingPoint()); }, + [&]() { item->setTimestamp(mFdp.ConsumeIntegral()); }, + [&]() { + std::string value = mFdp.ConsumeBool() + ? mFdp.ConsumeRandomLengthString(kMaxBytes) + : mFdp.PickValueInArray(keyMediaAction); + item->setCString(keyValue.c_str(), value.c_str()); + }, + [&]() { + item->setRate(keyValue.c_str(), mFdp.ConsumeIntegral(), + mFdp.ConsumeIntegral()); + }, + [&]() { + mediametrics::LogItem<1> itemTemp(mFdp.ConsumeRandomLengthString(kMaxBytes)); + itemTemp.setPid(mFdp.ConsumeIntegral()) + .setUid(mFdp.ConsumeIntegral()); + + int32_t i = mFdp.ConsumeIntegral(); + itemTemp.set(std::to_string(i).c_str(), (int32_t)i); + itemTemp.updateHeader(); + (void)item->readFromByteString(itemTemp.getBuffer(), itemTemp.getLength()); + }, + + }); + invokeActionAPIs(); } -void MediaMetricsServiceFuzzer::invokePackageInstallerCheck(const uint8_t *data, size_t size) { - FuzzedDataProvider fdp = FuzzedDataProvider(data, size); - while (fdp.remaining_bytes()) { - MediaMetricsService::useUidForPackage(fdp.ConsumeRandomLengthString().c_str(), - fdp.ConsumeRandomLengthString().c_str()); +std::shared_ptr MediaMetricsServiceFuzzer::CreateItem() { + std::string key; + if (mFdp.ConsumeBool()) { + key = mFdp.ConsumeRandomLengthString(kMaxItemLength); + } else { + key = mFdp.PickValueInArray(keyMediaValues); } -} - -void MediaMetricsServiceFuzzer::invokeItemManipulation(const uint8_t *data, size_t size) { - FuzzedDataProvider fdp = FuzzedDataProvider(data, size); - mediametrics::Item item(fdp.ConsumeRandomLengthString().c_str()); - while (fdp.remaining_bytes()) { - const uint8_t action = fdp.ConsumeIntegralInRange(0, 16); - const std::string key = fdp.ConsumeRandomLengthString(); - if (fdp.remaining_bytes() < 1 || key.length() < 1) { - break; + std::shared_ptr item = std::make_shared(key.c_str()); + size_t numKeys = mFdp.ConsumeIntegralInRange(kMinBytes, kMaxBytes); + std::set keySet; + for (size_t i = 0; i < numKeys; ++i) { + std::string keyValue; + if (mFdp.ConsumeBool()) { + keyValue = mFdp.ConsumeRandomLengthString(kMaxBytes); + } else { + keyValue = mFdp.PickValueInArray( + {AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_STATE, "logSessionIkeyd"}); } - switch (action) { - case 0: { - item.setInt32(key.c_str(), fdp.ConsumeIntegral()); - break; - } - case 1: { - item.addInt32(key.c_str(), fdp.ConsumeIntegral()); - break; - } - case 2: { - int32_t i32 = 0; - item.getInt32(key.c_str(), &i32); - break; - } - case 3: { - item.setInt64(key.c_str(), fdp.ConsumeIntegral()); - break; - } - case 4: { - item.addInt64(key.c_str(), fdp.ConsumeIntegral()); - break; - } - case 5: { - int64_t i64 = 0; - item.getInt64(key.c_str(), &i64); - break; - } - case 6: { - item.setDouble(key.c_str(), fdp.ConsumeFloatingPoint()); - break; - } - case 7: { - item.addDouble(key.c_str(), fdp.ConsumeFloatingPoint()); - break; - } - case 8: { - double d = 0; - item.getDouble(key.c_str(), &d); - break; - } - case 9: { - item.setCString(key.c_str(), fdp.ConsumeRandomLengthString().c_str()); - break; - } - case 10: { - char *s = nullptr; - item.getCString(key.c_str(), &s); - if (s) free(s); - break; - } - case 11: { - std::string s; - item.getString(key.c_str(), &s); - break; - } - case 12: { - item.setRate(key.c_str(), fdp.ConsumeIntegral(), - fdp.ConsumeIntegral()); - break; - } - case 13: { - int64_t b = 0, h = 0; - double d = 0; - item.getRate(key.c_str(), &b, &h, &d); - break; - } - case 14: { - (void)item.filter(key.c_str()); - break; - } - case 15: { - const char *arr[1] = {""}; - arr[0] = const_cast(key.c_str()); - (void)item.filterNot(1, arr); - break; - } - case 16: { - (void)item.toString().c_str(); - break; - } + if (keySet.find(keyValue) == keySet.end()) { + setKeyValues(item, keyValue); + keySet.insert(keyValue); } } - - Parcel p; - mediametrics::Item item2; - - (void)item.writeToParcel(&p); - p.setDataPosition(0); // rewind for reading - (void)item2.readFromParcel(p); - - char *byteData = nullptr; - size_t length = 0; - (void)item.writeToByteString(&byteData, &length); - (void)item2.readFromByteString(byteData, length); - if (byteData) { - free(byteData); - } - - sp mediaMetricsService = new MediaMetricsService(); - mediaMetricsService->submit(&item2); + return item; } -void MediaMetricsServiceFuzzer::invokeItemExpansion(const uint8_t *data, size_t size) { - FuzzedDataProvider fdp = FuzzedDataProvider(data, size); - - mediametrics::LogItem<1> item("FuzzItem"); - item.setPid(fdp.ConsumeIntegral()).setUid(fdp.ConsumeIntegral()); - - while (fdp.remaining_bytes()) { - int32_t i = fdp.ConsumeIntegral(); - item.set(std::to_string(i).c_str(), (int32_t)i); - } - item.updateHeader(); - - mediametrics::Item item2; - (void)item2.readFromByteString(item.getBuffer(), item.getLength()); +void MediaMetricsServiceFuzzer::invokeStartsWith() { + android::mediametrics::startsWith(mFdp.ConsumeRandomLengthString(kMaxBytes), + mFdp.ConsumeRandomLengthString(kMaxBytes)); +} - sp mediaMetricsService = new MediaMetricsService(); - mediaMetricsService->submit(&item2); +void MediaMetricsServiceFuzzer::invokeInstantiate() { + auto item = CreateItem(); + mMediaMetricsService->submit(item.get()); } -void MediaMetricsServiceFuzzer::invokeTimeMachineStorage(const uint8_t *data, size_t size) { - FuzzedDataProvider fdp = FuzzedDataProvider(data, size); +void MediaMetricsServiceFuzzer::invokePackageInstallerCheck() { + MediaMetricsService::useUidForPackage(mFdp.ConsumeRandomLengthString(kMaxBytes).c_str(), + mFdp.ConsumeRandomLengthString(kMaxBytes).c_str()); +} - auto item = std::make_shared("FuzzKey"); - int32_t i32 = fdp.ConsumeIntegral(); - int64_t i64 = fdp.ConsumeIntegral(); - double d = fdp.ConsumeFloatingPoint(); - std::string str = fdp.ConsumeRandomLengthString(); - std::pair pair(fdp.ConsumeIntegral(), - fdp.ConsumeIntegral()); +void MediaMetricsServiceFuzzer::invokeTimeMachineStorage() { + auto item = CreateItem(); + int32_t i32 = mFdp.ConsumeIntegral(); + int64_t i64 = mFdp.ConsumeIntegral(); + double d = mFdp.ConsumeFloatingPoint(); + std::string str = mFdp.ConsumeRandomLengthString(kMaxBytes); + std::pair pair(mFdp.ConsumeIntegral(), + mFdp.ConsumeIntegral()); (*item).set("i32", i32).set("i64", i64).set("double", d).set("string", str).set("rate", pair); android::mediametrics::TimeMachine timeMachine; @@ -253,124 +202,89 @@ void MediaMetricsServiceFuzzer::invokeTimeMachineStorage(const uint8_t *data, si timeMachine.get("Key.string", &str, -1); } -void MediaMetricsServiceFuzzer::invokeTransactionLog(const uint8_t *data, size_t size) { - FuzzedDataProvider fdp = FuzzedDataProvider(data, size); - - auto item = std::make_shared("Key1"); - (*item) - .set("one", fdp.ConsumeIntegral()) - .set("two", fdp.ConsumeIntegral()) - .setTimestamp(fdp.ConsumeIntegral()); +void MediaMetricsServiceFuzzer::invokeTransactionLog() { + auto item = CreateItem(); android::mediametrics::TransactionLog transactionLog( kLogItemsLowWater, kLogItemsHighWater); // keep at most 2 items transactionLog.size(); transactionLog.put(item); - transactionLog.size(); - - auto item2 = std::make_shared("Key2"); - (*item2) - .set("three", fdp.ConsumeIntegral()) - .set("[Key1]three", fdp.ConsumeIntegral()) - .setTimestamp(fdp.ConsumeIntegral()); - - transactionLog.put(item2); - transactionLog.size(); - - auto item3 = std::make_shared("Key3"); - (*item3) - .set("six", fdp.ConsumeIntegral()) - .set("[Key1]four", fdp.ConsumeIntegral()) // affects Key1 - .set("[Key1]five", fdp.ConsumeIntegral()) // affects key1 - .setTimestamp(fdp.ConsumeIntegral()); - - transactionLog.put(item3); - transactionLog.size(); } -void MediaMetricsServiceFuzzer::invokeAnalyticsAction(const uint8_t *data, size_t size) { - FuzzedDataProvider fdp = FuzzedDataProvider(data, size); - +void MediaMetricsServiceFuzzer::invokeAnalyticsAction() { mediametrics::AnalyticsActions analyticsActions; bool action = false; - while (fdp.remaining_bytes()) { - analyticsActions.addAction( - (fdp.ConsumeRandomLengthString() + std::string(".event")).c_str(), - fdp.ConsumeRandomLengthString(), + analyticsActions.addAction( + (mFdp.ConsumeRandomLengthString(kMaxBytes) + std::string(".event")).c_str(), + mFdp.ConsumeRandomLengthString(kMaxBytes), std::make_shared( - [&](const std::shared_ptr &) { - action = true; - })); - } - - FuzzedDataProvider fdp2 = FuzzedDataProvider(data, size); - size_t apiCount = 0; - while (fdp2.remaining_bytes() && ++apiCount <= kMaxApis) { - // make a test item - auto item = std::make_shared( - fdp2.ConsumeRandomLengthString(kMaxItemLength).c_str()); - (*item).set("event", fdp2.ConsumeRandomLengthString().c_str()); - - // get the actions and execute them - auto actions = analyticsActions.getActionsForItem(item); - for (const auto &action : actions) { - action->operator()(item); + [&](const std::shared_ptr&) { + action = true; + })); + + // make a test item + auto item = CreateItem(); + (*item).set("event", mFdp.ConsumeRandomLengthString(kMaxBytes).c_str()); + + // get the actions and execute them + auto actions = analyticsActions.getActionsForItem(item); + for (const auto& action : actions) { + action->operator()(item); } - } } -void MediaMetricsServiceFuzzer::invokeAudioAnalytics(const uint8_t *data, size_t size) { - FuzzedDataProvider fdp = FuzzedDataProvider(data, size); +void MediaMetricsServiceFuzzer::invokeAudioAnalytics() { + int32_t maxLogLine = mFdp.ConsumeIntegralInRange(0, STATSD_LOG_LINES_MAX); std::shared_ptr statsdLog = - std::make_shared(10); + std::make_shared(maxLogLine); android::mediametrics::AudioAnalytics audioAnalytics{statsdLog}; - while (fdp.remaining_bytes()) { - auto item = std::make_shared(fdp.ConsumeRandomLengthString().c_str()); - int32_t transactionUid = fdp.ConsumeIntegral(); // arbitrary - (*item) - .set(fdp.ConsumeRandomLengthString().c_str(), fdp.ConsumeIntegral()) - .set(fdp.ConsumeRandomLengthString().c_str(), fdp.ConsumeIntegral()) - .set(AMEDIAMETRICS_PROP_ALLOWUID, transactionUid) - .setUid(transactionUid) - .setTimestamp(fdp.ConsumeIntegral()); - audioAnalytics.submit(item, fdp.ConsumeBool()); + auto item = CreateItem(); + Parcel parcel; + item->writeToParcel(&parcel); + parcel.setDataPosition(0); + if (mFdp.ConsumeBool()) { + item->readFromParcel(parcel); } - - audioAnalytics.dump(1000); + audioAnalytics.submit(item, mFdp.ConsumeBool()); } -void MediaMetricsServiceFuzzer::invokeTimedAction(const uint8_t *data, size_t size) { - FuzzedDataProvider fdp = FuzzedDataProvider(data, size); +void MediaMetricsServiceFuzzer::invokeTimedAction() { android::mediametrics::TimedAction timedAction; - - while (fdp.remaining_bytes()) { - timedAction.postIn(std::chrono::seconds(fdp.ConsumeIntegral()), - [this] { ++mValue; }); - timedAction.size(); - } + timedAction.postIn(std::chrono::seconds(mFdp.ConsumeIntegral()), + [this] { ++mValue; }); + timedAction.size(); } -void MediaMetricsServiceFuzzer::process(const uint8_t *data, size_t size) { - invokeStartsWith(data, size); - invokeInstantiate(data, size); - invokePackageInstallerCheck(data, size); - invokeItemManipulation(data, size); - invokeItemExpansion(data, size); - invokeTimeMachineStorage(data, size); - invokeTransactionLog(data, size); - invokeAnalyticsAction(data, size); - invokeAudioAnalytics(data, size); - invokeTimedAction(data, size); +void MediaMetricsServiceFuzzer::process() { + mMediaMetricsService = sp::make(); + + if (mFdp.ConsumeBool()) { + IPCThreadState::self()->restoreCallingIdentity(kPackedCallingUid); + } else { + IPCThreadState::self()->restoreCallingIdentity(mFdp.ConsumeIntegral()); + } + while (mFdp.remaining_bytes()) { + auto invokeAPIs = mFdp.PickValueInArray>({ + [&]() { invokeStartsWith(); }, + [&]() { invokeInstantiate(); }, + [&]() { invokePackageInstallerCheck(); }, + [&]() { invokeTimeMachineStorage(); }, + [&]() { invokeTransactionLog(); }, + [&]() { invokeAudioAnalytics(); }, + [&]() { invokeTimedAction(); }, + }); + invokeAPIs(); + } } -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { if (size < 1) { return 0; } - MediaMetricsServiceFuzzer mediaMetricsServiceFuzzer; - mediaMetricsServiceFuzzer.process(data, size); + MediaMetricsServiceFuzzer mediaMetricsServiceFuzzer(data, size); + mediaMetricsServiceFuzzer.process(); return 0; }