Tri Vo | 77e0ca0 | 2016-12-05 10:08:59 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2016 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 | |
Tri Vo | 77e0ca0 | 2016-12-05 10:08:59 -0800 | [diff] [blame] | 17 | #include "ProtoFuzzerMutator.h" |
| 18 | |
Tri Vo | 77e0ca0 | 2016-12-05 10:08:59 -0800 | [diff] [blame] | 19 | #include "test/vts/proto/ComponentSpecificationMessage.pb.h" |
| 20 | |
| 21 | #include <unistd.h> |
| 22 | |
Tri Vo | c8bfd0d | 2017-07-24 15:31:46 -0700 | [diff] [blame] | 23 | #include <cstdlib> |
Tri Vo | 77e0ca0 | 2016-12-05 10:08:59 -0800 | [diff] [blame] | 24 | #include <iostream> |
| 25 | #include <memory> |
| 26 | #include <string> |
| 27 | #include <vector> |
| 28 | |
Tri Vo | 77e0ca0 | 2016-12-05 10:08:59 -0800 | [diff] [blame] | 29 | using std::cout; |
| 30 | using std::endl; |
| 31 | using std::make_unique; |
Tri Vo | 826a201 | 2017-01-05 12:21:25 -0800 | [diff] [blame] | 32 | using std::string; |
Tri Vo | 77e0ca0 | 2016-12-05 10:08:59 -0800 | [diff] [blame] | 33 | using std::unique_ptr; |
| 34 | using std::vector; |
| 35 | |
| 36 | namespace android { |
| 37 | namespace vts { |
Tri Vo | 70c1ab6 | 2017-03-15 09:19:10 -0700 | [diff] [blame] | 38 | namespace fuzzer { |
Tri Vo | 77e0ca0 | 2016-12-05 10:08:59 -0800 | [diff] [blame] | 39 | |
Tri Vo | 16eed23 | 2017-03-08 08:52:15 -0800 | [diff] [blame] | 40 | // 64-bit random number generator. |
Tri Vo | 624961d | 2017-07-24 10:30:41 -0700 | [diff] [blame] | 41 | static unique_ptr<Random> random; |
Tri Vo | 9f5fd85 | 2017-05-20 12:32:26 -0700 | [diff] [blame] | 42 | // Parameters that were passed in to fuzzer. |
Tri Vo | 16eed23 | 2017-03-08 08:52:15 -0800 | [diff] [blame] | 43 | static ProtoFuzzerParams params; |
Tri Vo | 16eed23 | 2017-03-08 08:52:15 -0800 | [diff] [blame] | 44 | // Used to mutate inputs to hal driver. |
Tri Vo | 77e0ca0 | 2016-12-05 10:08:59 -0800 | [diff] [blame] | 45 | static unique_ptr<ProtoFuzzerMutator> mutator; |
Tri Vo | 9f5fd85 | 2017-05-20 12:32:26 -0700 | [diff] [blame] | 46 | // Used to exercise HIDL HAL's API. |
| 47 | static unique_ptr<ProtoFuzzerRunner> runner; |
Tri Vo | 77e0ca0 | 2016-12-05 10:08:59 -0800 | [diff] [blame] | 48 | |
Tri Vo | f4037d4 | 2017-03-31 17:28:25 -0700 | [diff] [blame] | 49 | static ProtoFuzzerMutatorConfig mutator_config{ |
Tri Vo | ced7954 | 2017-01-26 15:01:09 -0800 | [diff] [blame] | 50 | // Heuristic: values close to 0 are likely to be meaningful scalar input |
| 51 | // values. |
| 52 | [](Random &rand) { |
| 53 | size_t dice_roll = rand(10); |
| 54 | if (dice_roll < 3) { |
| 55 | // With probability of 30% return an integer in range [0, 10). |
| 56 | return rand(10); |
| 57 | } else if (dice_roll >= 3 && dice_roll < 6) { |
| 58 | // With probability of 30% return an integer in range [0, 100). |
| 59 | return rand(100); |
| 60 | } else if (dice_roll >= 6 && dice_roll < 9) { |
| 61 | // With probability of 30% return an integer in range [0, 100). |
| 62 | return rand(1000); |
| 63 | } |
| 64 | if (rand(10) == 0) { |
| 65 | // With probability of 1% return 0xffffffffffffffff. |
| 66 | return 0xffffffffffffffff; |
| 67 | } |
| 68 | // With probability 9% result is uniformly random. |
| 69 | return rand.Rand(); |
| 70 | }, |
| 71 | // Odds of an enum being treated like a scalar are 1:1000. |
| 72 | {1, 1000}}; |
| 73 | |
Tri Vo | c8bfd0d | 2017-07-24 15:31:46 -0700 | [diff] [blame] | 74 | // Executed when fuzzer process exits. We use this to print out useful |
| 75 | // information about the state of the fuzzer. |
| 76 | static void AtExit() { |
| 77 | // Print currently opened interfaces. |
| 78 | cerr << "Currently opened interfaces: " << endl; |
| 79 | for (const auto &iface_desc : runner->GetOpenedIfaces()) { |
| 80 | cerr << iface_desc.first << endl; |
| 81 | } |
Tri Vo | f657d67 | 2017-07-26 16:13:02 -0700 | [diff] [blame] | 82 | cerr << endl; |
| 83 | cerr << runner->GetStats().StatsString(); |
Tri Vo | c8bfd0d | 2017-07-24 15:31:46 -0700 | [diff] [blame] | 84 | } |
| 85 | |
Tri Vo | 77e0ca0 | 2016-12-05 10:08:59 -0800 | [diff] [blame] | 86 | extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) { |
Tri Vo | 16eed23 | 2017-03-08 08:52:15 -0800 | [diff] [blame] | 87 | params = ExtractProtoFuzzerParams(*argc, *argv); |
Tri Vo | 624961d | 2017-07-24 10:30:41 -0700 | [diff] [blame] | 88 | cerr << params.DebugString() << endl; |
| 89 | |
| 90 | random = make_unique<Random>(params.seed_); |
Tri Vo | 826a201 | 2017-01-05 12:21:25 -0800 | [diff] [blame] | 91 | mutator = make_unique<ProtoFuzzerMutator>( |
Tri Vo | 624961d | 2017-07-24 10:30:41 -0700 | [diff] [blame] | 92 | *random.get(), ExtractPredefinedTypes(params.comp_specs_), |
| 93 | mutator_config); |
Tri Vo | 9f5fd85 | 2017-05-20 12:32:26 -0700 | [diff] [blame] | 94 | runner = make_unique<ProtoFuzzerRunner>(params.comp_specs_); |
| 95 | |
| 96 | runner->Init(params.target_iface_, params.binder_mode_); |
Tri Vo | c8bfd0d | 2017-07-24 15:31:46 -0700 | [diff] [blame] | 97 | // Register atexit handler after all static objects' initialization. |
| 98 | std::atexit(AtExit); |
Tri Vo | 77e0ca0 | 2016-12-05 10:08:59 -0800 | [diff] [blame] | 99 | return 0; |
| 100 | } |
| 101 | |
| 102 | extern "C" size_t LLVMFuzzerCustomMutator(uint8_t *data, size_t size, |
| 103 | size_t max_size, unsigned int seed) { |
Tri Vo | 9f5fd85 | 2017-05-20 12:32:26 -0700 | [diff] [blame] | 104 | ExecSpec exec_spec{}; |
Tri Vo | d0229fb | 2017-08-10 17:27:49 -0700 | [diff] [blame] | 105 | // An Execution is randomly generated if: |
| 106 | // 1. It can't be serialized from the given buffer OR |
| 107 | // 2. The runner has opened interfaces that have not been touched. |
| 108 | // Otherwise, the Execution is mutated. |
| 109 | if (!FromArray(data, size, &exec_spec) || runner->UntouchedIfaces()) { |
Tri Vo | 16eed23 | 2017-03-08 08:52:15 -0800 | [diff] [blame] | 110 | exec_spec = |
Tri Vo | 9f5fd85 | 2017-05-20 12:32:26 -0700 | [diff] [blame] | 111 | mutator->RandomGen(runner->GetOpenedIfaces(), params.exec_size_); |
Tri Vo | 77e0ca0 | 2016-12-05 10:08:59 -0800 | [diff] [blame] | 112 | } else { |
Tri Vo | 9f5fd85 | 2017-05-20 12:32:26 -0700 | [diff] [blame] | 113 | mutator->Mutate(runner->GetOpenedIfaces(), &exec_spec); |
Tri Vo | 77e0ca0 | 2016-12-05 10:08:59 -0800 | [diff] [blame] | 114 | } |
Tri Vo | dfe95ea | 2017-06-07 17:52:10 -0700 | [diff] [blame] | 115 | return ToArray(data, size, &exec_spec); |
Tri Vo | 77e0ca0 | 2016-12-05 10:08:59 -0800 | [diff] [blame] | 116 | } |
| 117 | |
Tri Vo | 826a201 | 2017-01-05 12:21:25 -0800 | [diff] [blame] | 118 | // TODO(trong): implement a meaningful cross-over mechanism. |
Tri Vo | 77e0ca0 | 2016-12-05 10:08:59 -0800 | [diff] [blame] | 119 | size_t LLVMFuzzerCustomCrossOver(const uint8_t *data1, size_t size1, |
| 120 | const uint8_t *data2, size_t size2, |
| 121 | uint8_t *out, size_t max_out_size, |
| 122 | unsigned int seed) { |
| 123 | memcpy(out, data1, size1); |
| 124 | return size1; |
| 125 | } |
| 126 | |
| 127 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
Tri Vo | dfe95ea | 2017-06-07 17:52:10 -0700 | [diff] [blame] | 128 | ExecSpec exec_spec{}; |
| 129 | if (!FromArray(data, size, &exec_spec)) { |
| 130 | cerr << "Failed to deserialize an ExecSpec." << endl; |
Tri Vo | 77e0ca0 | 2016-12-05 10:08:59 -0800 | [diff] [blame] | 131 | return 0; |
| 132 | } |
Tri Vo | 9f5fd85 | 2017-05-20 12:32:26 -0700 | [diff] [blame] | 133 | runner->Execute(exec_spec); |
Tri Vo | 77e0ca0 | 2016-12-05 10:08:59 -0800 | [diff] [blame] | 134 | return 0; |
| 135 | } |
| 136 | |
Tri Vo | 70c1ab6 | 2017-03-15 09:19:10 -0700 | [diff] [blame] | 137 | } // namespace fuzzer |
Tri Vo | 77e0ca0 | 2016-12-05 10:08:59 -0800 | [diff] [blame] | 138 | } // namespace vts |
| 139 | } // namespace android |