diff options
| author | 2020-05-12 00:41:30 -0700 | |
|---|---|---|
| committer | 2022-08-30 10:29:18 +0000 | |
| commit | b8d9326f7586f47d7771c7d1e7bafd35d1b6c82e (patch) | |
| tree | 889a812656fab6bff7217fcc1484a65f9f19b815 | |
| parent | 26d49f7f39a05fe1773354ae1d49cad6454c82cb (diff) | |
Add initial batch of inputFlinger fuzzers
This batch of fuzzers is focused on the input Mappers. These fuzzers are
not host_supported, and must be run on-device. Followup CLs containing
additional inputflinger fuzzers will rely on the FuzzContainer.h and
MapperHelpers.h header files.
Fuzzers included:
- CursorInputFuzzer
- KeyboardInputFuzzer
- MultiTouchInputFuzzer
- SwitchInputFuzzer
Test: Tested on a pixel 3a with HWASAN. Accurate % coverage information is
not available due to the large number of shared libraries included
in runs built with hwasan interfering with PC Count information
(increasing the total PC count to ~682,000).
Summary of updates:
Coverage improvements: 75% to 82%
Design changes:
[1] Refactored
- CursorInputFuzzer
- KeyboardInputFuzzer
- MultiTouchInputFuzzer
- SwitchInputFuzzer
in order to generate event as a combination of valid and invalid input.
[2] Used FuzzedDataProvider to generate values for events.
Signed-off-by: Michael Ensing <michael.ensing@leviathansecurity.com>
Change-Id: Id39205c691f54c516f8a452293cb098382019335
| -rw-r--r-- | libs/input/PropertyMap.cpp | 2 | ||||
| -rw-r--r-- | services/inputflinger/tests/fuzzers/Android.bp | 71 | ||||
| -rw-r--r-- | services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp | 96 | ||||
| -rw-r--r-- | services/inputflinger/tests/fuzzers/FuzzContainer.h | 82 | ||||
| -rw-r--r-- | services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp | 110 | ||||
| -rw-r--r-- | services/inputflinger/tests/fuzzers/MapperHelpers.h | 372 | ||||
| -rw-r--r-- | services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp | 134 | ||||
| -rw-r--r-- | services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp | 61 |
8 files changed, 927 insertions, 1 deletions
diff --git a/libs/input/PropertyMap.cpp b/libs/input/PropertyMap.cpp index 662e568ac0..16ffa10223 100644 --- a/libs/input/PropertyMap.cpp +++ b/libs/input/PropertyMap.cpp @@ -75,7 +75,7 @@ bool PropertyMap::tryGetProperty(const std::string& key, int32_t& outValue) cons } char* end; - int value = strtol(stringValue.c_str(), &end, 10); + int32_t value = static_cast<int32_t>(strtol(stringValue.c_str(), &end, 10)); if (*end != '\0') { ALOGW("Property key '%s' has invalid value '%s'. Expected an integer.", key.c_str(), stringValue.c_str()); diff --git a/services/inputflinger/tests/fuzzers/Android.bp b/services/inputflinger/tests/fuzzers/Android.bp index 455a1e2133..a53db00282 100644 --- a/services/inputflinger/tests/fuzzers/Android.bp +++ b/services/inputflinger/tests/fuzzers/Android.bp @@ -46,3 +46,74 @@ cc_fuzz { cc: ["android-framework-input@google.com"], }, } + +cc_defaults { + name: "inputflinger_fuzz_defaults", + defaults: [ + "inputflinger_defaults", + ], + include_dirs: [ + "frameworks/native/services/inputflinger", + ], + shared_libs: [ + "android.hardware.input.classifier@1.0", + "libbase", + "libbinder", + "libcutils", + "liblog", + "libutils", + "libui", + "libinput", + "libinputflinger", + "libinputreader", + "libinputflinger_base", + "libstatslog", + ], + header_libs: [ + "libbatteryservice_headers", + "libinputreader_headers", + ], + fuzz_config: { + cc: ["android-framework-input@google.com"], + }, +} + +cc_fuzz { + name: "inputflinger_cursor_input_fuzzer", + defaults: [ + "inputflinger_fuzz_defaults", + ], + srcs: [ + "CursorInputFuzzer.cpp", + ], +} + +cc_fuzz { + name: "inputflinger_keyboard_input_fuzzer", + defaults: [ + "inputflinger_fuzz_defaults", + ], + srcs: [ + "KeyboardInputFuzzer.cpp", + ], +} + +cc_fuzz { + name: "inputflinger_multitouch_input_fuzzer", + defaults: [ + "inputflinger_fuzz_defaults", + ], + srcs: [ + "MultiTouchInputFuzzer.cpp", + ], +} + +cc_fuzz { + name: "inputflinger_switch_input_fuzzer", + defaults: [ + "inputflinger_fuzz_defaults", + ], + srcs: [ + "SwitchInputFuzzer.cpp", + ], +} diff --git a/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp new file mode 100644 index 0000000000..4b542aab19 --- /dev/null +++ b/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp @@ -0,0 +1,96 @@ +/* + * 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 <CursorInputMapper.h> +#include <FuzzContainer.h> +#include <fuzzer/FuzzedDataProvider.h> + +namespace android { + +static void addProperty(FuzzContainer& fuzzer, std::shared_ptr<FuzzedDataProvider> fdp) { + // Pick a random property to set for the mapper to have set. + fdp->PickValueInArray<std::function<void()>>( + {[&]() -> void { fuzzer.addProperty("cursor.mode", "pointer"); }, + [&]() -> void { fuzzer.addProperty("cursor.mode", "navigation"); }, + [&]() -> void { + fuzzer.addProperty("cursor.mode", fdp->ConsumeRandomLengthString(100).data()); + }, + [&]() -> void { + fuzzer.addProperty("cursor.orientationAware", + fdp->ConsumeRandomLengthString(100).data()); + }})(); +} + +extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { + std::shared_ptr<FuzzedDataProvider> fdp = std::make_shared<FuzzedDataProvider>(data, size); + FuzzContainer fuzzer(fdp); + + CursorInputMapper& mapper = fuzzer.getMapper<CursorInputMapper>(); + auto policyConfig = fuzzer.getPolicyConfig(); + + // Loop through mapper operations until randomness is exhausted. + while (fdp->remaining_bytes() > 0) { + fdp->PickValueInArray<std::function<void()>>({ + [&]() -> void { addProperty(fuzzer, fdp); }, + [&]() -> void { + std::string dump; + mapper.dump(dump); + }, + [&]() -> void { mapper.getSources(); }, + [&]() -> void { + mapper.configure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, + fdp->ConsumeIntegral<int32_t>()); + }, + [&]() -> void { + // Need to reconfigure with 0 or you risk a NPE. + mapper.configure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, 0); + InputDeviceInfo info; + mapper.populateDeviceInfo(&info); + }, + [&]() -> void { + int32_t type, code; + type = fdp->ConsumeBool() ? fdp->PickValueInArray(kValidTypes) + : fdp->ConsumeIntegral<int32_t>(); + code = fdp->ConsumeBool() ? fdp->PickValueInArray(kValidCodes) + : fdp->ConsumeIntegral<int32_t>(); + + // Need to reconfigure with 0 or you risk a NPE. + mapper.configure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, 0); + RawEvent rawEvent{fdp->ConsumeIntegral<nsecs_t>(), + fdp->ConsumeIntegral<nsecs_t>(), + fdp->ConsumeIntegral<int32_t>(), + type, + code, + fdp->ConsumeIntegral<int32_t>()}; + mapper.process(&rawEvent); + }, + [&]() -> void { mapper.reset(fdp->ConsumeIntegral<nsecs_t>()); }, + [&]() -> void { + mapper.getScanCodeState(fdp->ConsumeIntegral<uint32_t>(), + fdp->ConsumeIntegral<int32_t>()); + }, + [&]() -> void { + // Need to reconfigure with 0 or you risk a NPE. + mapper.configure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, 0); + mapper.getAssociatedDisplayId(); + }, + })(); + } + + return 0; +} + +} // namespace android diff --git a/services/inputflinger/tests/fuzzers/FuzzContainer.h b/services/inputflinger/tests/fuzzers/FuzzContainer.h new file mode 100644 index 0000000000..62615d0116 --- /dev/null +++ b/services/inputflinger/tests/fuzzers/FuzzContainer.h @@ -0,0 +1,82 @@ +/* + * 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. + */ + +#pragma once + +#include <InputDevice.h> +#include <InputMapper.h> +#include <InputReader.h> +#include <MapperHelpers.h> +#include <fuzzer/FuzzedDataProvider.h> + +namespace android { + +class FuzzContainer { + std::shared_ptr<FuzzEventHub> mFuzzEventHub; + sp<FuzzInputReaderPolicy> mFuzzPolicy; + std::unique_ptr<FuzzInputListener> mFuzzListener; + std::unique_ptr<FuzzInputReaderContext> mFuzzContext; + std::unique_ptr<InputDevice> mFuzzDevice; + InputReaderConfiguration mPolicyConfig; + std::shared_ptr<FuzzedDataProvider> mFdp; + +public: + FuzzContainer(std::shared_ptr<FuzzedDataProvider> fdp) : mFdp(fdp) { + // Setup parameters. + std::string deviceName = mFdp->ConsumeRandomLengthString(16); + std::string deviceLocation = mFdp->ConsumeRandomLengthString(12); + int32_t deviceID = mFdp->ConsumeIntegralInRange<int32_t>(0, 5); + int32_t deviceGeneration = mFdp->ConsumeIntegralInRange<int32_t>(/*from*/ 0, /*to*/ 5); + + // Create mocked objects. + mFuzzEventHub = std::make_shared<FuzzEventHub>(mFdp); + mFuzzPolicy = sp<FuzzInputReaderPolicy>::make(mFdp); + mFuzzListener = std::make_unique<FuzzInputListener>(); + mFuzzContext = std::make_unique<FuzzInputReaderContext>(mFuzzEventHub, mFuzzPolicy, + *mFuzzListener, mFdp); + + InputDeviceIdentifier identifier; + identifier.name = deviceName; + identifier.location = deviceLocation; + mFuzzDevice = std::make_unique<InputDevice>(mFuzzContext.get(), deviceID, deviceGeneration, + identifier); + mFuzzPolicy->getReaderConfiguration(&mPolicyConfig); + } + + ~FuzzContainer() {} + + void configureDevice() { + nsecs_t arbitraryTime = mFdp->ConsumeIntegral<nsecs_t>(); + mFuzzDevice->configure(arbitraryTime, &mPolicyConfig, 0); + mFuzzDevice->reset(arbitraryTime); + } + + void addProperty(std::string key, std::string value) { + mFuzzEventHub->addProperty(key, value); + configureDevice(); + } + + InputReaderConfiguration& getPolicyConfig() { return mPolicyConfig; } + + template <class T, typename... Args> + T& getMapper(Args... args) { + T& mapper = mFuzzDevice->addMapper<T>(mFdp->ConsumeIntegral<int32_t>(), args...); + configureDevice(); + return mapper; + } +}; + +} // namespace android diff --git a/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp new file mode 100644 index 0000000000..c48a099bca --- /dev/null +++ b/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp @@ -0,0 +1,110 @@ +/* + * 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 <FuzzContainer.h> +#include <KeyboardInputMapper.h> +#include <fuzzer/FuzzedDataProvider.h> + +namespace android { + +const int32_t kMaxKeycodes = 100; + +static void addProperty(FuzzContainer& fuzzer, std::shared_ptr<FuzzedDataProvider> fdp) { + // Pick a random property to set for the mapper to have set. + fdp->PickValueInArray<std::function<void()>>( + {[&]() -> void { fuzzer.addProperty("keyboard.orientationAware", "1"); }, + [&]() -> void { + fuzzer.addProperty("keyboard.orientationAware", + fdp->ConsumeRandomLengthString(100).data()); + }, + [&]() -> void { + fuzzer.addProperty("keyboard.doNotWakeByDefault", + fdp->ConsumeRandomLengthString(100).data()); + }, + [&]() -> void { + fuzzer.addProperty("keyboard.handlesKeyRepeat", + fdp->ConsumeRandomLengthString(100).data()); + }})(); +} + +extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { + std::shared_ptr<FuzzedDataProvider> fdp = std::make_shared<FuzzedDataProvider>(data, size); + FuzzContainer fuzzer(fdp); + + KeyboardInputMapper& mapper = + fuzzer.getMapper<KeyboardInputMapper>(fdp->ConsumeIntegral<uint32_t>(), + fdp->ConsumeIntegral<int32_t>()); + auto policyConfig = fuzzer.getPolicyConfig(); + + // Loop through mapper operations until randomness is exhausted. + while (fdp->remaining_bytes() > 0) { + fdp->PickValueInArray<std::function<void()>>({ + [&]() -> void { addProperty(fuzzer, fdp); }, + [&]() -> void { + std::string dump; + mapper.dump(dump); + }, + [&]() -> void { + InputDeviceInfo info; + mapper.populateDeviceInfo(&info); + }, + [&]() -> void { mapper.getSources(); }, + [&]() -> void { + mapper.configure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, + fdp->ConsumeIntegral<uint32_t>()); + }, + [&]() -> void { mapper.reset(fdp->ConsumeIntegral<nsecs_t>()); }, + [&]() -> void { + int32_t type, code; + type = fdp->ConsumeBool() ? fdp->PickValueInArray(kValidTypes) + : fdp->ConsumeIntegral<int32_t>(); + code = fdp->ConsumeBool() ? fdp->PickValueInArray(kValidCodes) + : fdp->ConsumeIntegral<int32_t>(); + RawEvent rawEvent{fdp->ConsumeIntegral<nsecs_t>(), + fdp->ConsumeIntegral<nsecs_t>(), + fdp->ConsumeIntegral<int32_t>(), + type, + code, + fdp->ConsumeIntegral<int32_t>()}; + mapper.process(&rawEvent); + }, + [&]() -> void { + mapper.getKeyCodeState(fdp->ConsumeIntegral<uint32_t>(), + fdp->ConsumeIntegral<int32_t>()); + }, + [&]() -> void { + mapper.getScanCodeState(fdp->ConsumeIntegral<uint32_t>(), + fdp->ConsumeIntegral<int32_t>()); + }, + [&]() -> void { + std::vector<int32_t> keyCodes; + int32_t numBytes = fdp->ConsumeIntegralInRange<int32_t>(0, kMaxKeycodes); + for (int32_t i = 0; i < numBytes; ++i) { + keyCodes.push_back(fdp->ConsumeIntegral<int32_t>()); + } + mapper.markSupportedKeyCodes(fdp->ConsumeIntegral<uint32_t>(), keyCodes, + nullptr); + }, + [&]() -> void { mapper.getMetaState(); }, + [&]() -> void { mapper.updateMetaState(fdp->ConsumeIntegral<int32_t>()); }, + [&]() -> void { mapper.getAssociatedDisplayId(); }, + })(); + } + + return 0; +} + +} // namespace android diff --git a/services/inputflinger/tests/fuzzers/MapperHelpers.h b/services/inputflinger/tests/fuzzers/MapperHelpers.h new file mode 100644 index 0000000000..53a7b169e4 --- /dev/null +++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h @@ -0,0 +1,372 @@ +/* + * 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. + */ + +#pragma once + +#include <InputDevice.h> +#include <InputMapper.h> +#include <InputReader.h> +#include <fuzzer/FuzzedDataProvider.h> +#include "android/hardware/input/InputDeviceCountryCode.h" + +using android::hardware::input::InputDeviceCountryCode; + +constexpr size_t kValidTypes[] = {EV_SW, + EV_SYN, + SYN_REPORT, + EV_ABS, + EV_KEY, + EV_MSC, + EV_REL, + android::EventHubInterface::DEVICE_ADDED, + android::EventHubInterface::DEVICE_REMOVED, + android::EventHubInterface::FINISHED_DEVICE_SCAN}; + +constexpr size_t kValidCodes[] = { + SYN_REPORT, + ABS_MT_SLOT, + SYN_MT_REPORT, + ABS_MT_POSITION_X, + ABS_MT_POSITION_Y, + ABS_MT_TOUCH_MAJOR, + ABS_MT_TOUCH_MINOR, + ABS_MT_WIDTH_MAJOR, + ABS_MT_WIDTH_MINOR, + ABS_MT_ORIENTATION, + ABS_MT_TRACKING_ID, + ABS_MT_PRESSURE, + ABS_MT_DISTANCE, + ABS_MT_TOOL_TYPE, + SYN_MT_REPORT, + MSC_SCAN, + REL_X, + REL_Y, + REL_WHEEL, + REL_HWHEEL, + BTN_LEFT, + BTN_RIGHT, + BTN_MIDDLE, + BTN_BACK, + BTN_SIDE, + BTN_FORWARD, + BTN_EXTRA, + BTN_TASK, +}; + +constexpr InputDeviceCountryCode kCountryCodes[] = { + InputDeviceCountryCode::INVALID, + InputDeviceCountryCode::NOT_SUPPORTED, + InputDeviceCountryCode::ARABIC, + InputDeviceCountryCode::BELGIAN, + InputDeviceCountryCode::CANADIAN_BILINGUAL, + InputDeviceCountryCode::CANADIAN_FRENCH, + InputDeviceCountryCode::CZECH_REPUBLIC, + InputDeviceCountryCode::DANISH, + InputDeviceCountryCode::FINNISH, + InputDeviceCountryCode::FRENCH, + InputDeviceCountryCode::GERMAN, + InputDeviceCountryCode::GREEK, + InputDeviceCountryCode::HEBREW, + InputDeviceCountryCode::HUNGARY, + InputDeviceCountryCode::INTERNATIONAL, + InputDeviceCountryCode::ITALIAN, + InputDeviceCountryCode::JAPAN, + InputDeviceCountryCode::KOREAN, + InputDeviceCountryCode::LATIN_AMERICAN, + InputDeviceCountryCode::DUTCH, + InputDeviceCountryCode::NORWEGIAN, + InputDeviceCountryCode::PERSIAN, + InputDeviceCountryCode::POLAND, + InputDeviceCountryCode::PORTUGUESE, + InputDeviceCountryCode::RUSSIA, + InputDeviceCountryCode::SLOVAKIA, + InputDeviceCountryCode::SPANISH, + InputDeviceCountryCode::SWEDISH, + InputDeviceCountryCode::SWISS_FRENCH, + InputDeviceCountryCode::SWISS_GERMAN, + InputDeviceCountryCode::SWITZERLAND, + InputDeviceCountryCode::TAIWAN, + InputDeviceCountryCode::TURKISH_Q, + InputDeviceCountryCode::UK, + InputDeviceCountryCode::US, + InputDeviceCountryCode::YUGOSLAVIA, + InputDeviceCountryCode::TURKISH_F, +}; + +constexpr size_t kMaxSize = 256; + +namespace android { + +class FuzzEventHub : public EventHubInterface { + InputDeviceIdentifier mIdentifier; + std::vector<TouchVideoFrame> mVideoFrames; + PropertyMap mFuzzConfig; + size_t mCount = 0; + std::array<RawEvent, kMaxSize> mBuf; + std::shared_ptr<FuzzedDataProvider> mFdp; + +public: + FuzzEventHub(std::shared_ptr<FuzzedDataProvider> fdp) : mFdp(std::move(fdp)) {} + ~FuzzEventHub() {} + void addProperty(std::string key, std::string value) { mFuzzConfig.addProperty(key, value); } + void addEvents(std::shared_ptr<FuzzedDataProvider> fdp) { + mCount = fdp->ConsumeIntegralInRange<size_t>(0, kMaxSize); + + for (size_t i = 0; i < mCount; ++i) { + int32_t type = fdp->ConsumeBool() ? fdp->PickValueInArray(kValidTypes) + : fdp->ConsumeIntegral<int32_t>(); + int32_t code = fdp->ConsumeBool() ? fdp->PickValueInArray(kValidCodes) + : fdp->ConsumeIntegral<int32_t>(); + mBuf[i] = {fdp->ConsumeIntegral<nsecs_t>(), + fdp->ConsumeIntegral<nsecs_t>(), + fdp->ConsumeIntegral<int32_t>(), + type, + code, + fdp->ConsumeIntegral<int32_t>()}; + } + } + + ftl::Flags<InputDeviceClass> getDeviceClasses(int32_t deviceId) const override { + return ftl::Flags<InputDeviceClass>(mFdp->ConsumeIntegral<uint32_t>()); + } + InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const override { + return mIdentifier; + } + int32_t getDeviceControllerNumber(int32_t deviceId) const override { + return mFdp->ConsumeIntegral<int32_t>(); + } + void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const override { + *outConfiguration = mFuzzConfig; + } + status_t getAbsoluteAxisInfo(int32_t deviceId, int axis, + RawAbsoluteAxisInfo* outAxisInfo) const override { + return mFdp->ConsumeIntegral<status_t>(); + } + bool hasRelativeAxis(int32_t deviceId, int axis) const override { return mFdp->ConsumeBool(); } + bool hasInputProperty(int32_t deviceId, int property) const override { + return mFdp->ConsumeBool(); + } + bool hasMscEvent(int32_t deviceId, int mscEvent) const override { return mFdp->ConsumeBool(); } + status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t metaState, + int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const override { + return mFdp->ConsumeIntegral<status_t>(); + } + status_t mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxisInfo) const override { + return mFdp->ConsumeIntegral<status_t>(); + } + void setExcludedDevices(const std::vector<std::string>& devices) override {} + size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) override { + for (size_t i = 0; i < mCount; ++i) buffer[i] = mBuf[i]; + + return mCount; + } + std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) override { return mVideoFrames; } + + base::Result<std::pair<InputDeviceSensorType, int32_t>> mapSensor( + int32_t deviceId, int32_t absCode) const override { + return base::ResultError("Fuzzer", UNKNOWN_ERROR); + }; + // Raw batteries are sysfs power_supply nodes we found from the EventHub device sysfs node, + // containing the raw info of the sysfs node structure. + std::vector<int32_t> getRawBatteryIds(int32_t deviceId) const override { return {}; } + std::optional<RawBatteryInfo> getRawBatteryInfo(int32_t deviceId, + int32_t BatteryId) const override { + return std::nullopt; + }; + + std::vector<int32_t> getRawLightIds(int32_t deviceId) const override { return {}; }; + std::optional<RawLightInfo> getRawLightInfo(int32_t deviceId, int32_t lightId) const override { + return std::nullopt; + }; + std::optional<int32_t> getLightBrightness(int32_t deviceId, int32_t lightId) const override { + return std::nullopt; + }; + void setLightBrightness(int32_t deviceId, int32_t lightId, int32_t brightness) override{}; + std::optional<std::unordered_map<LightColor, int32_t>> getLightIntensities( + int32_t deviceId, int32_t lightId) const override { + return std::nullopt; + }; + void setLightIntensities(int32_t deviceId, int32_t lightId, + std::unordered_map<LightColor, int32_t> intensities) override{}; + + InputDeviceCountryCode getCountryCode(int32_t deviceId) const override { + return mFdp->PickValueInArray<InputDeviceCountryCode>(kCountryCodes); + }; + + int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const override { + return mFdp->ConsumeIntegral<int32_t>(); + } + int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const override { + return mFdp->ConsumeIntegral<int32_t>(); + } + int32_t getSwitchState(int32_t deviceId, int32_t sw) const override { + return mFdp->ConsumeIntegral<int32_t>(); + } + int32_t getKeyCodeForKeyLocation(int32_t deviceId, int32_t locationKeyCode) const override { + return mFdp->ConsumeIntegral<int32_t>(); + } + status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis, + int32_t* outValue) const override { + return mFdp->ConsumeIntegral<status_t>(); + } + bool markSupportedKeyCodes(int32_t deviceId, const std::vector<int32_t>& keyCodes, + uint8_t* outFlags) const override { + return mFdp->ConsumeBool(); + } + bool hasScanCode(int32_t deviceId, int32_t scanCode) const override { + return mFdp->ConsumeBool(); + } + bool hasKeyCode(int32_t deviceId, int32_t keyCode) const override { + return mFdp->ConsumeBool(); + } + bool hasLed(int32_t deviceId, int32_t led) const override { return mFdp->ConsumeBool(); } + void setLedState(int32_t deviceId, int32_t led, bool on) override {} + void getVirtualKeyDefinitions( + int32_t deviceId, std::vector<VirtualKeyDefinition>& outVirtualKeys) const override {} + const std::shared_ptr<KeyCharacterMap> getKeyCharacterMap(int32_t deviceId) const override { + return nullptr; + } + bool setKeyboardLayoutOverlay(int32_t deviceId, std::shared_ptr<KeyCharacterMap> map) override { + return mFdp->ConsumeBool(); + } + void vibrate(int32_t deviceId, const VibrationElement& effect) override {} + void cancelVibrate(int32_t deviceId) override {} + + std::vector<int32_t> getVibratorIds(int32_t deviceId) const override { return {}; }; + + /* Query battery level. */ + std::optional<int32_t> getBatteryCapacity(int32_t deviceId, int32_t batteryId) const override { + return std::nullopt; + }; + + /* Query battery status. */ + std::optional<int32_t> getBatteryStatus(int32_t deviceId, int32_t batteryId) const override { + return std::nullopt; + }; + + void requestReopenDevices() override {} + void wake() override {} + void dump(std::string& dump) const override {} + void monitor() const override {} + bool isDeviceEnabled(int32_t deviceId) const override { return mFdp->ConsumeBool(); } + status_t enableDevice(int32_t deviceId) override { return mFdp->ConsumeIntegral<status_t>(); } + status_t disableDevice(int32_t deviceId) override { return mFdp->ConsumeIntegral<status_t>(); } +}; + +class FuzzPointerController : public PointerControllerInterface { + std::shared_ptr<FuzzedDataProvider> mFdp; + +public: + FuzzPointerController(std::shared_ptr<FuzzedDataProvider> mFdp) : mFdp(mFdp) {} + ~FuzzPointerController() {} + bool getBounds(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const override { + return mFdp->ConsumeBool(); + } + void move(float deltaX, float deltaY) override {} + void setButtonState(int32_t buttonState) override {} + int32_t getButtonState() const override { return mFdp->ConsumeIntegral<int32_t>(); } + void setPosition(float x, float y) override {} + void getPosition(float* outX, float* outY) const override {} + void fade(Transition transition) override {} + void unfade(Transition transition) override {} + void setPresentation(Presentation presentation) override {} + void setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex, + BitSet32 spotIdBits, int32_t displayId) override {} + void clearSpots() override {} + int32_t getDisplayId() const override { return mFdp->ConsumeIntegral<int32_t>(); } + void setDisplayViewport(const DisplayViewport& displayViewport) override {} +}; + +class FuzzInputReaderPolicy : public InputReaderPolicyInterface { + TouchAffineTransformation mTransform; + std::shared_ptr<FuzzPointerController> mPointerController; + std::shared_ptr<FuzzedDataProvider> mFdp; + +protected: + ~FuzzInputReaderPolicy() {} + +public: + FuzzInputReaderPolicy(std::shared_ptr<FuzzedDataProvider> mFdp) : mFdp(mFdp) { + mPointerController = std::make_shared<FuzzPointerController>(mFdp); + } + void getReaderConfiguration(InputReaderConfiguration* outConfig) override {} + std::shared_ptr<PointerControllerInterface> obtainPointerController(int32_t deviceId) override { + return mPointerController; + } + void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices) override {} + std::shared_ptr<KeyCharacterMap> getKeyboardLayoutOverlay( + const InputDeviceIdentifier& identifier) override { + return nullptr; + } + std::string getDeviceAlias(const InputDeviceIdentifier& identifier) { + return mFdp->ConsumeRandomLengthString(32); + } + TouchAffineTransformation getTouchAffineTransformation(const std::string& inputDeviceDescriptor, + int32_t surfaceRotation) override { + return mTransform; + } + void setTouchAffineTransformation(const TouchAffineTransformation t) { mTransform = t; } +}; + +class FuzzInputListener : public virtual InputListenerInterface { +public: + void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override {} + void notifyKey(const NotifyKeyArgs* args) override {} + void notifyMotion(const NotifyMotionArgs* args) override {} + void notifySwitch(const NotifySwitchArgs* args) override {} + void notifySensor(const NotifySensorArgs* args) override{}; + void notifyVibratorState(const NotifyVibratorStateArgs* args) override{}; + void notifyDeviceReset(const NotifyDeviceResetArgs* args) override {} + void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override{}; +}; + +class FuzzInputReaderContext : public InputReaderContext { + std::shared_ptr<EventHubInterface> mEventHub; + sp<InputReaderPolicyInterface> mPolicy; + InputListenerInterface& mListener; + std::shared_ptr<FuzzedDataProvider> mFdp; + +public: + FuzzInputReaderContext(std::shared_ptr<EventHubInterface> eventHub, + const sp<InputReaderPolicyInterface>& policy, + InputListenerInterface& listener, + std::shared_ptr<FuzzedDataProvider> mFdp) + : mEventHub(eventHub), mPolicy(policy), mListener(listener), mFdp(mFdp) {} + ~FuzzInputReaderContext() {} + void updateGlobalMetaState() override {} + int32_t getGlobalMetaState() { return mFdp->ConsumeIntegral<int32_t>(); } + void disableVirtualKeysUntil(nsecs_t time) override {} + bool shouldDropVirtualKey(nsecs_t now, int32_t keyCode, int32_t scanCode) override { + return mFdp->ConsumeBool(); + } + void fadePointer() override {} + std::shared_ptr<PointerControllerInterface> getPointerController(int32_t deviceId) override { + return mPolicy->obtainPointerController(0); + } + void requestTimeoutAtTime(nsecs_t when) override {} + int32_t bumpGeneration() override { return mFdp->ConsumeIntegral<int32_t>(); } + void getExternalStylusDevices(std::vector<InputDeviceInfo>& outDevices) override {} + void dispatchExternalStylusState(const StylusState& outState) override {} + InputReaderPolicyInterface* getPolicy() override { return mPolicy.get(); } + InputListenerInterface& getListener() override { return mListener; } + EventHubInterface* getEventHub() override { return mEventHub.get(); } + int32_t getNextId() override { return mFdp->ConsumeIntegral<int32_t>(); } + + void updateLedMetaState(int32_t metaState) override{}; + int32_t getLedMetaState() override { return mFdp->ConsumeIntegral<int32_t>(); }; +}; + +} // namespace android diff --git a/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp new file mode 100644 index 0000000000..59b064249a --- /dev/null +++ b/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp @@ -0,0 +1,134 @@ +/* + * 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 <FuzzContainer.h> +#include <MultiTouchInputMapper.h> +#include <fuzzer/FuzzedDataProvider.h> + +namespace android { + +const int32_t kMaxKeycodes = 100; + +static void addProperty(FuzzContainer& fuzzer, std::shared_ptr<FuzzedDataProvider> fdp) { + // Pick a random property to set for the mapper to have set. + fdp->PickValueInArray<std::function<void()>>( + {[&]() -> void { fuzzer.addProperty("touch.deviceType", "touchScreen"); }, + [&]() -> void { + fuzzer.addProperty("touch.deviceType", fdp->ConsumeRandomLengthString(8).data()); + }, + [&]() -> void { + fuzzer.addProperty("touch.size.scale", fdp->ConsumeRandomLengthString(8).data()); + }, + [&]() -> void { + fuzzer.addProperty("touch.size.bias", fdp->ConsumeRandomLengthString(8).data()); + }, + [&]() -> void { + fuzzer.addProperty("touch.size.isSummed", + fdp->ConsumeRandomLengthString(8).data()); + }, + [&]() -> void { + fuzzer.addProperty("touch.size.calibration", + fdp->ConsumeRandomLengthString(8).data()); + }, + [&]() -> void { + fuzzer.addProperty("touch.pressure.scale", + fdp->ConsumeRandomLengthString(8).data()); + }, + [&]() -> void { + fuzzer.addProperty("touch.size.calibration", + fdp->ConsumeBool() ? "diameter" : "area"); + }, + [&]() -> void { + fuzzer.addProperty("touch.pressure.calibration", + fdp->ConsumeRandomLengthString(8).data()); + }})(); +} + +extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { + std::shared_ptr<FuzzedDataProvider> fdp = std::make_shared<FuzzedDataProvider>(data, size); + FuzzContainer fuzzer(fdp); + + MultiTouchInputMapper& mapper = fuzzer.getMapper<MultiTouchInputMapper>(); + auto policyConfig = fuzzer.getPolicyConfig(); + + // Loop through mapper operations until randomness is exhausted. + while (fdp->remaining_bytes() > 0) { + fdp->PickValueInArray<std::function<void()>>({ + [&]() -> void { addProperty(fuzzer, fdp); }, + [&]() -> void { + std::string dump; + mapper.dump(dump); + }, + [&]() -> void { + InputDeviceInfo info; + mapper.populateDeviceInfo(&info); + }, + [&]() -> void { mapper.getSources(); }, + [&]() -> void { + mapper.configure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, + fdp->ConsumeIntegral<uint32_t>()); + }, + [&]() -> void { mapper.reset(fdp->ConsumeIntegral<nsecs_t>()); }, + [&]() -> void { + int32_t type = fdp->ConsumeBool() ? fdp->PickValueInArray(kValidTypes) + : fdp->ConsumeIntegral<int32_t>(); + int32_t code = fdp->ConsumeBool() ? fdp->PickValueInArray(kValidCodes) + : fdp->ConsumeIntegral<int32_t>(); + RawEvent rawEvent{fdp->ConsumeIntegral<nsecs_t>(), + fdp->ConsumeIntegral<nsecs_t>(), + fdp->ConsumeIntegral<int32_t>(), + type, + code, + fdp->ConsumeIntegral<int32_t>()}; + mapper.process(&rawEvent); + }, + [&]() -> void { + mapper.getKeyCodeState(fdp->ConsumeIntegral<uint32_t>(), + fdp->ConsumeIntegral<int32_t>()); + }, + [&]() -> void { + mapper.getScanCodeState(fdp->ConsumeIntegral<uint32_t>(), + fdp->ConsumeIntegral<int32_t>()); + }, + [&]() -> void { + std::vector<int32_t> keyCodes; + int32_t numBytes = fdp->ConsumeIntegralInRange<int32_t>(0, kMaxKeycodes); + for (int32_t i = 0; i < numBytes; ++i) { + keyCodes.push_back(fdp->ConsumeIntegral<int32_t>()); + } + mapper.markSupportedKeyCodes(fdp->ConsumeIntegral<uint32_t>(), keyCodes, + nullptr); + }, + [&]() -> void { + mapper.cancelTouch(fdp->ConsumeIntegral<nsecs_t>(), + fdp->ConsumeIntegral<nsecs_t>()); + }, + [&]() -> void { mapper.timeoutExpired(fdp->ConsumeIntegral<nsecs_t>()); }, + [&]() -> void { + StylusState state{fdp->ConsumeIntegral<nsecs_t>(), + fdp->ConsumeFloatingPoint<float>(), + fdp->ConsumeIntegral<uint32_t>(), + fdp->ConsumeIntegral<int32_t>()}; + mapper.updateExternalStylusState(state); + }, + [&]() -> void { mapper.getAssociatedDisplayId(); }, + })(); + } + + return 0; +} + +} // namespace android diff --git a/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp new file mode 100644 index 0000000000..e76bd728b8 --- /dev/null +++ b/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp @@ -0,0 +1,61 @@ +/* + * 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 <FuzzContainer.h> +#include <SwitchInputMapper.h> +#include <fuzzer/FuzzedDataProvider.h> + +namespace android { + +extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { + std::shared_ptr<FuzzedDataProvider> fdp = std::make_shared<FuzzedDataProvider>(data, size); + FuzzContainer fuzzer(fdp); + + SwitchInputMapper& mapper = fuzzer.getMapper<SwitchInputMapper>(); + auto policyConfig = fuzzer.getPolicyConfig(); + + // Loop through mapper operations until randomness is exhausted. + while (fdp->remaining_bytes() > 0) { + fdp->PickValueInArray<std::function<void()>>({ + [&]() -> void { + std::string dump; + mapper.dump(dump); + }, + [&]() -> void { mapper.getSources(); }, + [&]() -> void { + int32_t type = fdp->ConsumeBool() ? fdp->PickValueInArray(kValidTypes) + : fdp->ConsumeIntegral<int32_t>(); + int32_t code = fdp->ConsumeBool() ? fdp->PickValueInArray(kValidCodes) + : fdp->ConsumeIntegral<int32_t>(); + RawEvent rawEvent{fdp->ConsumeIntegral<nsecs_t>(), + fdp->ConsumeIntegral<nsecs_t>(), + fdp->ConsumeIntegral<int32_t>(), + type, + code, + fdp->ConsumeIntegral<int32_t>()}; + mapper.process(&rawEvent); + }, + [&]() -> void { + mapper.getSwitchState(fdp->ConsumeIntegral<uint32_t>(), + fdp->ConsumeIntegral<int32_t>()); + }, + })(); + } + + return 0; +} + +} // namespace android |