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