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 <fuzzer/FuzzedDataProvider.h>
22 #include <utils/String16.h>
23
24 using namespace android;
25
26 constexpr uint16_t kFeasibleTypes[] = {
27 MTP_TYPE_UNDEFINED, MTP_TYPE_INT8, MTP_TYPE_UINT8, MTP_TYPE_INT16, MTP_TYPE_UINT16,
28 MTP_TYPE_INT32, MTP_TYPE_UINT32, MTP_TYPE_INT64, MTP_TYPE_UINT64, MTP_TYPE_INT128,
29 MTP_TYPE_UINT128, MTP_TYPE_AINT8, MTP_TYPE_AUINT8, MTP_TYPE_AINT16, MTP_TYPE_AUINT16,
30 MTP_TYPE_AINT32, MTP_TYPE_AUINT32, MTP_TYPE_AINT64, MTP_TYPE_AUINT64, MTP_TYPE_AINT128,
31 MTP_TYPE_AUINT128, MTP_TYPE_STR,
32 };
33
34 class MtpPropertyFuzzer : MtpPacketFuzzerUtils {
35 public:
MtpPropertyFuzzer(const uint8_t * data,size_t size)36 MtpPropertyFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) {
37 mUsbDevFsUrb = (struct usbdevfs_urb*)malloc(sizeof(struct usbdevfs_urb) +
38 sizeof(struct usbdevfs_iso_packet_desc));
39 };
~MtpPropertyFuzzer()40 ~MtpPropertyFuzzer() { free(mUsbDevFsUrb); };
41 void process();
42
43 private:
44 FuzzedDataProvider mFdp;
45 };
46
process()47 void MtpPropertyFuzzer::process() {
48 MtpProperty* mtpProperty = nullptr;
49 if (mFdp.ConsumeBool()) {
50 mtpProperty = new MtpProperty();
51 } else {
52 uint16_t type = mFdp.ConsumeBool() ? mFdp.ConsumeIntegral<uint16_t>()
53 : mFdp.PickValueInArray<uint16_t>(kFeasibleTypes);
54 mtpProperty = new MtpProperty(mFdp.ConsumeIntegral<uint16_t>(), type, mFdp.ConsumeBool(),
55 mFdp.ConsumeIntegral<uint16_t>());
56 }
57
58 while (mFdp.remaining_bytes() > 0) {
59 auto invokeMtpPropertyFuzzer = mFdp.PickValueInArray<const std::function<void()>>({
60 [&]() {
61 MtpDataPacket mtpDataPacket;
62 if (mFdp.ConsumeBool()) {
63 mtpProperty->read(mtpDataPacket);
64
65 } else {
66 if (mFdp.ConsumeBool()) {
67 #ifdef MTP_DEVICE
68 android::IMtpHandle* h = new MtpDevHandle();
69 h->start(mFdp.ConsumeBool());
70 std::string text = mFdp.ConsumeRandomLengthString(kMaxLength);
71 char* data = const_cast<char*>(text.c_str());
72 h->read(static_cast<void*>(data), text.length());
73 mtpDataPacket.write(h);
74 h->close();
75 delete h;
76 #endif
77
78 #ifdef MTP_HOST
79 fillFilePath(&mFdp);
80 int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING);
81 fillUsbRequest(fd, &mFdp);
82 mUsbRequest.dev = usb_device_new(mPath.c_str(), fd);
83 mtpDataPacket.write(&mUsbRequest,
84 mFdp.PickValueInArray<UrbPacketDivisionMode>(
85 kUrbPacketDivisionModes),
86 fd,
87 mFdp.ConsumeIntegralInRange(kMinSize, kMaxSize));
88 usb_device_close(mUsbRequest.dev);
89 #endif
90 }
91
92 if (mFdp.ConsumeBool()) {
93 mtpProperty->write(mtpDataPacket);
94 } else {
95 mtpProperty->setCurrentValue(mtpDataPacket);
96 }
97 }
98 },
99 [&]() {
100 char16_t* data = nullptr;
101 std::string str = mFdp.ConsumeRandomLengthString(kMaxLength);
102 android::String16 s(str.c_str());
103 if (mFdp.ConsumeBool()) {
104 data = const_cast<char16_t*>(s.string());
105 }
106
107 if (mFdp.ConsumeBool()) {
108 mtpProperty->setDefaultValue(reinterpret_cast<uint16_t*>(data));
109 } else if (mFdp.ConsumeBool()) {
110 mtpProperty->setCurrentValue(reinterpret_cast<uint16_t*>(data));
111 } else {
112 mtpProperty->setCurrentValue(str.c_str());
113 }
114 },
115 [&]() {
116 mtpProperty->setFormRange(mFdp.ConsumeIntegral<int32_t>(),
117 mFdp.ConsumeIntegral<int32_t>(),
118 mFdp.ConsumeIntegral<int32_t>());
119 },
120 [&]() {
121 std::vector<int32_t> init;
122 for (size_t idx = 0; idx < mFdp.ConsumeIntegralInRange(kMinSize, kMaxSize);
123 ++idx) {
124 init.push_back(mFdp.ConsumeIntegral<int32_t>());
125 }
126 mtpProperty->setFormEnum(init.data(), init.size());
127 },
128 });
129 invokeMtpPropertyFuzzer();
130 }
131
132 delete (mtpProperty);
133 }
134
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)135 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
136 MtpPropertyFuzzer mtpPropertyFuzzer(data, size);
137 mtpPropertyFuzzer.process();
138 return 0;
139 }
140