diff options
| author | 2021-01-12 16:13:20 -0800 | |
|---|---|---|
| committer | 2022-08-30 10:29:49 +0000 | |
| commit | 0f0ca6e181cdacc57d1ba7b14fb205e2604fc76b (patch) | |
| tree | e58a80b12cedd1e8077cbbd4c312547316245d4a | |
| parent | 910968de36b314ccd702aaf0e8f92f403cd4c352 (diff) | |
Add inputflinger InputReader fuzzer
This CL aims to add a fuzzer to test inputflinger's InputReader
functionality.
Test: Fuzzers tested on a Pixel 3a, and run for approximately 1M
iterations each to test stability. Executions/sec vary from
~400-900, depending on the fuzzer.
Summary of updates:
Coverage improvements: 36.75% to 82.29%
Design changes:
[1] Provided a mock Implementation for InputReaderInterface and
added support for newer APIs.
[2] Enabled support for few more Events that helped in discovering
new code paths.
[3] Added missing APIs and resolved OOB Access crashes.
[4] Refactored InputReaderFuzzer to resolve build errors.
Signed-off-by: Michael Ensing <michael.ensing@leviathansecurity.com>
Change-Id: I8e9c5f78960dba6d84a46ad7ee46963b3be79fec
| -rw-r--r-- | services/inputflinger/tests/fuzzers/Android.bp | 10 | ||||
| -rw-r--r-- | services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp | 279 |
2 files changed, 289 insertions, 0 deletions
diff --git a/services/inputflinger/tests/fuzzers/Android.bp b/services/inputflinger/tests/fuzzers/Android.bp index 05755acf6c..f4ecba2a10 100644 --- a/services/inputflinger/tests/fuzzers/Android.bp +++ b/services/inputflinger/tests/fuzzers/Android.bp @@ -120,6 +120,16 @@ cc_fuzz { } cc_fuzz { + name: "inputflinger_input_reader_fuzzer", + defaults: [ + "inputflinger_fuzz_defaults", + ], + srcs: [ + "InputReaderFuzzer.cpp", + ], +} + +cc_fuzz { name: "inputflinger_blocking_queue_fuzzer", defaults: [ "inputflinger_fuzz_defaults", diff --git a/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp b/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp new file mode 100644 index 0000000000..f15d871403 --- /dev/null +++ b/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp @@ -0,0 +1,279 @@ +/* + * Copyright 2022 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 <InputReader.h> +#include <MapperHelpers.h> +#include <fuzzer/FuzzedDataProvider.h> +#include <input/InputDevice.h> +#include <chrono> +#include <thread> + +namespace android { + +constexpr InputDeviceSensorType kInputDeviceSensorType[] = { + InputDeviceSensorType::ACCELEROMETER, + InputDeviceSensorType::MAGNETIC_FIELD, + InputDeviceSensorType::ORIENTATION, + InputDeviceSensorType::GYROSCOPE, + InputDeviceSensorType::LIGHT, + InputDeviceSensorType::PRESSURE, + InputDeviceSensorType::TEMPERATURE, + InputDeviceSensorType::PROXIMITY, + InputDeviceSensorType::GRAVITY, + InputDeviceSensorType::LINEAR_ACCELERATION, + InputDeviceSensorType::ROTATION_VECTOR, + InputDeviceSensorType::RELATIVE_HUMIDITY, + InputDeviceSensorType::AMBIENT_TEMPERATURE, + InputDeviceSensorType::MAGNETIC_FIELD_UNCALIBRATED, + InputDeviceSensorType::GAME_ROTATION_VECTOR, + InputDeviceSensorType::GYROSCOPE_UNCALIBRATED, + InputDeviceSensorType::SIGNIFICANT_MOTION, +}; + +class FuzzInputReader : public InputReaderInterface { +public: + FuzzInputReader(std::shared_ptr<EventHubInterface> fuzzEventHub, + const sp<InputReaderPolicyInterface>& fuzzPolicy, + InputListenerInterface& fuzzListener) { + reader = std::make_unique<InputReader>(fuzzEventHub, fuzzPolicy, fuzzListener); + } + + void dump(std::string& dump) { reader->dump(dump); } + + void monitor() { reader->monitor(); } + + bool isInputDeviceEnabled(int32_t deviceId) { return reader->isInputDeviceEnabled(deviceId); } + + status_t start() { return reader->start(); } + + status_t stop() { return reader->stop(); } + + std::vector<InputDeviceInfo> getInputDevices() const { return reader->getInputDevices(); } + + int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask, int32_t scanCode) { + return reader->getScanCodeState(deviceId, sourceMask, scanCode); + } + + int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask, int32_t keyCode) { + return reader->getKeyCodeState(deviceId, sourceMask, keyCode); + } + + int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t sw) { + return reader->getSwitchState(deviceId, sourceMask, sw); + } + + void toggleCapsLockState(int32_t deviceId) { reader->toggleCapsLockState(deviceId); } + + bool hasKeys(int32_t deviceId, uint32_t sourceMask, const std::vector<int32_t>& keyCodes, + uint8_t* outFlags) { + return reader->hasKeys(deviceId, sourceMask, keyCodes, outFlags); + } + + void requestRefreshConfiguration(uint32_t changes) { + reader->requestRefreshConfiguration(changes); + } + + void vibrate(int32_t deviceId, const VibrationSequence& sequence, ssize_t repeat, + int32_t token) { + reader->vibrate(deviceId, sequence, repeat, token); + } + + void cancelVibrate(int32_t deviceId, int32_t token) { reader->cancelVibrate(deviceId, token); } + + bool isVibrating(int32_t deviceId) { return reader->isVibrating(deviceId); } + + std::vector<int32_t> getVibratorIds(int32_t deviceId) { + return reader->getVibratorIds(deviceId); + } + + std::optional<int32_t> getBatteryCapacity(int32_t deviceId) { + return reader->getBatteryCapacity(deviceId); + } + + std::optional<int32_t> getBatteryStatus(int32_t deviceId) { + return reader->getBatteryStatus(deviceId); + } + + std::vector<InputDeviceLightInfo> getLights(int32_t deviceId) { + return reader->getLights(deviceId); + } + + std::vector<InputDeviceSensorInfo> getSensors(int32_t deviceId) { + return reader->getSensors(deviceId); + } + + bool canDispatchToDisplay(int32_t deviceId, int32_t displayId) { + return reader->canDispatchToDisplay(deviceId, displayId); + } + + bool enableSensor(int32_t deviceId, InputDeviceSensorType sensorType, + std::chrono::microseconds samplingPeriod, + std::chrono::microseconds maxBatchReportLatency) { + return reader->enableSensor(deviceId, sensorType, samplingPeriod, maxBatchReportLatency); + } + + void disableSensor(int32_t deviceId, InputDeviceSensorType sensorType) { + return reader->disableSensor(deviceId, sensorType); + } + + void flushSensor(int32_t deviceId, InputDeviceSensorType sensorType) { + return reader->flushSensor(deviceId, sensorType); + } + + bool setLightColor(int32_t deviceId, int32_t lightId, int32_t color) { + return reader->setLightColor(deviceId, lightId, color); + } + + bool setLightPlayerId(int32_t deviceId, int32_t lightId, int32_t playerId) { + return reader->setLightPlayerId(deviceId, lightId, playerId); + } + + std::optional<int32_t> getLightColor(int32_t deviceId, int32_t lightId) { + return reader->getLightColor(deviceId, lightId); + } + + std::optional<int32_t> getLightPlayerId(int32_t deviceId, int32_t lightId) { + return reader->getLightPlayerId(deviceId, lightId); + } + + int32_t getKeyCodeForKeyLocation(int32_t deviceId, int32_t locationKeyCode) const { + return reader->getKeyCodeForKeyLocation(deviceId, locationKeyCode); + } + +private: + std::unique_ptr<InputReaderInterface> reader; +}; + +extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { + std::shared_ptr<FuzzedDataProvider> fdp = std::make_shared<FuzzedDataProvider>(data, size); + + FuzzInputListener fuzzListener; + sp<FuzzInputReaderPolicy> fuzzPolicy = sp<FuzzInputReaderPolicy>::make(fdp); + std::shared_ptr<FuzzEventHub> fuzzEventHub = std::make_shared<FuzzEventHub>(fdp); + std::unique_ptr<FuzzInputReader> reader = + std::make_unique<FuzzInputReader>(fuzzEventHub, fuzzPolicy, fuzzListener); + fuzzEventHub->addEvents(fdp); + size_t patternCount = fdp->ConsumeIntegralInRange<size_t>(1, 260); + VibrationSequence pattern(patternCount); + for (size_t i = 0; i < patternCount; ++i) { + VibrationElement element(i); + element.addChannel(fdp->ConsumeIntegral<int32_t>() /* vibratorId */, + fdp->ConsumeIntegral<uint8_t>() /* amplitude */); + pattern.addElement(element); + } + reader->vibrate(fdp->ConsumeIntegral<int32_t>(), pattern, + fdp->ConsumeIntegral<ssize_t>() /*repeat*/, + fdp->ConsumeIntegral<int32_t>() /*token*/); + reader->start(); + + // Loop through mapper operations until randomness is exhausted. + while (fdp->remaining_bytes() > 0) { + fdp->PickValueInArray<std::function<void()>>({ + [&]() -> void { + std::string dump; + reader->dump(dump); + }, + [&]() -> void { reader->monitor(); }, + [&]() -> void { reader->getInputDevices(); }, + [&]() -> void { reader->isInputDeviceEnabled(fdp->ConsumeIntegral<int32_t>()); }, + [&]() -> void { + reader->getScanCodeState(fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<uint32_t>(), + fdp->ConsumeIntegral<int32_t>()); + }, + [&]() -> void { + reader->getKeyCodeState(fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<uint32_t>(), + fdp->ConsumeIntegral<int32_t>()); + }, + [&]() -> void { + reader->getSwitchState(fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<uint32_t>(), + fdp->ConsumeIntegral<int32_t>()); + }, + [&]() -> void { reader->toggleCapsLockState(fdp->ConsumeIntegral<int32_t>()); }, + [&]() -> void { + size_t count = fdp->ConsumeIntegralInRange<size_t>(1, 1024); + std::vector<uint8_t> outFlags(count); + std::vector<int32_t> keyCodes; + for (size_t i = 0; i < count; ++i) { + keyCodes.push_back(fdp->ConsumeIntegral<int32_t>()); + } + reader->hasKeys(fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<uint32_t>(), keyCodes, outFlags.data()); + }, + [&]() -> void { + reader->requestRefreshConfiguration(fdp->ConsumeIntegral<uint32_t>()); + }, + [&]() -> void { + reader->cancelVibrate(fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<int32_t>()); + }, + [&]() -> void { + reader->canDispatchToDisplay(fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<int32_t>()); + }, + [&]() -> void { + reader->getKeyCodeForKeyLocation(fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<int32_t>()); + }, + [&]() -> void { reader->getBatteryCapacity(fdp->ConsumeIntegral<int32_t>()); }, + [&]() -> void { reader->getBatteryStatus(fdp->ConsumeIntegral<int32_t>()); }, + [&]() -> void { reader->getLights(fdp->ConsumeIntegral<int32_t>()); }, + [&]() -> void { reader->getSensors(fdp->ConsumeIntegral<int32_t>()); }, + [&]() -> void { + reader->getLightPlayerId(fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<int32_t>()); + }, + [&]() -> void { + reader->getLightColor(fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<int32_t>()); + }, + [&]() -> void { + reader->setLightPlayerId(fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<int32_t>()); + }, + [&]() -> void { + reader->setLightColor(fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<int32_t>()); + }, + [&]() -> void { + reader->flushSensor(fdp->ConsumeIntegral<int32_t>(), + fdp->PickValueInArray<InputDeviceSensorType>( + kInputDeviceSensorType)); + }, + [&]() -> void { + reader->disableSensor(fdp->ConsumeIntegral<int32_t>(), + fdp->PickValueInArray<InputDeviceSensorType>( + kInputDeviceSensorType)); + }, + [&]() -> void { + reader->enableSensor(fdp->ConsumeIntegral<int32_t>(), + fdp->PickValueInArray<InputDeviceSensorType>( + kInputDeviceSensorType), + std::chrono::microseconds(fdp->ConsumeIntegral<size_t>()), + std::chrono::microseconds(fdp->ConsumeIntegral<size_t>())); + }, + })(); + } + + reader->stop(); + return 0; +} + +} // namespace android |