• 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 <devices.h>
18 #include <firmware_handler.h>
19 #include <fuzzer/FuzzedDataProvider.h>
20 #include <modalias_handler.h>
21 #include <sys/stat.h>
22 #include <util.h>
23 #include <fstream>
24 
25 using namespace android;
26 using namespace android::init;
27 constexpr int32_t kMaxBytes = 100;
28 constexpr int32_t kMaxSize = 1000;
29 constexpr int32_t kMinSize = 1;
30 
31 /*'HandleUevent' prefixes the path with '/sys' and hence this is required to point
32  * to'/data/local/tmp' dir.*/
33 const std::string kPath = "/../data/local/tmp/";
34 const std::string kPathPrefix = "/..";
35 
MakeFile(FuzzedDataProvider * fdp,std::string s)36 void MakeFile(FuzzedDataProvider* fdp, std::string s) {
37     std::ofstream out;
38     out.open(s, std::ios::binary | std::ofstream::trunc);
39     for (int32_t idx = 0; idx < fdp->ConsumeIntegralInRange(kMinSize, kMaxSize); ++idx) {
40         out << fdp->ConsumeRandomLengthString(kMaxBytes) << "\n";
41     }
42     out.close();
43 }
44 
CreateDir(std::string Directory,FuzzedDataProvider * fdp)45 void CreateDir(std::string Directory, FuzzedDataProvider* fdp) {
46     std::string tmp = Directory.substr(kPathPrefix.length());
47     mkdir_recursive(android::base::Dirname(tmp.c_str()),
48                     S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
49     MakeFile(fdp, tmp + "/data");
50     MakeFile(fdp, tmp + "/loading");
51 }
52 
SelectRandomString(FuzzedDataProvider * fdp,std::string s)53 std::string SelectRandomString(FuzzedDataProvider* fdp, std::string s) {
54     if (fdp->ConsumeBool()) {
55         if (fdp->ConsumeBool()) {
56             return fdp->ConsumeRandomLengthString(kMaxBytes);
57         } else {
58             return s;
59         }
60     }
61     return "";
62 }
63 
CreateUevent(FuzzedDataProvider * fdp)64 Uevent CreateUevent(FuzzedDataProvider* fdp) {
65     Uevent uevent;
66     uevent.action = SelectRandomString(fdp, "add");
67     uevent.subsystem = SelectRandomString(fdp, "firmware");
68     uevent.path = SelectRandomString(fdp, kPath + fdp->ConsumeRandomLengthString(kMaxBytes));
69     uevent.firmware = fdp->ConsumeBool() ? fdp->ConsumeRandomLengthString(kMaxBytes) : "";
70     uevent.partition_name = fdp->ConsumeBool() ? fdp->ConsumeRandomLengthString(kMaxBytes) : "";
71     uevent.device_name = fdp->ConsumeBool() ? fdp->ConsumeRandomLengthString(kMaxBytes) : "";
72     uevent.modalias = fdp->ConsumeBool() ? fdp->ConsumeRandomLengthString(kMaxBytes) : "";
73     uevent.partition_num = fdp->ConsumeIntegral<int32_t>();
74     uevent.major = fdp->ConsumeIntegral<int32_t>();
75     uevent.minor = fdp->ConsumeIntegral<int32_t>();
76     return uevent;
77 }
78 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)79 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
80     FuzzedDataProvider fdp(data, size);
81     while (fdp.remaining_bytes()) {
82         auto invoke_uevent_handler_fuzzer = fdp.PickValueInArray<const std::function<void()>>({
83                 [&]() {
84                     std::vector<std::string> modalias_vector;
85                     for (size_t idx = 0;
86                          idx < fdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize); ++idx) {
87                         modalias_vector.push_back(fdp.ConsumeRandomLengthString(kMaxBytes));
88                     }
89                     ModaliasHandler modalias_handler = ModaliasHandler(modalias_vector);
90                     modalias_handler.HandleUevent(CreateUevent(&fdp));
91                 },
92                 [&]() {
93                     std::vector<ExternalFirmwareHandler> external_handlers;
94                     std::vector<std::string> firmware_directories;
95                     for (size_t idx = 0;
96                          idx < fdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize); ++idx) {
97                         std::string devPath = fdp.ConsumeRandomLengthString(kMaxBytes);
98                         uid_t uid = fdp.ConsumeIntegral<uid_t>();
99                         gid_t gid = fdp.ConsumeIntegral<gid_t>();
100                         std::string handlerPath = fdp.ConsumeRandomLengthString(kMaxBytes);
101                         ExternalFirmwareHandler externalFirmwareHandler =
102                                 ExternalFirmwareHandler(devPath, uid, gid, handlerPath);
103                         external_handlers.push_back(externalFirmwareHandler);
104                         firmware_directories.push_back(fdp.ConsumeRandomLengthString(kMaxBytes));
105                     }
106                     FirmwareHandler firmware_handler =
107                             FirmwareHandler(firmware_directories, external_handlers);
108                     Uevent uevent = CreateUevent(&fdp);
109                     if (fdp.ConsumeBool() && uevent.path.size() != 0 &&
110                         uevent.path.find(kPath) == 0) {
111                         CreateDir(uevent.path, &fdp);
112                         firmware_handler.HandleUevent(uevent);
113                         std::string s = uevent.path.substr(kPathPrefix.length());
114                         remove(s.c_str());
115                     } else {
116                         firmware_handler.HandleUevent(uevent);
117                     }
118                 },
119         });
120         invoke_uevent_handler_fuzzer();
121     }
122     return 0;
123 }
124