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
diff --git a/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp b/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp
new file mode 100644
index 0000000..f15d871
--- /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