1 /*
2 * Copyright (C) 2022 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
17 #include <MtpDataPacket.h>
18 #include <MtpDevHandle.h>
19 #include <MtpPacketFuzzerUtils.h>
20 #include <MtpProperty.h>
21 #include <functional>
22 #include <fuzzer/FuzzedDataProvider.h>
23 #include <utils/String16.h>
24
25 using namespace android;
26
27 constexpr uint16_t kFeasibleTypes[] = {
28 MTP_TYPE_UNDEFINED, MTP_TYPE_INT8, MTP_TYPE_UINT8, MTP_TYPE_INT16, MTP_TYPE_UINT16,
29 MTP_TYPE_INT32, MTP_TYPE_UINT32, MTP_TYPE_INT64, MTP_TYPE_UINT64, MTP_TYPE_INT128,
30 MTP_TYPE_UINT128, MTP_TYPE_AINT8, MTP_TYPE_AUINT8, MTP_TYPE_AINT16, MTP_TYPE_AUINT16,
31 MTP_TYPE_AINT32, MTP_TYPE_AUINT32, MTP_TYPE_AINT64, MTP_TYPE_AUINT64, MTP_TYPE_AINT128,
32 MTP_TYPE_AUINT128, MTP_TYPE_STR,
33 };
34
35 class MtpPropertyFuzzer : MtpPacketFuzzerUtils {
36 public:
MtpPropertyFuzzer(const uint8_t * data,size_t size)37 MtpPropertyFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) {
38 mUsbDevFsUrb = (struct usbdevfs_urb*)malloc(sizeof(struct usbdevfs_urb) +
39 sizeof(struct usbdevfs_iso_packet_desc));
40 };
~MtpPropertyFuzzer()41 ~MtpPropertyFuzzer() { free(mUsbDevFsUrb); };
42 void process();
43
44 private:
45 FuzzedDataProvider mFdp;
46 };
47
process()48 void MtpPropertyFuzzer::process() {
49 MtpProperty* mtpProperty = nullptr;
50 if (mFdp.ConsumeBool()) {
51 mtpProperty = new MtpProperty();
52 } else {
53 uint16_t type = mFdp.ConsumeBool() ? mFdp.ConsumeIntegral<uint16_t>()
54 : mFdp.PickValueInArray<uint16_t>(kFeasibleTypes);
55 mtpProperty = new MtpProperty(mFdp.ConsumeIntegral<uint16_t>(), type, mFdp.ConsumeBool(),
56 mFdp.ConsumeIntegral<uint16_t>());
57 }
58
59 while (mFdp.remaining_bytes() > 0) {
60 auto invokeMtpPropertyFuzzer = mFdp.PickValueInArray<const std::function<void()>>({
61 [&]() {
62 MtpDataPacket mtpDataPacket;
63 if (mFdp.ConsumeBool()) {
64 mtpProperty->read(mtpDataPacket);
65
66 } else {
67 if (mFdp.ConsumeBool()) {
68 #ifdef MTP_DEVICE
69 android::IMtpHandle* h = new MtpDevHandle();
70 h->start(mFdp.ConsumeBool());
71 std::string text = mFdp.ConsumeRandomLengthString(kMaxLength);
72 char* data = const_cast<char*>(text.c_str());
73 h->read(static_cast<void*>(data), text.length());
74 mtpDataPacket.write(h);
75 h->close();
76 delete h;
77 #endif
78
79 #ifdef MTP_HOST
80 fillFilePath(&mFdp);
81 int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING);
82 fillUsbRequest(fd, &mFdp);
83 mUsbRequest.dev = usb_device_new(mPath.c_str(), fd);
84 mtpDataPacket.write(&mUsbRequest,
85 mFdp.PickValueInArray<UrbPacketDivisionMode>(
86 kUrbPacketDivisionModes),
87 fd,
88 mFdp.ConsumeIntegralInRange(kMinSize, kMaxSize));
89 usb_device_close(mUsbRequest.dev);
90 #endif
91 }
92
93 if (mFdp.ConsumeBool()) {
94 mtpProperty->write(mtpDataPacket);
95 } else {
96 mtpProperty->setCurrentValue(mtpDataPacket);
97 }
98 }
99 },
100 [&]() {
101 char16_t* data = nullptr;
102 std::string str = mFdp.ConsumeRandomLengthString(kMaxLength);
103 android::String16 s(str.c_str());
104 if (mFdp.ConsumeBool()) {
105 data = const_cast<char16_t*>(s.c_str());
106 }
107
108 if (mFdp.ConsumeBool()) {
109 mtpProperty->setDefaultValue(reinterpret_cast<uint16_t*>(data));
110 } else if (mFdp.ConsumeBool()) {
111 mtpProperty->setCurrentValue(reinterpret_cast<uint16_t*>(data));
112 } else {
113 mtpProperty->setCurrentValue(str.c_str());
114 }
115 },
116 [&]() {
117 mtpProperty->setFormRange(mFdp.ConsumeIntegral<int32_t>(),
118 mFdp.ConsumeIntegral<int32_t>(),
119 mFdp.ConsumeIntegral<int32_t>());
120 },
121 [&]() {
122 std::vector<int32_t> init;
123 for (size_t idx = 0; idx < mFdp.ConsumeIntegralInRange(kMinSize, kMaxSize);
124 ++idx) {
125 init.push_back(mFdp.ConsumeIntegral<int32_t>());
126 }
127 mtpProperty->setFormEnum(init.data(), init.size());
128 },
129 });
130 invokeMtpPropertyFuzzer();
131 }
132
133 delete (mtpProperty);
134 }
135
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)136 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
137 MtpPropertyFuzzer mtpPropertyFuzzer(data, size);
138 mtpPropertyFuzzer.process();
139 return 0;
140 }
141