diff options
| -rw-r--r-- | libs/binder/fuzzer/main.cpp | 110 | ||||
| -rw-r--r-- | libs/binder/parcel_fuzzer/Android.bp (renamed from libs/binder/fuzzer/Android.bp) | 2 | ||||
| -rw-r--r-- | libs/binder/parcel_fuzzer/binder.cpp (renamed from libs/binder/fuzzer/binder.cpp) | 0 | ||||
| -rw-r--r-- | libs/binder/parcel_fuzzer/binder.h (renamed from libs/binder/fuzzer/binder.h) | 1 | ||||
| -rw-r--r-- | libs/binder/parcel_fuzzer/binder_ndk.cpp (renamed from libs/binder/fuzzer/binder_ndk.cpp) | 0 | ||||
| -rw-r--r-- | libs/binder/parcel_fuzzer/binder_ndk.h (renamed from libs/binder/fuzzer/binder_ndk.h) | 4 | ||||
| -rw-r--r-- | libs/binder/parcel_fuzzer/hwbinder.cpp (renamed from libs/binder/fuzzer/hwbinder.cpp) | 0 | ||||
| -rw-r--r-- | libs/binder/parcel_fuzzer/hwbinder.h (renamed from libs/binder/fuzzer/hwbinder.h) | 1 | ||||
| -rw-r--r-- | libs/binder/parcel_fuzzer/main.cpp | 101 | ||||
| -rw-r--r-- | libs/binder/parcel_fuzzer/parcel_fuzzer.h (renamed from libs/binder/fuzzer/parcel_fuzzer.h) | 1 | ||||
| -rw-r--r-- | libs/binder/parcel_fuzzer/random_fd.cpp | 35 | ||||
| -rw-r--r-- | libs/binder/parcel_fuzzer/random_fd.h | 27 | ||||
| -rw-r--r-- | libs/binder/parcel_fuzzer/random_parcel.cpp | 83 | ||||
| -rw-r--r-- | libs/binder/parcel_fuzzer/random_parcel.h | 27 | ||||
| -rw-r--r-- | libs/binder/parcel_fuzzer/util.cpp (renamed from libs/binder/fuzzer/util.cpp) | 0 | ||||
| -rw-r--r-- | libs/binder/parcel_fuzzer/util.h (renamed from libs/binder/fuzzer/util.h) | 1 |
16 files changed, 283 insertions, 110 deletions
diff --git a/libs/binder/fuzzer/main.cpp b/libs/binder/fuzzer/main.cpp deleted file mode 100644 index 6657edb46d..0000000000 --- a/libs/binder/fuzzer/main.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2019 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. - */ -#define FUZZ_LOG_TAG "main" - -#include "binder.h" -#include "binder_ndk.h" -#include "hwbinder.h" -#include "util.h" - -#include <android-base/logging.h> - -#include <cstdlib> -#include <ctime> - -template <typename P> -void doFuzz( - const std::vector<ParcelRead<P>>& reads, - const std::vector<uint8_t>& input, - const std::vector<uint8_t>& instructions) { - - P p; - p.setData(input.data(), input.size()); - - // since we are only using a byte to index - CHECK(reads.size() <= 255) << reads.size(); - - for (size_t i = 0; i < instructions.size() - 1; i += 2) { - uint8_t a = instructions[i]; - uint8_t readIdx = a % reads.size(); - - uint8_t b = instructions[i + 1]; - - FUZZ_LOG() << "Instruction: " << (i / 2) + 1 << "/" << instructions.size() / 2 - << " cmd: " << static_cast<size_t>(a) << " (" << static_cast<size_t>(readIdx) - << ") arg: " << static_cast<size_t>(b) << " size: " << p.dataSize() - << " avail: " << p.dataAvail() << " pos: " << p.dataPosition() - << " cap: " << p.dataCapacity(); - - reads[readIdx](p, b); - } -} - -void fuzz(uint8_t options, const std::vector<uint8_t>& input, const std::vector<uint8_t>& instructions) { - uint8_t parcelType = options & 0x3; - - switch (parcelType) { - case 0x0: - doFuzz<::android::hardware::Parcel>(HWBINDER_PARCEL_READ_FUNCTIONS, input, - instructions); - break; - case 0x1: - doFuzz<::android::Parcel>(BINDER_PARCEL_READ_FUNCTIONS, input, instructions); - break; - case 0x2: - doFuzz<NdkParcelAdapter>(BINDER_NDK_PARCEL_READ_FUNCTIONS, input, instructions); - break; - case 0x3: - /*reserved for future use*/ - break; - default: - LOG_ALWAYS_FATAL("unknown parcel type %d", static_cast<int>(parcelType)); - } -} - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - if (size <= 1) return 0; // no use - - // avoid timeouts, see b/142617274, b/142473153 - if (size > 50000) return 0; - - uint8_t options = *data; - data++; - size--; - - // TODO: generate 'objects' data - - // data to fill out parcel - size_t inputLen = size / 2; - std::vector<uint8_t> input(data, data + inputLen); - data += inputLen; - size -= inputLen; - - // data to use to determine what to do - size_t instructionLen = size; - std::vector<uint8_t> instructions(data, data + instructionLen); - data += instructionLen; - size -= instructionLen; - - CHECK(size == 0) << "size: " << size; - - FUZZ_LOG() << "options: " << (int)options << " inputLen: " << inputLen << " instructionLen: " << instructionLen; - FUZZ_LOG() << "input: " << hexString(input); - FUZZ_LOG() << "instructions: " << hexString(instructions); - - fuzz(options, input, instructions); - return 0; -} diff --git a/libs/binder/fuzzer/Android.bp b/libs/binder/parcel_fuzzer/Android.bp index d2b4d52acc..1a6789833c 100644 --- a/libs/binder/fuzzer/Android.bp +++ b/libs/binder/parcel_fuzzer/Android.bp @@ -12,6 +12,8 @@ cc_fuzz { "binder_ndk.cpp", "hwbinder.cpp", "main.cpp", + "random_fd.cpp", + "random_parcel.cpp", "util.cpp", ], static_libs: [ diff --git a/libs/binder/fuzzer/binder.cpp b/libs/binder/parcel_fuzzer/binder.cpp index c2d4a3f66a..c2d4a3f66a 100644 --- a/libs/binder/fuzzer/binder.cpp +++ b/libs/binder/parcel_fuzzer/binder.cpp diff --git a/libs/binder/fuzzer/binder.h b/libs/binder/parcel_fuzzer/binder.h index b224ef49a1..0c51d68a37 100644 --- a/libs/binder/fuzzer/binder.h +++ b/libs/binder/parcel_fuzzer/binder.h @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#pragma once #include <binder/Parcel.h> #include <vector> diff --git a/libs/binder/fuzzer/binder_ndk.cpp b/libs/binder/parcel_fuzzer/binder_ndk.cpp index 29da8f7537..29da8f7537 100644 --- a/libs/binder/fuzzer/binder_ndk.cpp +++ b/libs/binder/parcel_fuzzer/binder_ndk.cpp diff --git a/libs/binder/fuzzer/binder_ndk.h b/libs/binder/parcel_fuzzer/binder_ndk.h index 622cafc7df..e69d9c1d8f 100644 --- a/libs/binder/fuzzer/binder_ndk.h +++ b/libs/binder/parcel_fuzzer/binder_ndk.h @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#pragma once #include <android/binder_auto_utils.h> #include <vector> @@ -31,6 +32,9 @@ public: const AParcel* aParcel() const { return mParcel.get(); } AParcel* aParcel() { return mParcel.get(); } + android::Parcel* parcel() { return aParcel()->get(); } + + const uint8_t* data() const { return aParcel()->get()->data(); } size_t dataSize() const { return aParcel()->get()->dataSize(); } size_t dataAvail() const { return aParcel()->get()->dataAvail(); } size_t dataPosition() const { return aParcel()->get()->dataPosition(); } diff --git a/libs/binder/fuzzer/hwbinder.cpp b/libs/binder/parcel_fuzzer/hwbinder.cpp index 0fec393e55..0fec393e55 100644 --- a/libs/binder/fuzzer/hwbinder.cpp +++ b/libs/binder/parcel_fuzzer/hwbinder.cpp diff --git a/libs/binder/fuzzer/hwbinder.h b/libs/binder/parcel_fuzzer/hwbinder.h index a6c66beb44..1fa56d433d 100644 --- a/libs/binder/fuzzer/hwbinder.h +++ b/libs/binder/parcel_fuzzer/hwbinder.h @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#pragma once #include <hwbinder/Parcel.h> #include <vector> diff --git a/libs/binder/parcel_fuzzer/main.cpp b/libs/binder/parcel_fuzzer/main.cpp new file mode 100644 index 0000000000..46bf4178d0 --- /dev/null +++ b/libs/binder/parcel_fuzzer/main.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2019 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. + */ +#define FUZZ_LOG_TAG "main" + +#include "binder.h" +#include "binder_ndk.h" +#include "hwbinder.h" +#include "random_parcel.h" +#include "util.h" + +#include <android-base/logging.h> +#include <fuzzer/FuzzedDataProvider.h> + +#include <cstdlib> +#include <ctime> + +using android::fillRandomParcel; + +void fillRandomParcel(::android::hardware::Parcel* p, FuzzedDataProvider&& provider) { + std::vector<uint8_t> input = provider.ConsumeRemainingBytes<uint8_t>(); + p->setData(input.data(), input.size()); +} + +template <typename P> +void doFuzz(const char* backend, const std::vector<ParcelRead<P>>& reads, + FuzzedDataProvider&& provider) { + // Allow some majority of the bytes to be dedicated to telling us what to + // do. The fixed value added here represents that we want to test doing a + // lot of 'instructions' even on really short parcels. + size_t maxInstructions = 20 + (provider.remaining_bytes() * 2 / 3); + // but don't always use that many instructions. We want to allow the fuzzer + // to explore large parcels with few instructions if it wants to. + std::vector<uint8_t> instructions = provider.ConsumeBytes<uint8_t>( + provider.ConsumeIntegralInRange<size_t>(0, maxInstructions)); + + P p; + fillRandomParcel(&p, std::move(provider)); + + // since we are only using a byte to index + CHECK(reads.size() <= 255) << reads.size(); + + FUZZ_LOG() << "backend: " << backend; + FUZZ_LOG() << "input: " << hexString(p.data(), p.dataSize()); + FUZZ_LOG() << "instructions: " << hexString(instructions); + + for (size_t i = 0; i + 1 < instructions.size(); i += 2) { + uint8_t a = instructions[i]; + uint8_t readIdx = a % reads.size(); + + uint8_t b = instructions[i + 1]; + + FUZZ_LOG() << "Instruction: " << (i / 2) + 1 << "/" << instructions.size() / 2 + << " cmd: " << static_cast<size_t>(a) << " (" << static_cast<size_t>(readIdx) + << ") arg: " << static_cast<size_t>(b) << " size: " << p.dataSize() + << " avail: " << p.dataAvail() << " pos: " << p.dataPosition() + << " cap: " << p.dataCapacity(); + + reads[readIdx](p, b); + } +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if (size <= 1) return 0; // no use + + // avoid timeouts, see b/142617274, b/142473153 + if (size > 50000) return 0; + + FuzzedDataProvider provider = FuzzedDataProvider(data, size); + + const std::function<void(FuzzedDataProvider &&)> fuzzBackend[3] = { + [](FuzzedDataProvider&& provider) { + doFuzz<::android::hardware::Parcel>("hwbinder", HWBINDER_PARCEL_READ_FUNCTIONS, + std::move(provider)); + }, + [](FuzzedDataProvider&& provider) { + doFuzz<::android::Parcel>("binder", BINDER_PARCEL_READ_FUNCTIONS, + std::move(provider)); + }, + [](FuzzedDataProvider&& provider) { + doFuzz<NdkParcelAdapter>("binder_ndk", BINDER_NDK_PARCEL_READ_FUNCTIONS, + std::move(provider)); + }, + }; + + provider.PickValueInArray(fuzzBackend)(std::move(provider)); + + return 0; +} diff --git a/libs/binder/fuzzer/parcel_fuzzer.h b/libs/binder/parcel_fuzzer/parcel_fuzzer.h index 10cf17c328..b68a8a91e6 100644 --- a/libs/binder/fuzzer/parcel_fuzzer.h +++ b/libs/binder/parcel_fuzzer/parcel_fuzzer.h @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#pragma once template <typename P> using ParcelRead = std::function<void(const P& p, uint8_t data)>; diff --git a/libs/binder/parcel_fuzzer/random_fd.cpp b/libs/binder/parcel_fuzzer/random_fd.cpp new file mode 100644 index 0000000000..eb80ece747 --- /dev/null +++ b/libs/binder/parcel_fuzzer/random_fd.cpp @@ -0,0 +1,35 @@ +/* + * 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 "random_fd.h" + +#include <fcntl.h> + +#include <android-base/logging.h> +#include <cutils/ashmem.h> + +namespace android { + +int getRandomFd(FuzzedDataProvider* provider) { + int fd = provider->PickValueInArray<std::function<int()>>({ + []() { return ashmem_create_region("binder test region", 1024); }, + []() { return open("/dev/null", O_RDWR); }, + })(); + CHECK(fd >= 0); + return fd; +} + +} // namespace android diff --git a/libs/binder/parcel_fuzzer/random_fd.h b/libs/binder/parcel_fuzzer/random_fd.h new file mode 100644 index 0000000000..0a083d7665 --- /dev/null +++ b/libs/binder/parcel_fuzzer/random_fd.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#pragma once + +#include <fuzzer/FuzzedDataProvider.h> + +namespace android { + +// ownership to callee, always valid or aborts +// get a random FD for use in fuzzing, of a few different specific types +int getRandomFd(FuzzedDataProvider* provider); + +} // namespace android diff --git a/libs/binder/parcel_fuzzer/random_parcel.cpp b/libs/binder/parcel_fuzzer/random_parcel.cpp new file mode 100644 index 0000000000..3dae9043da --- /dev/null +++ b/libs/binder/parcel_fuzzer/random_parcel.cpp @@ -0,0 +1,83 @@ +/* + * 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 "random_parcel.h" + +#include "random_fd.h" + +#include <android-base/logging.h> +#include <binder/IServiceManager.h> +#include <utils/String16.h> + +namespace android { + +void fillRandomParcel(NdkParcelAdapter* p, FuzzedDataProvider&& provider) { + fillRandomParcel(p->parcel(), std::move(provider)); +} + +class NamedBinder : public BBinder { +public: + NamedBinder(const String16& descriptor) : mDescriptor(descriptor) {} + const String16& getInterfaceDescriptor() const override { return mDescriptor; } + +private: + String16 mDescriptor; +}; + +void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider) { + while (provider.remaining_bytes() > 0) { + auto fillFunc = provider.PickValueInArray<const std::function<void()>>({ + // write data + [&]() { + size_t toWrite = + provider.ConsumeIntegralInRange<size_t>(0, provider.remaining_bytes()); + std::vector<uint8_t> data = provider.ConsumeBytes<uint8_t>(toWrite); + CHECK(OK == p->write(data.data(), data.size())); + }, + // write FD + [&]() { + int fd = getRandomFd(&provider); + CHECK(OK == p->writeFileDescriptor(fd, true /*takeOwnership*/)); + }, + // write binder + [&]() { + auto makeFunc = provider.PickValueInArray<const std::function<sp<IBinder>()>>({ + [&]() { + // descriptor is the length of a class name, e.g. + // "some.package.Foo" + std::string str = + provider.ConsumeRandomLengthString(100 /*max length*/); + return new NamedBinder(String16(str.c_str())); + }, + []() { + // this is the easiest remote binder to get ahold of, and it + // should be able to handle anything thrown at it, and + // essentially every process can talk to it, so it's a good + // candidate for checking usage of an actual BpBinder + return IInterface::asBinder(defaultServiceManager()); + }, + []() { return nullptr; }, + }); + sp<IBinder> binder = makeFunc(); + CHECK(OK == p->writeStrongBinder(binder)); + }, + }); + + fillFunc(); + } +} + +} // namespace android diff --git a/libs/binder/parcel_fuzzer/random_parcel.h b/libs/binder/parcel_fuzzer/random_parcel.h new file mode 100644 index 0000000000..2923c47f46 --- /dev/null +++ b/libs/binder/parcel_fuzzer/random_parcel.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#pragma once + +#include "binder_ndk.h" + +#include <binder/Parcel.h> +#include <fuzzer/FuzzedDataProvider.h> + +namespace android { +void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider); +void fillRandomParcel(NdkParcelAdapter* p, FuzzedDataProvider&& provider); +} // namespace android diff --git a/libs/binder/fuzzer/util.cpp b/libs/binder/parcel_fuzzer/util.cpp index 479f406d8c..479f406d8c 100644 --- a/libs/binder/fuzzer/util.cpp +++ b/libs/binder/parcel_fuzzer/util.cpp diff --git a/libs/binder/fuzzer/util.h b/libs/binder/parcel_fuzzer/util.h index aa504d29f2..45e8c571a8 100644 --- a/libs/binder/fuzzer/util.h +++ b/libs/binder/parcel_fuzzer/util.h @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#pragma once #include <iostream> #include <sstream> |