Steven Moreland | 46e0da7 | 2019-09-05 15:52:02 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2019 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | #define FUZZ_LOG_TAG "main" |
| 17 | |
| 18 | #include "binder.h" |
Steven Moreland | 28f8142 | 2019-10-03 10:40:59 -0700 | [diff] [blame] | 19 | #include "binder_ndk.h" |
Steven Moreland | 46e0da7 | 2019-09-05 15:52:02 -0700 | [diff] [blame] | 20 | #include "hwbinder.h" |
| 21 | #include "util.h" |
| 22 | |
| 23 | #include <android-base/logging.h> |
Steven Moreland | 362e4da | 2020-10-16 19:49:39 +0000 | [diff] [blame^] | 24 | #include <fuzzbinder/random_parcel.h> |
Steven Moreland | 842b593 | 2020-10-08 00:23:35 +0000 | [diff] [blame] | 25 | #include <fuzzer/FuzzedDataProvider.h> |
Steven Moreland | 46e0da7 | 2019-09-05 15:52:02 -0700 | [diff] [blame] | 26 | |
| 27 | #include <cstdlib> |
| 28 | #include <ctime> |
| 29 | |
Steven Moreland | 5e561af | 2020-10-08 02:16:03 +0000 | [diff] [blame] | 30 | using android::fillRandomParcel; |
| 31 | |
| 32 | void fillRandomParcel(::android::hardware::Parcel* p, FuzzedDataProvider&& provider) { |
Steven Moreland | 362e4da | 2020-10-16 19:49:39 +0000 | [diff] [blame^] | 33 | // TODO: functionality to create random parcels for libhwbinder parcels |
Steven Moreland | 5e561af | 2020-10-08 02:16:03 +0000 | [diff] [blame] | 34 | std::vector<uint8_t> input = provider.ConsumeRemainingBytes<uint8_t>(); |
| 35 | p->setData(input.data(), input.size()); |
| 36 | } |
Steven Moreland | 362e4da | 2020-10-16 19:49:39 +0000 | [diff] [blame^] | 37 | static void fillRandomParcel(NdkParcelAdapter* p, FuzzedDataProvider&& provider) { |
| 38 | // fill underlying parcel using functions to fill random libbinder parcel |
| 39 | fillRandomParcel(p->parcel(), std::move(provider)); |
| 40 | } |
Steven Moreland | 5e561af | 2020-10-08 02:16:03 +0000 | [diff] [blame] | 41 | |
Steven Moreland | 46e0da7 | 2019-09-05 15:52:02 -0700 | [diff] [blame] | 42 | template <typename P> |
Steven Moreland | 842b593 | 2020-10-08 00:23:35 +0000 | [diff] [blame] | 43 | void doFuzz(const char* backend, const std::vector<ParcelRead<P>>& reads, |
Steven Moreland | 5e561af | 2020-10-08 02:16:03 +0000 | [diff] [blame] | 44 | FuzzedDataProvider&& provider) { |
Steven Moreland | 842b593 | 2020-10-08 00:23:35 +0000 | [diff] [blame] | 45 | // Allow some majority of the bytes to be dedicated to telling us what to |
| 46 | // do. The fixed value added here represents that we want to test doing a |
| 47 | // lot of 'instructions' even on really short parcels. |
Steven Moreland | 5e561af | 2020-10-08 02:16:03 +0000 | [diff] [blame] | 48 | size_t maxInstructions = 20 + (provider.remaining_bytes() * 2 / 3); |
Steven Moreland | 842b593 | 2020-10-08 00:23:35 +0000 | [diff] [blame] | 49 | // but don't always use that many instructions. We want to allow the fuzzer |
| 50 | // to explore large parcels with few instructions if it wants to. |
Steven Moreland | 5e561af | 2020-10-08 02:16:03 +0000 | [diff] [blame] | 51 | std::vector<uint8_t> instructions = provider.ConsumeBytes<uint8_t>( |
| 52 | provider.ConsumeIntegralInRange<size_t>(0, maxInstructions)); |
Steven Moreland | 46e0da7 | 2019-09-05 15:52:02 -0700 | [diff] [blame] | 53 | |
| 54 | P p; |
Steven Moreland | 5e561af | 2020-10-08 02:16:03 +0000 | [diff] [blame] | 55 | fillRandomParcel(&p, std::move(provider)); |
Steven Moreland | 46e0da7 | 2019-09-05 15:52:02 -0700 | [diff] [blame] | 56 | |
Steven Moreland | 7eac78a | 2019-10-11 18:46:24 -0700 | [diff] [blame] | 57 | // since we are only using a byte to index |
| 58 | CHECK(reads.size() <= 255) << reads.size(); |
| 59 | |
Steven Moreland | 842b593 | 2020-10-08 00:23:35 +0000 | [diff] [blame] | 60 | FUZZ_LOG() << "backend: " << backend; |
Steven Moreland | 5e561af | 2020-10-08 02:16:03 +0000 | [diff] [blame] | 61 | FUZZ_LOG() << "input: " << hexString(p.data(), p.dataSize()); |
Steven Moreland | 842b593 | 2020-10-08 00:23:35 +0000 | [diff] [blame] | 62 | FUZZ_LOG() << "instructions: " << hexString(instructions); |
| 63 | |
| 64 | for (size_t i = 0; i + 1 < instructions.size(); i += 2) { |
Steven Moreland | 46e0da7 | 2019-09-05 15:52:02 -0700 | [diff] [blame] | 65 | uint8_t a = instructions[i]; |
Steven Moreland | dc449dc | 2019-10-10 10:06:58 -0700 | [diff] [blame] | 66 | uint8_t readIdx = a % reads.size(); |
| 67 | |
Steven Moreland | 46e0da7 | 2019-09-05 15:52:02 -0700 | [diff] [blame] | 68 | uint8_t b = instructions[i + 1]; |
| 69 | |
Steven Moreland | dc449dc | 2019-10-10 10:06:58 -0700 | [diff] [blame] | 70 | FUZZ_LOG() << "Instruction: " << (i / 2) + 1 << "/" << instructions.size() / 2 |
| 71 | << " cmd: " << static_cast<size_t>(a) << " (" << static_cast<size_t>(readIdx) |
| 72 | << ") arg: " << static_cast<size_t>(b) << " size: " << p.dataSize() |
| 73 | << " avail: " << p.dataAvail() << " pos: " << p.dataPosition() |
| 74 | << " cap: " << p.dataCapacity(); |
Steven Moreland | 46e0da7 | 2019-09-05 15:52:02 -0700 | [diff] [blame] | 75 | |
Steven Moreland | dc449dc | 2019-10-10 10:06:58 -0700 | [diff] [blame] | 76 | reads[readIdx](p, b); |
Steven Moreland | 46e0da7 | 2019-09-05 15:52:02 -0700 | [diff] [blame] | 77 | } |
| 78 | } |
| 79 | |
Steven Moreland | 46e0da7 | 2019-09-05 15:52:02 -0700 | [diff] [blame] | 80 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { |
| 81 | if (size <= 1) return 0; // no use |
Steven Moreland | 9894741 | 2019-10-15 10:36:05 -0700 | [diff] [blame] | 82 | |
| 83 | // avoid timeouts, see b/142617274, b/142473153 |
| 84 | if (size > 50000) return 0; |
| 85 | |
Steven Moreland | 842b593 | 2020-10-08 00:23:35 +0000 | [diff] [blame] | 86 | FuzzedDataProvider provider = FuzzedDataProvider(data, size); |
Steven Moreland | 46e0da7 | 2019-09-05 15:52:02 -0700 | [diff] [blame] | 87 | |
Steven Moreland | 5e561af | 2020-10-08 02:16:03 +0000 | [diff] [blame] | 88 | const std::function<void(FuzzedDataProvider &&)> fuzzBackend[3] = { |
| 89 | [](FuzzedDataProvider&& provider) { |
Steven Moreland | 842b593 | 2020-10-08 00:23:35 +0000 | [diff] [blame] | 90 | doFuzz<::android::hardware::Parcel>("hwbinder", HWBINDER_PARCEL_READ_FUNCTIONS, |
Steven Moreland | 5e561af | 2020-10-08 02:16:03 +0000 | [diff] [blame] | 91 | std::move(provider)); |
Steven Moreland | 842b593 | 2020-10-08 00:23:35 +0000 | [diff] [blame] | 92 | }, |
Steven Moreland | 5e561af | 2020-10-08 02:16:03 +0000 | [diff] [blame] | 93 | [](FuzzedDataProvider&& provider) { |
| 94 | doFuzz<::android::Parcel>("binder", BINDER_PARCEL_READ_FUNCTIONS, |
| 95 | std::move(provider)); |
Steven Moreland | 842b593 | 2020-10-08 00:23:35 +0000 | [diff] [blame] | 96 | }, |
Steven Moreland | 5e561af | 2020-10-08 02:16:03 +0000 | [diff] [blame] | 97 | [](FuzzedDataProvider&& provider) { |
| 98 | doFuzz<NdkParcelAdapter>("binder_ndk", BINDER_NDK_PARCEL_READ_FUNCTIONS, |
| 99 | std::move(provider)); |
Steven Moreland | 842b593 | 2020-10-08 00:23:35 +0000 | [diff] [blame] | 100 | }, |
| 101 | }; |
Steven Moreland | 46e0da7 | 2019-09-05 15:52:02 -0700 | [diff] [blame] | 102 | |
Steven Moreland | 5e561af | 2020-10-08 02:16:03 +0000 | [diff] [blame] | 103 | provider.PickValueInArray(fuzzBackend)(std::move(provider)); |
Steven Moreland | 46e0da7 | 2019-09-05 15:52:02 -0700 | [diff] [blame] | 104 | |
Steven Moreland | 46e0da7 | 2019-09-05 15:52:02 -0700 | [diff] [blame] | 105 | return 0; |
| 106 | } |