• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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                                                     &parameters);
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