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