xref: /aosp_15_r20/frameworks/av/media/mtp/tests/MtpFuzzer/mtp_device_fuzzer.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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                                                     &parameters);
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