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 <MtpDevHandle.h>
18 #include <MtpDevice.h>
19 #include <MtpDeviceInfo.h>
20 #include <MtpObjectInfo.h>
21 #include <MtpProperty.h>
22 #include <MtpStorageInfo.h>
23 #include <MtpStringBuffer.h>
24 #include <android-base/unique_fd.h>
25 #include <fcntl.h>
26 #include <functional>
27 #include <fuzzer/FuzzedDataProvider.h>
28 #include <linux/usb/ch9.h>
29 #include <sys/mman.h>
30 #include <unistd.h>
31 #include <usbhost/usbhost.h>
32
33 using namespace android;
34
35 constexpr int32_t kMaxStringLength = 20;
36 constexpr int32_t kMaxBytes = 200;
37 constexpr int32_t kMaxDataSize = 20;
38 constexpr uint16_t kWMaxPacketSize = 64;
39 constexpr uint16_t kEndpointsCount = 3;
40 const std::string kInputFile = "/dev/null";
41 const std::string kConfigFilePath = "/data/local/tmp/config";
42
readCallback(void * data,uint32_t offset,uint32_t length,void * clientData)43 static bool readCallback(void* data, uint32_t offset, uint32_t length, void* clientData) {
44 return true;
45 }
46
47 struct fdDescriptors {
48 struct usb_interface_descriptor interface;
49 struct usb_endpoint_descriptor ep[kEndpointsCount];
50 };
51
writeDescriptorsToFd(int32_t fd,FuzzedDataProvider & fdp)52 fdDescriptors writeDescriptorsToFd(int32_t fd, FuzzedDataProvider& fdp) {
53 fdDescriptors desc;
54 desc.interface.bLength = sizeof(desc.interface);
55 desc.interface.bDescriptorType = USB_DT_INTERFACE;
56 desc.interface.bInterfaceNumber = fdp.ConsumeIntegral<uint8_t>();
57 desc.interface.bNumEndpoints = kEndpointsCount;
58 desc.interface.bInterfaceClass =
59 fdp.ConsumeBool() ? USB_CLASS_STILL_IMAGE : USB_CLASS_VENDOR_SPEC;
60 desc.interface.bInterfaceSubClass = fdp.ConsumeBool() ? 1 : 0xFF;
61 desc.interface.bInterfaceProtocol = fdp.ConsumeBool() ? 1 : 0;
62 desc.interface.iInterface = fdp.ConsumeIntegral<uint8_t>();
63 for (uint16_t idx = 0; idx < kEndpointsCount; ++idx) {
64 desc.ep[idx].bLength = sizeof(desc.ep[idx]);
65 desc.ep[idx].bDescriptorType = USB_DT_ENDPOINT;
66 desc.ep[idx].bEndpointAddress = idx | (fdp.ConsumeBool() ? USB_DIR_OUT : USB_DIR_IN);
67 desc.ep[idx].bmAttributes =
68 fdp.ConsumeBool() ? USB_ENDPOINT_XFER_BULK : USB_ENDPOINT_XFER_INT;
69 desc.ep[idx].wMaxPacketSize = kWMaxPacketSize;
70 }
71 write(fd, &desc, sizeof(fdDescriptors));
72 return desc;
73 }
74
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)75 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
76 FuzzedDataProvider fdp(data, size);
77 int32_t fd = memfd_create(kConfigFilePath.c_str(), MFD_ALLOW_SEALING);
78 fdDescriptors descriptor = writeDescriptorsToFd(fd, fdp);
79 std::string deviceName = fdp.ConsumeRandomLengthString(kMaxStringLength);
80 usb_device* device = usb_device_new(deviceName.c_str(), fd);
81 MtpDevice mtpDevice(device, fdp.ConsumeIntegral<int32_t>(), &descriptor.ep[0],
82 &descriptor.ep[1], &descriptor.ep[2]);
83 while (fdp.remaining_bytes()) {
84 auto mtpDeviceFunction = fdp.PickValueInArray<const std::function<void()>>(
85 {[&]() { mtpDevice.getStorageIDs(); },
86 [&]() {
87 mtpDevice.getStorageInfo(fdp.ConsumeIntegral<int32_t>() /* storageID */);
88 },
89 [&]() {
90 mtpDevice.getObjectHandles(fdp.ConsumeIntegral<uint32_t>() /* storageID */,
91 fdp.ConsumeIntegral<uint16_t>() /* format */,
92 fdp.ConsumeIntegral<uint32_t>() /* parent */);
93 },
94 [&]() { mtpDevice.initialize(); },
95 [&]() {
96 int32_t outLength = 0;
97 mtpDevice.getThumbnail(fdp.ConsumeIntegral<uint32_t>() /* handle */,
98 outLength);
99 },
100 [&]() {
101 MtpObjectInfo mtpObjectInfo(fdp.ConsumeIntegral<uint32_t>() /* handle */);
102 std::string name = fdp.ConsumeRandomLengthString(kMaxStringLength);
103 std::string keywords = fdp.ConsumeRandomLengthString(kMaxStringLength);
104 mtpObjectInfo.mName = strdup(name.c_str());
105 mtpObjectInfo.mKeywords = strdup(keywords.c_str());
106 mtpDevice.sendObjectInfo(&mtpObjectInfo);
107 },
108 [&]() {
109 mtpDevice.sendObject(fdp.ConsumeIntegral<uint32_t>() /* handle */,
110 fdp.ConsumeIntegral<uint32_t>() /* size */, fd);
111 },
112 [&]() { mtpDevice.deleteObject(fdp.ConsumeIntegral<uint32_t>() /* handle */); },
113 [&]() {
114 mtpDevice.getObjectPropsSupported(
115 fdp.ConsumeIntegral<uint16_t>() /* format */);
116 },
117 [&]() {
118 MtpDataType dataType = fdp.ConsumeIntegral<int16_t>();
119 MtpProperty mtpProperty(fdp.ConsumeIntegral<int16_t>() /* propCode */,
120 dataType, fdp.ConsumeBool() /* writeable */,
121 fdp.ConsumeIntegral<int32_t>() /* defaultValue */);
122 if (dataType == MTP_TYPE_STR) {
123 mtpProperty.setCurrentValue(
124 fdp.ConsumeRandomLengthString(kMaxStringLength).c_str());
125 }
126 mtpDevice.setDevicePropValueStr(&mtpProperty);
127 },
128 [&]() {
129 mtpDevice.getObjectPropDesc(fdp.ConsumeIntegral<uint16_t>() /* code */,
130 fdp.ConsumeIntegral<uint16_t>() /* format */);
131 },
132 [&]() {
133 MtpProperty property;
134 mtpDevice.getObjectPropValue(fdp.ConsumeIntegral<uint16_t>() /* handle */,
135 &property);
136 },
137 [&]() {
138 std::vector<uint8_t> clientData = fdp.ConsumeBytes<uint8_t>(kMaxDataSize);
139 mtpDevice.readObject(
140 fdp.ConsumeIntegral<uint32_t>() /* handle */, readCallback,
141 fdp.ConsumeIntegral<uint32_t>() /* objectSize */, &clientData);
142 },
143 [&]() {
144 std::vector<uint8_t> clientData = fdp.ConsumeBytes<uint8_t>(kMaxDataSize);
145 uint32_t writtenSize = 0;
146 mtpDevice.readPartialObject(fdp.ConsumeIntegral<uint32_t>() /* handle */,
147 fdp.ConsumeIntegral<uint32_t>() /* offset */,
148 fdp.ConsumeIntegral<uint32_t>() /* size */,
149 &writtenSize, readCallback, &clientData);
150 },
151 [&]() {
152 std::vector<uint8_t> clientData = fdp.ConsumeBytes<uint8_t>(kMaxDataSize);
153 uint32_t writtenSize = 0;
154 mtpDevice.readPartialObject(fdp.ConsumeIntegral<uint32_t>() /* handle */,
155 fdp.ConsumeIntegral<uint64_t>() /* offset */,
156 fdp.ConsumeIntegral<uint32_t>() /* size */,
157 &writtenSize, readCallback, &clientData);
158 },
159 [&]() {
160 if (mtpDevice.submitEventRequest() != -1) {
161 uint32_t parameters[3];
162 mtpDevice.reapEventRequest(fdp.ConsumeIntegral<int32_t>() /* handle */,
163 ¶meters);
164 }
165 },
166 [&]() {
167 mtpDevice.discardEventRequest(fdp.ConsumeIntegral<int32_t>() /*handle*/);
168 },
169 [&]() {
170 mtpDevice.discardEventRequest(fdp.ConsumeIntegral<int32_t>() /* handle */);
171 },
172 [&]() { mtpDevice.print(); },
173 [&]() { mtpDevice.getDeviceName(); },
174 [&]() { mtpDevice.getObjectInfo(fdp.ConsumeIntegral<uint32_t>() /* handle */); },
175 [&]() { mtpDevice.getParent(fdp.ConsumeIntegral<uint32_t>() /* handle */); },
176 [&]() { mtpDevice.getStorageID(fdp.ConsumeIntegral<uint32_t>() /* handle */); },
177 [&]() { mtpDevice.getDevicePropDesc(fdp.ConsumeIntegral<uint16_t>() /* code */); },
178 [&]() {
179 mtpDevice.readObject(
180 fdp.ConsumeIntegral<uint32_t>() /* handle */,
181 fdp.ConsumeRandomLengthString(kMaxStringLength).c_str() /* destPath */,
182 fdp.ConsumeIntegral<int32_t>() /* group */,
183 fdp.ConsumeIntegral<int32_t>() /* perm */);
184 },
185 [&]() {
186 int32_t filefd = open(kConfigFilePath.c_str(), O_CREAT | O_RDWR);
187 mtpDevice.readObject(fdp.ConsumeIntegral<uint16_t>() /* handle */, filefd);
188 close(filefd);
189 },
190 [&]() { MtpDevice::open(deviceName.c_str(), fd); },
191 [&]() {
192 MtpObjectInfo objectinfo(fdp.ConsumeIntegral<uint32_t>() /* handle */);
193 MtpDataPacket mtpDataPacket;
194 MtpDevHandle devHandle;
195 std::vector<uint8_t> packet = fdp.ConsumeBytes<uint8_t>(kMaxBytes);
196 mtpDataPacket.writeData(&devHandle, packet.data(), packet.size());
197 objectinfo.read(mtpDataPacket);
198 objectinfo.print();
199 },
200 [&]() {
201 MtpStorageInfo storageInfo(fdp.ConsumeIntegral<uint32_t>() /* id */);
202 MtpDataPacket mtpDataPacket;
203 MtpDevHandle devHandle;
204 std::vector<uint8_t> packet = fdp.ConsumeBytes<uint8_t>(kMaxBytes);
205 mtpDataPacket.writeData(&devHandle, packet.data(), packet.size());
206 storageInfo.read(mtpDataPacket);
207 storageInfo.print();
208 }});
209 mtpDeviceFunction();
210 }
211 close(fd);
212 return 0;
213 }
214