From 84f5c0f337c9ea87c9b4e0f69bc86586cd3700ac Mon Sep 17 00:00:00 2001 From: Corbin Souffrant Date: Fri, 26 Jun 2020 00:42:43 -0700 Subject: Adding multiple fuzzers for libbinder. Adding fuzzers in libbinder for Binder, BpBinder, MemoryHeapBase, ParcelBlob, PersistableBundle, Stability, Status, and TextOutput. These follow the same framework style. Test: Tested on a Pixel3a device for 500k iterations each. Signed-off-by: Corbin Souffrant Change-Id: I53b85570a3abde854b01ffefc2739b79b39af7e2 --- PREUPLOAD.cfg | 1 + libs/binder/tests/fuzzers/Android.bp | 66 ++++++++ libs/binder/tests/fuzzers/BinderFuzz.cpp | 46 ++++++ libs/binder/tests/fuzzers/BinderFuzzFunctions.h | 70 ++++++++ libs/binder/tests/fuzzers/BpBinderFuzz.cpp | 54 ++++++ libs/binder/tests/fuzzers/BpBinderFuzzFunctions.h | 110 +++++++++++++ libs/binder/tests/fuzzers/IBinderFuzzFunctions.h | 87 ++++++++++ .../binder/tests/fuzzers/PersistableBundleFuzz.cpp | 37 +++++ .../tests/fuzzers/PersistableBundleFuzzFunctions.h | 183 +++++++++++++++++++++ libs/binder/tests/fuzzers/StabilityFuzz.cpp | 33 ++++ libs/binder/tests/fuzzers/StabilityFuzzFunctions.h | 67 ++++++++ libs/binder/tests/fuzzers/StatusFuzz.cpp | 47 ++++++ libs/binder/tests/fuzzers/StatusFuzzFunctions.h | 91 ++++++++++ libs/binder/tests/fuzzers/TextOutputFuzz.cpp | 60 +++++++ libs/binder/tests/fuzzers/commonFuzzHelpers.h | 41 +++++ 15 files changed, 993 insertions(+) create mode 100644 libs/binder/tests/fuzzers/Android.bp create mode 100644 libs/binder/tests/fuzzers/BinderFuzz.cpp create mode 100644 libs/binder/tests/fuzzers/BinderFuzzFunctions.h create mode 100644 libs/binder/tests/fuzzers/BpBinderFuzz.cpp create mode 100644 libs/binder/tests/fuzzers/BpBinderFuzzFunctions.h create mode 100644 libs/binder/tests/fuzzers/IBinderFuzzFunctions.h create mode 100644 libs/binder/tests/fuzzers/PersistableBundleFuzz.cpp create mode 100644 libs/binder/tests/fuzzers/PersistableBundleFuzzFunctions.h create mode 100644 libs/binder/tests/fuzzers/StabilityFuzz.cpp create mode 100644 libs/binder/tests/fuzzers/StabilityFuzzFunctions.h create mode 100644 libs/binder/tests/fuzzers/StatusFuzz.cpp create mode 100644 libs/binder/tests/fuzzers/StatusFuzzFunctions.h create mode 100644 libs/binder/tests/fuzzers/TextOutputFuzz.cpp create mode 100644 libs/binder/tests/fuzzers/commonFuzzHelpers.h diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg index 0473bb833e..9cab9b4c41 100644 --- a/PREUPLOAD.cfg +++ b/PREUPLOAD.cfg @@ -8,6 +8,7 @@ clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp include/input/ libs/binder/fuzzer/ libs/binder/ndk/ + libs/binder/tests/fuzzers/ libs/binderthreadstate/ libs/graphicsenv/ libs/gui/ diff --git a/libs/binder/tests/fuzzers/Android.bp b/libs/binder/tests/fuzzers/Android.bp new file mode 100644 index 0000000000..46379fc629 --- /dev/null +++ b/libs/binder/tests/fuzzers/Android.bp @@ -0,0 +1,66 @@ +// +// Copyright (C) 2020 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +cc_defaults { + name: "binder_fuzz_defaults", + host_supported: true, + cflags: [ + "-Wall", + "-Werror", + ], + shared_libs: [ + "libbinder", + "libutils", + "libbase", + ], +} + +cc_fuzz { + name: "binder_binderFuzz", + defaults: ["binder_fuzz_defaults"], + srcs: ["BinderFuzz.cpp"], +} + +cc_fuzz { + name: "binder_bpBinderFuzz", + defaults: ["binder_fuzz_defaults"], + host_supported: false, + srcs: ["BpBinderFuzz.cpp"], +} + +cc_fuzz { + name: "binder_persistableBundleFuzz", + defaults: ["binder_fuzz_defaults"], + srcs: ["PersistableBundleFuzz.cpp"], +} + +cc_fuzz { + name: "binder_stabilityFuzz", + defaults: ["binder_fuzz_defaults"], + srcs: ["StabilityFuzz.cpp"], +} + +cc_fuzz { + name: "binder_statusFuzz", + defaults: ["binder_fuzz_defaults"], + srcs: ["StatusFuzz.cpp"], +} + +cc_fuzz { + name: "binder_textOutputFuzz", + defaults: ["binder_fuzz_defaults"], + srcs: ["TextOutputFuzz.cpp"], +} diff --git a/libs/binder/tests/fuzzers/BinderFuzz.cpp b/libs/binder/tests/fuzzers/BinderFuzz.cpp new file mode 100644 index 0000000000..1e5d80a205 --- /dev/null +++ b/libs/binder/tests/fuzzers/BinderFuzz.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include + +namespace android { + +// Fuzzer entry point. +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + FuzzedDataProvider fdp(data, size); + sp bbinder = new BBinder(); + + // To prevent memory from running out from calling too many add item operations. + const uint32_t MAX_RUNS = 2048; + uint32_t count = 0; + + while (fdp.remaining_bytes() > 0 && count++ < MAX_RUNS) { + if (fdp.ConsumeBool()) { + callArbitraryFunction(&fdp, gBBinderOperations, bbinder); + } else { + callArbitraryFunction(&fdp, gIBinderOperations, + reinterpret_cast(bbinder.get())); + } + } + + return 0; +} +} // namespace android diff --git a/libs/binder/tests/fuzzers/BinderFuzzFunctions.h b/libs/binder/tests/fuzzers/BinderFuzzFunctions.h new file mode 100644 index 0000000000..9ac65bb2c1 --- /dev/null +++ b/libs/binder/tests/fuzzers/BinderFuzzFunctions.h @@ -0,0 +1,70 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +#include +#include +#include +#include +#include + +namespace android { + +/* This is a vector of lambda functions the fuzzer will pull from. + * This is done so new functions can be added to the fuzzer easily + * without requiring modifications to the main fuzzer file. This also + * allows multiple fuzzers to include this file, if functionality is needed. + */ +static const std::vector&)>> + gBBinderOperations = {[](FuzzedDataProvider*, const sp& bbinder) -> void { + bbinder->isRequestingSid(); + }, + [](FuzzedDataProvider* fdp, const sp& bbinder) -> void { + bool request_sid = fdp->ConsumeBool(); + bbinder->setRequestingSid(request_sid); + }, + [](FuzzedDataProvider*, const sp& bbinder) -> void { + bbinder->getExtension(); + }, + [](FuzzedDataProvider*, const sp& bbinder) -> void { + static IBinder* extension = nullptr; + bbinder->setExtension(extension); + }, + [](FuzzedDataProvider* fdp, const sp& bbinder) -> void { + int priority; + int policy = fdp->ConsumeIntegralInRange(0, 2); + if (policy == 0) { + priority = fdp->ConsumeIntegralInRange(-20, 19); + } else { + priority = fdp->ConsumeIntegralInRange(1, 99); + } + bbinder->setMinSchedulerPolicy(policy, priority); + }, + [](FuzzedDataProvider*, const sp& bbinder) -> void { + bbinder->getMinSchedulerPolicy(); + }, + [](FuzzedDataProvider*, const sp& bbinder) -> void { + bbinder->getMinSchedulerPriority(); + }, + [](FuzzedDataProvider*, const sp& bbinder) -> void { + bbinder->getDebugPid(); + }}; + +} // namespace android diff --git a/libs/binder/tests/fuzzers/BpBinderFuzz.cpp b/libs/binder/tests/fuzzers/BpBinderFuzz.cpp new file mode 100644 index 0000000000..c50279b13d --- /dev/null +++ b/libs/binder/tests/fuzzers/BpBinderFuzz.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include +#include + +namespace android { + +// Fuzzer entry point. +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + FuzzedDataProvider fdp(data, size); + + // TODO: In the future it would be more effective to fork a new process and then pass a BBinder + // to your process. Right now this is not implemented because it would involved fuzzing IPC on a + // forked process, and libfuzzer will not be able to handle code coverage. This would lead to + // crashes that are not easy to diagnose. + int32_t handle = fdp.ConsumeIntegralInRange(0, 1024); + sp bpbinder = BpBinder::create(handle); + if (bpbinder == nullptr) return 0; + + // To prevent memory from running out from calling too many add item operations. + const uint32_t MAX_RUNS = 2048; + uint32_t count = 0; + sp s_recipient = new FuzzDeathRecipient(); + + while (fdp.remaining_bytes() > 0 && count++ < MAX_RUNS) { + if (fdp.ConsumeBool()) { + callArbitraryFunction(&fdp, gBPBinderOperations, bpbinder, s_recipient); + } else { + callArbitraryFunction(&fdp, gIBinderOperations, bpbinder.get()); + } + } + + return 0; +} +} // namespace android diff --git a/libs/binder/tests/fuzzers/BpBinderFuzzFunctions.h b/libs/binder/tests/fuzzers/BpBinderFuzzFunctions.h new file mode 100644 index 0000000000..c685b41026 --- /dev/null +++ b/libs/binder/tests/fuzzers/BpBinderFuzzFunctions.h @@ -0,0 +1,110 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +namespace android { + +// Static variable to reference so we don't consume a bunch of memory to link and +// unlink DeathRecipients. +static int8_t kBpBinderCookie = 0; + +/* This is a vector of lambda functions the fuzzer will pull from. + * This is done so new functions can be added to the fuzzer easily + * without requiring modifications to the main fuzzer file. This also + * allows multiple fuzzers to include this file, if functionality is needed. + */ +static const std::vector&, + const sp&)>> + gBPBinderOperations = + {[](FuzzedDataProvider*, const sp& bpbinder, + const sp&) -> void { bpbinder->handle(); }, + [](FuzzedDataProvider* fdp, const sp& bpbinder, + const sp& s_recipient) -> void { + // Clean up possible leftover memory. + wp outRecipient(nullptr); + bpbinder->sendObituary(); + bpbinder->unlinkToDeath(nullptr, reinterpret_cast(&kBpBinderCookie), 0, + &outRecipient); + + uint32_t flags = fdp->ConsumeIntegral(); + kBpBinderCookie = fdp->ConsumeIntegral(); + bpbinder->linkToDeath(s_recipient.get(), + reinterpret_cast(&kBpBinderCookie), flags); + }, + [](FuzzedDataProvider* fdp, const sp& bpbinder, + const sp&) -> void { + wp out_recipient(nullptr); + uint32_t flags = fdp->ConsumeIntegral(); + int8_t random_cookie = fdp->ConsumeIntegral(); + bpbinder->unlinkToDeath(nullptr, reinterpret_cast(&random_cookie), + flags, &out_recipient); + }, + [](FuzzedDataProvider*, const sp& bpbinder, + const sp&) -> void { bpbinder->remoteBinder(); }, + [](FuzzedDataProvider*, const sp& bpbinder, + const sp&) -> void { bpbinder->sendObituary(); }, + [](FuzzedDataProvider* fdp, const sp& bpbinder, + const sp&) -> void { + uint32_t uid = fdp->ConsumeIntegral(); + bpbinder->getBinderProxyCount(uid); + }, + [](FuzzedDataProvider*, const sp& bpbinder, + const sp&) -> void { bpbinder->enableCountByUid(); }, + [](FuzzedDataProvider*, const sp& bpbinder, + const sp&) -> void { bpbinder->disableCountByUid(); }, + [](FuzzedDataProvider*, const sp& bpbinder, + const sp&) -> void { + Vector uids; + Vector counts; + bpbinder->getCountByUid(uids, counts); + }, + [](FuzzedDataProvider* fdp, const sp& bpbinder, + const sp&) -> void { + bool enable = fdp->ConsumeBool(); + bpbinder->setCountByUidEnabled(enable); + }, + [](FuzzedDataProvider*, const sp& bpbinder, + const sp&) -> void { + binder_proxy_limit_callback cb = binder_proxy_limit_callback(); + bpbinder->setLimitCallback(cb); + }, + [](FuzzedDataProvider* fdp, const sp& bpbinder, + const sp&) -> void { + int high = fdp->ConsumeIntegral(); + int low = fdp->ConsumeIntegral(); + bpbinder->setBinderProxyCountWatermarks(high, low); + }}; + +} // namespace android diff --git a/libs/binder/tests/fuzzers/IBinderFuzzFunctions.h b/libs/binder/tests/fuzzers/IBinderFuzzFunctions.h new file mode 100644 index 0000000000..626b7585f7 --- /dev/null +++ b/libs/binder/tests/fuzzers/IBinderFuzzFunctions.h @@ -0,0 +1,87 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { + +class FuzzDeathRecipient : public IBinder::DeathRecipient { +private: + virtual void binderDied(const wp& who) { (void)who; }; +}; + +// Allow objects to be attached that aren't stack locals +static uint32_t objectID = 0; +static uint32_t object = 0; +static uint32_t cleanup_cookie = 0; + +/* This is a vector of lambda functions the fuzzer will pull from. + * This is done so new functions can be added to the fuzzer easily + * without requiring modifications to the main fuzzer file. This also + * allows multiple fuzzers to include this file, if functionality is needed. + */ +static const std::vector> gIBinderOperations = + {[](FuzzedDataProvider*, IBinder* ibinder) -> void { ibinder->getInterfaceDescriptor(); }, + [](FuzzedDataProvider*, IBinder* ibinder) -> void { ibinder->isBinderAlive(); }, + [](FuzzedDataProvider*, IBinder* ibinder) -> void { ibinder->pingBinder(); }, + [](FuzzedDataProvider* fdp, IBinder* ibinder) -> void { + int fd = STDOUT_FILENO; + std::string rand_str = fdp->ConsumeRandomLengthString(fdp->remaining_bytes()); + Vector args; + args.push(String16(rand_str.c_str())); + ibinder->dump(fd, args); + }, + [](FuzzedDataProvider* fdp, IBinder* ibinder) -> void { + objectID = fdp->ConsumeIntegral(); + object = fdp->ConsumeIntegral(); + cleanup_cookie = fdp->ConsumeIntegral(); + IBinder::object_cleanup_func func = IBinder::object_cleanup_func(); + ibinder->attachObject(fdp->ConsumeBool() ? reinterpret_cast(&objectID) + : nullptr, + fdp->ConsumeBool() ? reinterpret_cast(&object) : nullptr, + fdp->ConsumeBool() ? reinterpret_cast(&cleanup_cookie) + : nullptr, + func); + }, + [](FuzzedDataProvider* fdp, IBinder* ibinder) -> void { + uint32_t id = fdp->ConsumeIntegral(); + ibinder->findObject(reinterpret_cast(&id)); + }, + [](FuzzedDataProvider* fdp, IBinder* ibinder) -> void { + uint32_t id = fdp->ConsumeIntegral(); + ibinder->detachObject(reinterpret_cast(&id)); + }, + [](FuzzedDataProvider* fdp, IBinder* ibinder) -> void { + uint32_t code = fdp->ConsumeIntegral(); + Parcel p_data; + Parcel reply; + uint32_t flags = fdp->ConsumeIntegral(); + ibinder->transact(code, p_data, &reply, flags); + }}; +} // namespace android diff --git a/libs/binder/tests/fuzzers/PersistableBundleFuzz.cpp b/libs/binder/tests/fuzzers/PersistableBundleFuzz.cpp new file mode 100644 index 0000000000..4843c46545 --- /dev/null +++ b/libs/binder/tests/fuzzers/PersistableBundleFuzz.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +namespace android { +// Fuzzer entry point. +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + FuzzedDataProvider fdp(data, size); + std::shared_ptr p_bundle(new os::PersistableBundle()); + + while (fdp.remaining_bytes() > 0) { + String16 key(fdp.ConsumeRandomLengthString(fdp.remaining_bytes()).c_str()); + callArbitraryFunction(&fdp, gPersistableBundleOperations, p_bundle, &key); + } + + return 0; +} + +} // namespace android diff --git a/libs/binder/tests/fuzzers/PersistableBundleFuzzFunctions.h b/libs/binder/tests/fuzzers/PersistableBundleFuzzFunctions.h new file mode 100644 index 0000000000..820e9e8c31 --- /dev/null +++ b/libs/binder/tests/fuzzers/PersistableBundleFuzzFunctions.h @@ -0,0 +1,183 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { + +/* This is a vector of lambda functions the fuzzer will pull from. + * This is done so new functions can be added to the fuzzer easily + * without requiring modifications to the main fuzzer file. This also + * allows multiple fuzzers to include this file, if functionality is needed. + */ +static const std::vector const&, String16*)>> + gPersistableBundleOperations = + {[](FuzzedDataProvider*, std::shared_ptr const& p_bundle, + String16*) -> void { p_bundle->empty(); }, + [](FuzzedDataProvider*, std::shared_ptr const& p_bundle, + String16*) -> void { + Parcel parcel; + p_bundle->writeToParcel(&parcel); + }, + [](FuzzedDataProvider* fdp, std::shared_ptr const& p_bundle, + String16*) -> void { + Parcel parcel; + std::vector buf = fdp->ConsumeBytes( + fdp->ConsumeIntegralInRange(0, fdp->remaining_bytes() - 1)); + parcel.write(buf.data(), buf.size()); + p_bundle->readFromParcel(&parcel); + }, + [](FuzzedDataProvider*, std::shared_ptr const& p_bundle, + String16*) -> void { p_bundle->size(); }, + [](FuzzedDataProvider*, std::shared_ptr const& p_bundle, + String16* key) -> void { p_bundle->erase(*key); }, + [](FuzzedDataProvider* fdp, std::shared_ptr const& p_bundle, + String16* key) -> void { + bool value = fdp->ConsumeBool(); + p_bundle->putBoolean(*key, value); + }, + [](FuzzedDataProvider* fdp, std::shared_ptr const& p_bundle, + String16* key) -> void { + int32_t value = fdp->ConsumeIntegral(); + p_bundle->putInt(*key, value); + }, + [](FuzzedDataProvider*, std::shared_ptr const& p_bundle, + String16* key) -> void { + os::PersistableBundle value = os::PersistableBundle(); + p_bundle->putPersistableBundle(*key, value); + }, + [](FuzzedDataProvider*, std::shared_ptr const& p_bundle, + String16* key) -> void { + std::vector value; + p_bundle->putStringVector(*key, value); + }, + [](FuzzedDataProvider*, std::shared_ptr const& p_bundle, + String16* key) -> void { + std::vector value; + p_bundle->putDoubleVector(*key, value); + }, + [](FuzzedDataProvider*, std::shared_ptr const& p_bundle, + String16* key) -> void { + std::vector value; + p_bundle->putLongVector(*key, value); + }, + [](FuzzedDataProvider*, std::shared_ptr const& p_bundle, + String16* key) -> void { + std::vector value; + p_bundle->putIntVector(*key, value); + }, + [](FuzzedDataProvider*, std::shared_ptr const& p_bundle, + String16* key) -> void { + std::vector value; + p_bundle->putBooleanVector(*key, value); + }, + [](FuzzedDataProvider* fdp, std::shared_ptr const& p_bundle, + String16* key) -> void { + String16 value(fdp->ConsumeRandomLengthString(fdp->remaining_bytes()).c_str()); + p_bundle->putString(*key, value); + }, + [](FuzzedDataProvider* fdp, std::shared_ptr const& p_bundle, + String16* key) -> void { + int64_t value = fdp->ConsumeIntegral(); + p_bundle->putLong(*key, value); + }, + [](FuzzedDataProvider* fdp, std::shared_ptr const& p_bundle, + String16* key) -> void { + double value = fdp->ConsumeFloatingPoint(); + p_bundle->putDouble(*key, value); + }, + [](FuzzedDataProvider*, std::shared_ptr const& p_bundle, + String16* key) -> void { + bool out; + p_bundle->getBoolean(*key, &out); + }, + [](FuzzedDataProvider*, std::shared_ptr const& p_bundle, + String16* key) -> void { + os::PersistableBundle out; + p_bundle->getPersistableBundle(*key, &out); + }, + [](FuzzedDataProvider*, std::shared_ptr const& p_bundle, + String16* key) -> void { + std::vector out; + p_bundle->getStringVector(*key, &out); + }, + [](FuzzedDataProvider*, std::shared_ptr const& p_bundle, + String16* key) -> void { + std::vector out; + p_bundle->getDoubleVector(*key, &out); + }, + [](FuzzedDataProvider*, std::shared_ptr const& p_bundle, + String16* key) -> void { + std::vector out; + p_bundle->getLongVector(*key, &out); + }, + [](FuzzedDataProvider*, std::shared_ptr const& p_bundle, + String16* key) -> void { + std::vector out; + p_bundle->getIntVector(*key, &out); + }, + [](FuzzedDataProvider*, std::shared_ptr const& p_bundle, + String16* key) -> void { + std::vector out; + p_bundle->getBooleanVector(*key, &out); + }, + [](FuzzedDataProvider*, std::shared_ptr const& p_bundle, + String16* key) -> void { + String16 out; + p_bundle->getString(*key, &out); + }, + [](FuzzedDataProvider*, std::shared_ptr const& p_bundle, + String16* key) -> void { + double out; + p_bundle->getDouble(*key, &out); + }, + [](FuzzedDataProvider*, std::shared_ptr const& p_bundle, + String16* key) -> void { + int64_t out; + p_bundle->getLong(*key, &out); + }, + [](FuzzedDataProvider*, std::shared_ptr const& p_bundle, + String16* key) -> void { + int32_t out; + p_bundle->getInt(*key, &out); + }, + [](FuzzedDataProvider*, std::shared_ptr const& p_bundle, + String16*) -> void { + p_bundle->getBooleanKeys(); + p_bundle->getIntKeys(); + p_bundle->getLongKeys(); + p_bundle->getDoubleKeys(); + p_bundle->getStringKeys(); + p_bundle->getBooleanVectorKeys(); + p_bundle->getIntVectorKeys(); + p_bundle->getLongVectorKeys(); + p_bundle->getDoubleVectorKeys(); + p_bundle->getStringVectorKeys(); + p_bundle->getPersistableBundleKeys(); + }}; + +} // namespace android diff --git a/libs/binder/tests/fuzzers/StabilityFuzz.cpp b/libs/binder/tests/fuzzers/StabilityFuzz.cpp new file mode 100644 index 0000000000..8ad9b44f65 --- /dev/null +++ b/libs/binder/tests/fuzzers/StabilityFuzz.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +// Fuzzer entry point. +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + // Init our wrapper + FuzzedDataProvider dataProvider(data, size); + android::sp bbinder = new android::BBinder(); + + // Call some functions + while (dataProvider.remaining_bytes() > 0) { + callArbitraryFunction(&dataProvider, gStabilityOperations, bbinder); + } + + return 0; +} diff --git a/libs/binder/tests/fuzzers/StabilityFuzzFunctions.h b/libs/binder/tests/fuzzers/StabilityFuzzFunctions.h new file mode 100644 index 0000000000..8b4ed702af --- /dev/null +++ b/libs/binder/tests/fuzzers/StabilityFuzzFunctions.h @@ -0,0 +1,67 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include + +#define STABILITY_MAX_TAG_LENGTH 2048 +static bool marked = false; + +/* This is a vector of lambda functions the fuzzer will pull from. + * This is done so new functions can be added to the fuzzer easily + * without requiring modifications to the main fuzzer file. This also + * allows multiple fuzzers to include this file, if functionality is needed. + */ +static const std::vector< + std::function const&)>> + gStabilityOperations = { + // markCompilationUnit(IBinder* binder) + [](FuzzedDataProvider*, android::sp const& bbinder) -> void { + if (!marked) { + android::internal::Stability::markCompilationUnit(bbinder.get()); + marked = true; + } + }, + + // markVintf(IBinder* binder) + [](FuzzedDataProvider*, android::sp const& bbinder) -> void { + if (!marked) { + android::internal::Stability::markVintf(bbinder.get()); + marked = true; + } + }, + + // debugLogStability(const std::string& tag, const sp& binder) + [](FuzzedDataProvider* fdp, android::sp const& bbinder) -> void { + std::string tag = fdp->ConsumeRandomLengthString(STABILITY_MAX_TAG_LENGTH); + android::internal::Stability::debugLogStability(tag, bbinder); + }, + + // markVndk(IBinder* binder) + [](FuzzedDataProvider*, android::sp const& bbinder) -> void { + if (!marked) { + android::internal::Stability::markVndk(bbinder.get()); + marked = true; + } + }, + + // requiresVintfDeclaration(const sp& binder) + [](FuzzedDataProvider*, android::sp const& bbinder) -> void { + android::internal::Stability::requiresVintfDeclaration(bbinder); + }}; diff --git a/libs/binder/tests/fuzzers/StatusFuzz.cpp b/libs/binder/tests/fuzzers/StatusFuzz.cpp new file mode 100644 index 0000000000..4f6ad6f707 --- /dev/null +++ b/libs/binder/tests/fuzzers/StatusFuzz.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { +// Fuzzer entry point. +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + FuzzedDataProvider fdp(data, size); + + int32_t exceptionCode = fdp.ConsumeIntegral(); + std::string message_str = fdp.ConsumeRandomLengthString(fdp.remaining_bytes()); + String8 message(message_str.c_str()); + + Parcel parcel; + std::vector buf = fdp.ConsumeBytes( + fdp.ConsumeIntegralInRange(0, fdp.remaining_bytes() - 1)); + parcel.write(buf.data(), buf.size()); + binder::Status status = binder::Status::fromExceptionCode(exceptionCode, message); + + while (fdp.remaining_bytes() > 0) { + callArbitraryFunction(&fdp, gStatusOperations, &status, &parcel); + } + return 0; +} +} // namespace android diff --git a/libs/binder/tests/fuzzers/StatusFuzzFunctions.h b/libs/binder/tests/fuzzers/StatusFuzzFunctions.h new file mode 100644 index 0000000000..bc8d17a34f --- /dev/null +++ b/libs/binder/tests/fuzzers/StatusFuzzFunctions.h @@ -0,0 +1,91 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace android { +/* This is a vector of lambda functions the fuzzer will pull from. + * This is done so new functions can be added to the fuzzer easily + * without requiring modifications to the main fuzzer file. This also + * allows multiple fuzzers to include this file, if functionality is needed. + */ +static const std::vector> + gStatusOperations = { + [](FuzzedDataProvider*, binder::Status* status, Parcel* parcel) -> void { + parcel->setDataPosition(0); + status->readFromParcel(*parcel); + }, + [](FuzzedDataProvider*, binder::Status* status, Parcel* parcel) -> void { + status->writeToParcel(parcel); + }, + [](FuzzedDataProvider* fdp, binder::Status* status, Parcel*) -> void { + std::string message_str = + fdp->ConsumeRandomLengthString(fdp->remaining_bytes()); + String8 message(message_str.c_str()); + status->setServiceSpecificError(fdp->ConsumeIntegral(), message); + }, + [](FuzzedDataProvider* fdp, binder::Status* status, Parcel*) -> void { + std::string message_str = + fdp->ConsumeRandomLengthString(fdp->remaining_bytes()); + String8 message(message_str.c_str()); + status->setException(fdp->ConsumeIntegral(), message); + }, + [](FuzzedDataProvider*, binder::Status* status, Parcel*) -> void { status->ok(); }, + [](FuzzedDataProvider* fdp, binder::Status* status, Parcel*) -> void { + std::string message_str = + fdp->ConsumeRandomLengthString(fdp->remaining_bytes()); + String8 message(message_str.c_str()); + *status = binder::Status::fromExceptionCode(fdp->ConsumeIntegral(), + message); + }, + [](FuzzedDataProvider* fdp, binder::Status* status, Parcel*) -> void { + *status = binder::Status::fromServiceSpecificError( + fdp->ConsumeIntegral()); + }, + [](FuzzedDataProvider* fdp, binder::Status*, Parcel*) -> void { + binder::Status::exceptionToString(fdp->ConsumeIntegral()); + }, + [](FuzzedDataProvider* fdp, binder::Status* status, Parcel*) -> void { + std::string message_str = + fdp->ConsumeRandomLengthString(fdp->remaining_bytes()); + String8 message(message_str.c_str()); + *status = binder::Status::fromServiceSpecificError(fdp->ConsumeIntegral< + int32_t>(), + message); + }, + [](FuzzedDataProvider* fdp, binder::Status* status, Parcel*) -> void { + *status = binder::Status::fromStatusT(fdp->ConsumeIntegral()); + }, + [](FuzzedDataProvider* fdp, binder::Status* status, Parcel*) -> void { + status->setFromStatusT(fdp->ConsumeIntegral()); + }, + [](FuzzedDataProvider*, binder::Status* status, Parcel*) -> void { + std::stringstream ss; + ss << *status; + }, +}; + +} // namespace android diff --git a/libs/binder/tests/fuzzers/TextOutputFuzz.cpp b/libs/binder/tests/fuzzers/TextOutputFuzz.cpp new file mode 100644 index 0000000000..c9500205df --- /dev/null +++ b/libs/binder/tests/fuzzers/TextOutputFuzz.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include "android-base/file.h" +#include "android-base/test_utils.h" + +#include +#include +#include +#include +#include + +// Fuzzer for the TextOutput class. These were lifted from the existing +// test suite. +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + FuzzedDataProvider fdp(data, size); + CapturedStderr cap; + + while (fdp.remaining_bytes() > 1) { + switch (fdp.ConsumeIntegral() % 3) { + case 0: { + std::string input = fdp.ConsumeBytesAsString( + fdp.ConsumeIntegralInRange(0, fdp.remaining_bytes())); + android::aerr << input << android::endl; + break; + } + case 1: { + std::string str = fdp.ConsumeRandomLengthString(fdp.remaining_bytes()); + android::HexDump input(str.c_str(), sizeof(str.c_str())); + android::aerr << input << android::endl; + break; + } + case 2: { + android::TypeCode input(fdp.ConsumeIntegral()); + android::aerr << input << android::endl; + } + } + } + cap.Stop(); + + return 0; +} diff --git a/libs/binder/tests/fuzzers/commonFuzzHelpers.h b/libs/binder/tests/fuzzers/commonFuzzHelpers.h new file mode 100644 index 0000000000..d58d9b6d84 --- /dev/null +++ b/libs/binder/tests/fuzzers/commonFuzzHelpers.h @@ -0,0 +1,41 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +// Calls a function from the ops_vector +template +void callArbitraryFunction(F* fdp, T const& ops_vector, Types... args) { + // Choose which function we'll be calling + uint8_t function_id = fdp->template ConsumeIntegralInRange(0, ops_vector.size() - 1); + + // Call the function we've chosen + ops_vector[function_id](fdp, args...); +} + +template +T getArbitraryVectorElement(FuzzedDataProvider* fdp, std::vector const& vect, bool allow_null) { + // If we're allowing null, give it a 50:50 shot at returning a nullptr + if (vect.empty() || (allow_null && fdp->ConsumeBool())) { + return nullptr; + } + + // Otherwise, return an element from our vector + return vect.at(fdp->ConsumeIntegralInRange(0, vect.size() - 1)); +} -- cgit v1.2.3-59-g8ed1b