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 | 842b593 | 2020-10-08 00:23:35 +0000 | [diff] [blame^] | 24 | #include <fuzzer/FuzzedDataProvider.h> |
Steven Moreland | 46e0da7 | 2019-09-05 15:52:02 -0700 | [diff] [blame] | 25 | |
| 26 | #include <cstdlib> |
| 27 | #include <ctime> |
| 28 | |
| 29 | template <typename P> |
Steven Moreland | 842b593 | 2020-10-08 00:23:35 +0000 | [diff] [blame^] | 30 | void doFuzz(const char* backend, const std::vector<ParcelRead<P>>& reads, |
| 31 | FuzzedDataProvider* provider) { |
| 32 | // Allow some majority of the bytes to be dedicated to telling us what to |
| 33 | // do. The fixed value added here represents that we want to test doing a |
| 34 | // lot of 'instructions' even on really short parcels. |
| 35 | size_t maxInstructions = 20 + (provider->remaining_bytes() * 2 / 3); |
| 36 | // but don't always use that many instructions. We want to allow the fuzzer |
| 37 | // to explore large parcels with few instructions if it wants to. |
| 38 | std::vector<uint8_t> instructions = provider->ConsumeBytes<uint8_t>( |
| 39 | provider->ConsumeIntegralInRange<size_t>(0, maxInstructions)); |
| 40 | |
| 41 | // TODO: generate 'objects' data |
| 42 | std::vector<uint8_t> input = provider->ConsumeRemainingBytes<uint8_t>(); |
Steven Moreland | 46e0da7 | 2019-09-05 15:52:02 -0700 | [diff] [blame] | 43 | |
| 44 | P p; |
| 45 | p.setData(input.data(), input.size()); |
| 46 | |
Steven Moreland | 7eac78a | 2019-10-11 18:46:24 -0700 | [diff] [blame] | 47 | // since we are only using a byte to index |
| 48 | CHECK(reads.size() <= 255) << reads.size(); |
| 49 | |
Steven Moreland | 842b593 | 2020-10-08 00:23:35 +0000 | [diff] [blame^] | 50 | FUZZ_LOG() << "backend: " << backend; |
| 51 | FUZZ_LOG() << "input: " << hexString(input); |
| 52 | FUZZ_LOG() << "instructions: " << hexString(instructions); |
| 53 | |
| 54 | for (size_t i = 0; i + 1 < instructions.size(); i += 2) { |
Steven Moreland | 46e0da7 | 2019-09-05 15:52:02 -0700 | [diff] [blame] | 55 | uint8_t a = instructions[i]; |
Steven Moreland | dc449dc | 2019-10-10 10:06:58 -0700 | [diff] [blame] | 56 | uint8_t readIdx = a % reads.size(); |
| 57 | |
Steven Moreland | 46e0da7 | 2019-09-05 15:52:02 -0700 | [diff] [blame] | 58 | uint8_t b = instructions[i + 1]; |
| 59 | |
Steven Moreland | dc449dc | 2019-10-10 10:06:58 -0700 | [diff] [blame] | 60 | FUZZ_LOG() << "Instruction: " << (i / 2) + 1 << "/" << instructions.size() / 2 |
| 61 | << " cmd: " << static_cast<size_t>(a) << " (" << static_cast<size_t>(readIdx) |
| 62 | << ") arg: " << static_cast<size_t>(b) << " size: " << p.dataSize() |
| 63 | << " avail: " << p.dataAvail() << " pos: " << p.dataPosition() |
| 64 | << " cap: " << p.dataCapacity(); |
Steven Moreland | 46e0da7 | 2019-09-05 15:52:02 -0700 | [diff] [blame] | 65 | |
Steven Moreland | dc449dc | 2019-10-10 10:06:58 -0700 | [diff] [blame] | 66 | reads[readIdx](p, b); |
Steven Moreland | 46e0da7 | 2019-09-05 15:52:02 -0700 | [diff] [blame] | 67 | } |
| 68 | } |
| 69 | |
Steven Moreland | 46e0da7 | 2019-09-05 15:52:02 -0700 | [diff] [blame] | 70 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { |
| 71 | if (size <= 1) return 0; // no use |
Steven Moreland | 9894741 | 2019-10-15 10:36:05 -0700 | [diff] [blame] | 72 | |
| 73 | // avoid timeouts, see b/142617274, b/142473153 |
| 74 | if (size > 50000) return 0; |
| 75 | |
Steven Moreland | 842b593 | 2020-10-08 00:23:35 +0000 | [diff] [blame^] | 76 | FuzzedDataProvider provider = FuzzedDataProvider(data, size); |
Steven Moreland | 46e0da7 | 2019-09-05 15:52:02 -0700 | [diff] [blame] | 77 | |
Steven Moreland | 842b593 | 2020-10-08 00:23:35 +0000 | [diff] [blame^] | 78 | const std::function<void(FuzzedDataProvider*)> fuzzBackend[3] = { |
| 79 | [](FuzzedDataProvider* provider) { |
| 80 | doFuzz<::android::hardware::Parcel>("hwbinder", HWBINDER_PARCEL_READ_FUNCTIONS, |
| 81 | provider); |
| 82 | }, |
| 83 | [](FuzzedDataProvider* provider) { |
| 84 | doFuzz<::android::Parcel>("binder", BINDER_PARCEL_READ_FUNCTIONS, provider); |
| 85 | }, |
| 86 | [](FuzzedDataProvider* provider) { |
| 87 | doFuzz<NdkParcelAdapter>("binder_ndk", BINDER_NDK_PARCEL_READ_FUNCTIONS, provider); |
| 88 | }, |
| 89 | }; |
Steven Moreland | 46e0da7 | 2019-09-05 15:52:02 -0700 | [diff] [blame] | 90 | |
Steven Moreland | 842b593 | 2020-10-08 00:23:35 +0000 | [diff] [blame^] | 91 | provider.PickValueInArray(fuzzBackend)(&provider); |
Steven Moreland | 46e0da7 | 2019-09-05 15:52:02 -0700 | [diff] [blame] | 92 | |
Steven Moreland | 46e0da7 | 2019-09-05 15:52:02 -0700 | [diff] [blame] | 93 | return 0; |
| 94 | } |