diff options
| author | 2022-09-08 07:45:28 +0000 | |
|---|---|---|
| committer | 2022-09-08 07:45:28 +0000 | |
| commit | 93b5420d8c5d18a631f5bfeba4a74bef0ee919de (patch) | |
| tree | 5c992b613b25fb27442f8e25ac769763b9a9e025 | |
| parent | f1d670fb9ee5281060a7d7d56d09dd53114bc72f (diff) | |
| parent | 0f0ca6e181cdacc57d1ba7b14fb205e2604fc76b (diff) | |
Merge changes I8e9c5f78,If48e5ddb
* changes:
Add inputflinger InputReader fuzzer
Add inputflinger blockingQueue/classifier fuzzers
4 files changed, 505 insertions, 0 deletions
diff --git a/services/inputflinger/tests/fuzzers/Android.bp b/services/inputflinger/tests/fuzzers/Android.bp index a53db00282..f4ecba2a10 100644 --- a/services/inputflinger/tests/fuzzers/Android.bp +++ b/services/inputflinger/tests/fuzzers/Android.bp @@ -57,6 +57,7 @@ cc_defaults { ], shared_libs: [ "android.hardware.input.classifier@1.0", + "android.hardware.input.processor-V1-ndk", "libbase", "libbinder", "libcutils", @@ -117,3 +118,33 @@ cc_fuzz { "SwitchInputFuzzer.cpp", ], } + +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", + ], + srcs: [ + "BlockingQueueFuzzer.cpp", + ], +} + +cc_fuzz { + name: "inputflinger_input_classifier_fuzzer", + defaults: [ + "inputflinger_fuzz_defaults", + ], + srcs: [ + "InputClassifierFuzzer.cpp", + ], +} diff --git a/services/inputflinger/tests/fuzzers/BlockingQueueFuzzer.cpp b/services/inputflinger/tests/fuzzers/BlockingQueueFuzzer.cpp new file mode 100644 index 0000000000..d2595bfc9d --- /dev/null +++ b/services/inputflinger/tests/fuzzers/BlockingQueueFuzzer.cpp @@ -0,0 +1,69 @@ +/* + * 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 <fuzzer/FuzzedDataProvider.h> +#include <thread> +#include "BlockingQueue.h" + +// Chosen to be a number large enough for variation in fuzzer runs, but not consume too much memory. +static constexpr size_t MAX_CAPACITY = 1024; + +namespace android { + +extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) { + FuzzedDataProvider fdp(data, size); + size_t capacity = fdp.ConsumeIntegralInRange<size_t>(1, MAX_CAPACITY); + size_t filled = 0; + BlockingQueue<int32_t> queue(capacity); + + while (fdp.remaining_bytes() > 0) { + fdp.PickValueInArray<std::function<void()>>({ + [&]() -> void { + size_t numPushes = fdp.ConsumeIntegralInRange<size_t>(0, capacity + 1); + for (size_t i = 0; i < numPushes; i++) { + queue.push(fdp.ConsumeIntegral<int32_t>()); + } + filled = std::min(capacity, filled + numPushes); + }, + [&]() -> void { + // Pops blocks if it is empty, so only pop up to num elements inserted. + size_t numPops = fdp.ConsumeIntegralInRange<size_t>(0, filled); + for (size_t i = 0; i < numPops; i++) { + queue.pop(); + } + filled > numPops ? filled -= numPops : filled = 0; + }, + [&]() -> void { + queue.clear(); + filled = 0; + }, + [&]() -> void { + int32_t eraseElement = fdp.ConsumeIntegral<int32_t>(); + queue.erase([&](int32_t element) { + if (element == eraseElement) { + filled--; + return true; + } + return false; + }); + }, + })(); + } + + return 0; +} + +} // namespace android diff --git a/services/inputflinger/tests/fuzzers/InputClassifierFuzzer.cpp b/services/inputflinger/tests/fuzzers/InputClassifierFuzzer.cpp new file mode 100644 index 0000000000..c407cffdbf --- /dev/null +++ b/services/inputflinger/tests/fuzzers/InputClassifierFuzzer.cpp @@ -0,0 +1,126 @@ +/* + * 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 <MapperHelpers.h> +#include <fuzzer/FuzzedDataProvider.h> +#include "InputCommonConverter.h" +#include "InputProcessor.h" + +namespace android { + +static constexpr int32_t MAX_AXES = 64; + +// Used by two fuzz operations and a bit lengthy, so pulled out into a function. +NotifyMotionArgs generateFuzzedMotionArgs(FuzzedDataProvider &fdp) { + // Create a basic motion event for testing + PointerProperties properties; + properties.id = 0; + properties.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER; + PointerCoords coords; + coords.clear(); + for (int32_t i = 0; i < fdp.ConsumeIntegralInRange<int32_t>(0, MAX_AXES); i++) { + coords.setAxisValue(fdp.ConsumeIntegral<int32_t>(), fdp.ConsumeFloatingPoint<float>()); + } + + const nsecs_t downTime = 2; + const nsecs_t readTime = downTime + fdp.ConsumeIntegralInRange<nsecs_t>(0, 1E8); + NotifyMotionArgs motionArgs(fdp.ConsumeIntegral<uint32_t>() /*sequenceNum*/, + downTime /*eventTime*/, readTime, + fdp.ConsumeIntegral<int32_t>() /*deviceId*/, AINPUT_SOURCE_ANY, + ADISPLAY_ID_DEFAULT, + fdp.ConsumeIntegral<uint32_t>() /*policyFlags*/, + AMOTION_EVENT_ACTION_DOWN, + fdp.ConsumeIntegral<int32_t>() /*actionButton*/, + fdp.ConsumeIntegral<int32_t>() /*flags*/, AMETA_NONE, + fdp.ConsumeIntegral<int32_t>() /*buttonState*/, + MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, + 1 /*pointerCount*/, &properties, &coords, + fdp.ConsumeFloatingPoint<float>() /*xPrecision*/, + fdp.ConsumeFloatingPoint<float>() /*yPrecision*/, + AMOTION_EVENT_INVALID_CURSOR_POSITION, + AMOTION_EVENT_INVALID_CURSOR_POSITION, downTime, + {} /*videoFrames*/); + return motionArgs; +} + +extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) { + FuzzedDataProvider fdp(data, size); + + std::unique_ptr<FuzzInputListener> mFuzzListener = std::make_unique<FuzzInputListener>(); + std::unique_ptr<InputProcessorInterface> mClassifier = + std::make_unique<InputProcessor>(*mFuzzListener); + + while (fdp.remaining_bytes() > 0) { + fdp.PickValueInArray<std::function<void()>>({ + [&]() -> void { + // SendToNextStage_NotifyConfigurationChangedArgs + NotifyConfigurationChangedArgs + args(fdp.ConsumeIntegral<uint32_t>() /*sequenceNum*/, + fdp.ConsumeIntegral<nsecs_t>() /*eventTime*/); + mClassifier->notifyConfigurationChanged(&args); + }, + [&]() -> void { + // SendToNextStage_NotifyKeyArgs + const nsecs_t eventTime = fdp.ConsumeIntegral<nsecs_t>(); + const nsecs_t readTime = + eventTime + fdp.ConsumeIntegralInRange<nsecs_t>(0, 1E8); + NotifyKeyArgs keyArgs(fdp.ConsumeIntegral<uint32_t>() /*sequenceNum*/, + eventTime, readTime, + fdp.ConsumeIntegral<int32_t>() /*deviceId*/, + AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_DEFAULT, + fdp.ConsumeIntegral<uint32_t>() /*policyFlags*/, + AKEY_EVENT_ACTION_DOWN, + fdp.ConsumeIntegral<int32_t>() /*flags*/, AKEYCODE_HOME, + fdp.ConsumeIntegral<int32_t>() /*scanCode*/, AMETA_NONE, + fdp.ConsumeIntegral<nsecs_t>() /*downTime*/); + + mClassifier->notifyKey(&keyArgs); + }, + [&]() -> void { + // SendToNextStage_NotifyMotionArgs + NotifyMotionArgs motionArgs = generateFuzzedMotionArgs(fdp); + mClassifier->notifyMotion(&motionArgs); + }, + [&]() -> void { + // SendToNextStage_NotifySwitchArgs + NotifySwitchArgs switchArgs(fdp.ConsumeIntegral<uint32_t>() /*sequenceNum*/, + fdp.ConsumeIntegral<nsecs_t>() /*eventTime*/, + fdp.ConsumeIntegral<uint32_t>() /*policyFlags*/, + fdp.ConsumeIntegral<uint32_t>() /*switchValues*/, + fdp.ConsumeIntegral<uint32_t>() /*switchMask*/); + + mClassifier->notifySwitch(&switchArgs); + }, + [&]() -> void { + // SendToNextStage_NotifyDeviceResetArgs + NotifyDeviceResetArgs resetArgs(fdp.ConsumeIntegral<uint32_t>() /*sequenceNum*/, + fdp.ConsumeIntegral<nsecs_t>() /*eventTime*/, + fdp.ConsumeIntegral<int32_t>() /*deviceId*/); + + mClassifier->notifyDeviceReset(&resetArgs); + }, + [&]() -> void { + // InputClassifierConverterTest + const NotifyMotionArgs motionArgs = generateFuzzedMotionArgs(fdp); + aidl::android::hardware::input::common::MotionEvent motionEvent = + notifyMotionArgsToHalMotionEvent(motionArgs); + }, + })(); + } + return 0; +} + +} // namespace android 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 |