1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "faultloggerdserver_fuzzer.h"
17 
18 #include <cstddef>
19 #include <cstdint>
20 #include <unistd.h>
21 #include <sys/socket.h>
22 
23 #include "dfx_exception.h"
24 #include "dfx_util.h"
25 #include "faultloggerd_client.h"
26 #include "faultloggerd_fuzzertest_common.h"
27 #include "fault_logger_config.h"
28 #define private public
29 #include "fault_logger_daemon.h"
30 #undef private
31 
32 namespace OHOS {
33 namespace HiviewDFX {
34 constexpr int32_t FAULTLOGGERD_FUZZ_READ_BUFF = 1024;
35 
ReadThread1(void * param)36 void *ReadThread1(void *param)
37 {
38     int fd = static_cast<int>(reinterpret_cast<long>(param));
39     char buff[FAULTLOGGERD_FUZZ_READ_BUFF];
40     OHOS_TEMP_FAILURE_RETRY(read(fd, buff, sizeof(buff)));
41     char msg[] = "any test str";
42     OHOS_TEMP_FAILURE_RETRY(write(fd, reinterpret_cast<char*>(msg), sizeof(msg)));
43     return nullptr;
44 }
45 
ReadThread2(void * param)46 void *ReadThread2(void *param)
47 {
48     int fd = static_cast<int>(reinterpret_cast<long>(param));
49     char buff[FAULTLOGGERD_FUZZ_READ_BUFF];
50     OHOS_TEMP_FAILURE_RETRY(read(fd, buff, sizeof(buff)));
51     CrashDumpException test;
52     test.error = CRASH_DUMP_LOCAL_REPORT;
53     OHOS_TEMP_FAILURE_RETRY(write(fd, reinterpret_cast<char*>(&test), sizeof(CrashDumpException)));
54     return nullptr;
55 }
56 
ReadThread3(void * param)57 void *ReadThread3(void *param)
58 {
59     int fd = static_cast<int>(reinterpret_cast<long>(param));
60     char buff[FAULTLOGGERD_FUZZ_READ_BUFF];
61     OHOS_TEMP_FAILURE_RETRY(read(fd, buff, sizeof(buff)));
62     CrashDumpException test{};
63     OHOS_TEMP_FAILURE_RETRY(write(fd, reinterpret_cast<char*>(&test), sizeof(CrashDumpException)));
64     return nullptr;
65 }
66 
HandleRequestTestCommon(std::shared_ptr<FaultLoggerDaemon> daemon,char * buff,size_t len,void * (* startRoutine)(void *))67 void HandleRequestTestCommon(std::shared_ptr<FaultLoggerDaemon> daemon, char* buff, size_t len,
68     void *(*startRoutine)(void *))
69 {
70     int socketFd[2]; // 2 : the length of the array
71     if (socketpair(AF_UNIX, SOCK_STREAM, 0, socketFd) == 0) {
72         OHOS_TEMP_FAILURE_RETRY(write(socketFd[1], buff, len));
73         daemon->connectionMap_[socketFd[0]] = socketFd[0];
74 
75         if (!startRoutine) {
76             daemon->HandleRequest(0, socketFd[0]);
77         } else {
78             pthread_t threadId;
79             if (pthread_create(&threadId, nullptr, startRoutine, reinterpret_cast<void*>(socketFd[1])) != 0) {
80                 perror("Failed to create thread");
81                 close(socketFd[0]);
82                 close(socketFd[1]);
83                 return;
84             }
85 
86             daemon->HandleRequest(0, socketFd[0]);
87 
88             pthread_join(threadId, nullptr);
89         }
90         close(socketFd[1]);
91     }
92 }
93 
InitStatsRequests(const uint8_t * data,size_t size)94 std::vector<FaultLoggerdStatsRequest> InitStatsRequests(const uint8_t* data, size_t size)
95 {
96     std::vector<FaultLoggerdStatsRequest> statsRequest;
97     {
98         FaultLoggerdStatsRequest requst{};
99         requst.type = PROCESS_DUMP;
100         requst.signalTime = GetTimeMilliSeconds();
101         requst.pid = 1;
102         requst.processdumpStartTime = time(nullptr);
103         requst.processdumpFinishTime = time(nullptr) + 10; // 10 : Get the last 10 seconds of the current time
104         statsRequest.emplace_back(requst);
105     }
106     {
107         FaultLoggerdStatsRequest requst{};
108         auto lastRequst = statsRequest.back();
109         requst.type = DUMP_CATCHER;
110         requst.pid = lastRequst.pid;
111         requst.requestTime = time(nullptr);
112         requst.dumpCatcherFinishTime = time(nullptr) + 10; // 10 : Get the last 10 seconds of the current time
113         requst.result = 1;
114         statsRequest.emplace_back(requst);
115     }
116     {
117         FaultLoggerdStatsRequest requst{};
118         requst.type = DUMP_CATCHER;
119         requst.pid = 1;
120         requst.requestTime = time(nullptr);
121         requst.dumpCatcherFinishTime = time(nullptr) + 10; // 10 : Get the last 10 seconds of the current time
122         requst.result = 1;
123         statsRequest.emplace_back(requst);
124     }
125     return statsRequest;
126 }
127 
HandleRequestByClientTypeForDefaultClientTest(std::shared_ptr<FaultLoggerDaemon> daemon)128 void HandleRequestByClientTypeForDefaultClientTest(std::shared_ptr<FaultLoggerDaemon> daemon)
129 {
130     FaultLoggerdRequest requst;
131     requst.clientType = FaultLoggerClientType::DEFAULT_CLIENT;
132     HandleRequestTestCommon(daemon, reinterpret_cast<char*>(&requst), sizeof(FaultLoggerdRequest), nullptr);
133     requst.type = FaultLoggerType::CPP_CRASH;
134     HandleRequestTestCommon(daemon, reinterpret_cast<char*>(&requst), sizeof(FaultLoggerdRequest), nullptr);
135     requst.type = FaultLoggerType::JS_HEAP_SNAPSHOT;
136     HandleRequestTestCommon(daemon, reinterpret_cast<char*>(&requst), sizeof(FaultLoggerdRequest), nullptr);
137     daemon->crashTimeMap_[1] = time(nullptr) - 10; // 10 : Get the first 10 seconds of the current time
138     HandleRequestTestCommon(daemon, reinterpret_cast<char*>(&requst), sizeof(FaultLoggerdRequest), nullptr);
139     daemon->crashTimeMap_[1] = time(nullptr);
140     HandleRequestTestCommon(daemon, reinterpret_cast<char*>(&requst), sizeof(FaultLoggerdRequest), nullptr);
141 }
142 
HandleRequestByClientTypeTest(std::shared_ptr<FaultLoggerDaemon> daemon)143 void HandleRequestByClientTypeTest(std::shared_ptr<FaultLoggerDaemon> daemon)
144 {
145     HandleRequestByClientTypeForDefaultClientTest(daemon);
146     {
147         FaultLoggerdRequest requst;
148         requst.clientType = FaultLoggerClientType::LOG_FILE_DES_CLIENT;
149         HandleRequestTestCommon(daemon, reinterpret_cast<char*>(&requst), sizeof(FaultLoggerdRequest), nullptr);
150     }
151     {
152         FaultLoggerdRequest requst;
153         requst.clientType = FaultLoggerClientType::PRINT_T_HILOG_CLIENT;
154         HandleRequestTestCommon(daemon, reinterpret_cast<char*>(&requst), sizeof(FaultLoggerdRequest), ReadThread2);
155     }
156     {
157         FaultLoggerdRequest requst;
158         requst.clientType = FaultLoggerClientType::PERMISSION_CLIENT;
159         HandleRequestTestCommon(daemon, reinterpret_cast<char*>(&requst), sizeof(FaultLoggerdRequest), ReadThread2);
160     }
161     {
162         FaultLoggerdRequest requst;
163         requst.clientType = FaultLoggerClientType::SDK_DUMP_CLIENT;
164         requst.pid = 1;
165         HandleRequestTestCommon(daemon, reinterpret_cast<char*>(&requst), sizeof(FaultLoggerdRequest), ReadThread2);
166     }
167     {
168         FaultLoggerdRequest requst;
169         requst.clientType = FaultLoggerClientType::PIPE_FD_CLIENT;
170         HandleRequestTestCommon(daemon, reinterpret_cast<char*>(&requst), sizeof(FaultLoggerdRequest), nullptr);
171     }
172     {
173         FaultLoggerdRequest requst;
174         requst.clientType = FaultLoggerClientType::REPORT_EXCEPTION_CLIENT;
175         HandleRequestTestCommon(daemon, reinterpret_cast<char*>(&requst), sizeof(FaultLoggerdRequest), ReadThread1);
176         HandleRequestTestCommon(daemon, reinterpret_cast<char*>(&requst), sizeof(FaultLoggerdRequest), ReadThread2);
177         HandleRequestTestCommon(daemon, reinterpret_cast<char*>(&requst), sizeof(FaultLoggerdRequest), ReadThread3);
178     }
179     {
180         FaultLoggerdRequest requst;
181         requst.clientType = -1;
182         HandleRequestTestCommon(daemon, reinterpret_cast<char*>(&requst), sizeof(FaultLoggerdRequest), nullptr);
183     }
184 }
185 
HandStaticTest(std::shared_ptr<FaultLoggerDaemon> daemon)186 void HandStaticTest(std::shared_ptr<FaultLoggerDaemon> daemon)
187 {
188     daemon->HandleStaticForFuzzer(FaultLoggerType::CPP_STACKTRACE, 0);
189     daemon->HandleStaticForFuzzer(FaultLoggerType::JS_STACKTRACE, 0);
190     daemon->HandleStaticForFuzzer(FaultLoggerType::LEAK_STACKTRACE, 1);
191     daemon->HandleStaticForFuzzer(FaultLoggerType::FFRT_CRASH_LOG, 1);
192     daemon->HandleStaticForFuzzer(FaultLoggerType::JIT_CODE_LOG, 1);
193 }
194 
CheckReadResp(int sockfd)195 bool CheckReadResp(int sockfd)
196 {
197     char controlBuffer[SOCKET_BUFFER_SIZE] = {0};
198     ssize_t nread = OHOS_TEMP_FAILURE_RETRY(read(sockfd, controlBuffer, sizeof(controlBuffer) - 1));
199     if (nread != static_cast<ssize_t>(strlen(FAULTLOGGER_DAEMON_RESP))) {
200         return false;
201     }
202     return true;
203 }
204 
HandleRequestByPipeTypeCommon(std::shared_ptr<FaultLoggerDaemon> daemon,int32_t pipeType,bool isPassCheck=false,bool isJson=false)205 void HandleRequestByPipeTypeCommon(std::shared_ptr<FaultLoggerDaemon> daemon, int32_t pipeType,
206     bool isPassCheck = false, bool isJson = false)
207 {
208     int fd = -1;
209     FaultLoggerdRequest request;
210     request.pipeType = pipeType;
211     std::unique_ptr<FaultLoggerPipe2> ptr = std::make_unique<FaultLoggerPipe2>(GetTimeMilliSeconds(), isJson);
212 
213     if (!isPassCheck) {
214         daemon->HandleRequestByPipeType(fd, 1, &request, ptr.get());
215         close(fd);
216         return;
217     }
218 
219     int socketFd[2]; // 2 : the length of the array
220     if (socketpair(AF_UNIX, SOCK_STREAM, 0, socketFd) == 0) {
221         pid_t pid = fork();
222         if (pid == 0) {
223             sleep(1);
224             if (CheckReadResp(socketFd[1])) {
225                 std::string test = "test";
226                 OHOS_TEMP_FAILURE_RETRY(write(socketFd[1], test.c_str(), sizeof(test)));
227             }
228         } else if (pid > 0) {
229             daemon->connectionMap_[socketFd[0]] = socketFd[0];
230             daemon->HandleRequestByPipeType(fd, socketFd[0], &request, ptr.get());
231             close(fd);
232             close(socketFd[1]);
233         }
234     }
235 }
236 
HandleRequestByPipeTypeTest(std::shared_ptr<FaultLoggerDaemon> daemon)237 void HandleRequestByPipeTypeTest(std::shared_ptr<FaultLoggerDaemon> daemon)
238 {
239     HandleRequestByPipeTypeCommon(daemon, FaultLoggerPipeType::PIPE_FD_READ_BUF, true, false);
240     HandleRequestByPipeTypeCommon(daemon, FaultLoggerPipeType::PIPE_FD_READ_RES, true, false);
241     HandleRequestByPipeTypeCommon(daemon, FaultLoggerPipeType::PIPE_FD_DELETE, true, false);
242     HandleRequestByPipeTypeCommon(daemon, FaultLoggerPipeType::PIPE_FD_JSON_READ_BUF, true, true);
243     HandleRequestByPipeTypeCommon(daemon, FaultLoggerPipeType::PIPE_FD_JSON_READ_RES, true, true);
244 
245     HandleRequestByPipeTypeCommon(daemon, FaultLoggerPipeType::PIPE_FD_READ_BUF);
246     HandleRequestByPipeTypeCommon(daemon, FaultLoggerPipeType::PIPE_FD_WRITE_BUF);
247     HandleRequestByPipeTypeCommon(daemon, FaultLoggerPipeType::PIPE_FD_READ_RES);
248     HandleRequestByPipeTypeCommon(daemon, FaultLoggerPipeType::PIPE_FD_WRITE_RES);
249     HandleRequestByPipeTypeCommon(daemon, FaultLoggerPipeType::PIPE_FD_JSON_READ_BUF, false, true);
250     HandleRequestByPipeTypeCommon(daemon, FaultLoggerPipeType::PIPE_FD_JSON_WRITE_BUF, false, true);
251     HandleRequestByPipeTypeCommon(daemon, FaultLoggerPipeType::PIPE_FD_JSON_READ_RES, false, true);
252     HandleRequestByPipeTypeCommon(daemon, FaultLoggerPipeType::PIPE_FD_JSON_WRITE_RES, false, true);
253     HandleRequestByPipeTypeCommon(daemon, -1);
254 }
255 
FaultloggerdServerTestCallOnce(const uint8_t * data,size_t size)256 void FaultloggerdServerTestCallOnce(const uint8_t* data, size_t size)
257 {
258     static bool callCnt = false;
259     if (callCnt) {
260         return;
261     }
262     callCnt = true;
263 
264     std::shared_ptr<FaultLoggerDaemon> daemon = std::make_shared<FaultLoggerDaemon>();
265     // HandleRequest
266     daemon->HandleRequest(-1, 0);
267 
268     // HandleRequestTest
269     std::vector<FaultLoggerdStatsRequest> statsRequest = InitStatsRequests(data, size);
270     for (auto requst : statsRequest) {
271         HandleRequestTestCommon(daemon, reinterpret_cast<char*>(&requst), sizeof(FaultLoggerdStatsRequest), nullptr);
272     }
273 
274     // CheckReadRequest
275     {
276         int socketFd[2]; // 2 : the length of the array
277         if (socketpair(AF_UNIX, SOCK_STREAM, 0, socketFd) == 0) {
278             close(socketFd[1]);
279             daemon->HandleRequest(0, socketFd[0]);
280         }
281     }
282     char buff[] = "any test str";
283     HandleRequestTestCommon(daemon, reinterpret_cast<char*>(buff), sizeof(buff), nullptr);
284 
285     // CheckRequestCredential
286     {
287         FaultLoggerdRequest requst;
288         int socketFd[2]; // 2 : the length of the array
289         if (socketpair(AF_UNIX, SOCK_STREAM, 0, socketFd) == 0) {
290             OHOS_TEMP_FAILURE_RETRY(write(socketFd[1], reinterpret_cast<char*>(&requst), sizeof(FaultLoggerdRequest)));
291             daemon->HandleRequest(0, socketFd[0]);
292             close(socketFd[1]);
293         }
294     }
295 
296     // init
297     if (!daemon->InitEnvironment()) {
298         daemon->CleanupSockets();
299         return;
300     }
301 
302     HandleRequestByClientTypeTest(daemon);
303     HandleRequestByPipeTypeTest(daemon);
304     HandStaticTest(daemon);
305 }
306 
FaultloggerdServerTest(const uint8_t * data,size_t size)307 void FaultloggerdServerTest(const uint8_t* data, size_t size)
308 {
309     std::shared_ptr<FaultLoggerDaemon> daemon = std::make_shared<FaultLoggerDaemon>();
310 
311     int32_t epollFd;
312     int32_t connectionFd;
313     int32_t type;
314     int32_t pid;
315     int32_t tid;
316     int32_t uid;
317 
318     int offsetTotalLength = sizeof(epollFd) + sizeof(connectionFd) + sizeof(type) + sizeof(pid) +
319                             sizeof(tid) + sizeof(uid);
320     if (offsetTotalLength > size) {
321         return;
322     }
323 
324     STREAM_TO_VALUEINFO(data, epollFd);
325     STREAM_TO_VALUEINFO(data, connectionFd);
326     STREAM_TO_VALUEINFO(data, type);
327     STREAM_TO_VALUEINFO(data, pid);
328     STREAM_TO_VALUEINFO(data, tid);
329     STREAM_TO_VALUEINFO(data, uid);
330 
331     if (epollFd < 0 || connectionFd < 3) { // 3: not allow fd = 0,1,2 because they are reserved by system
332         return;
333     }
334 
335     struct FaultLoggerdRequest request;
336     (void)memset_s(&request, sizeof(request), 0, sizeof(request));
337     request.type = type;
338     request.pid = pid;
339     request.tid = tid;
340     request.uid = uid;
341     request.time = OHOS::HiviewDFX::GetTimeMilliSeconds();
342 
343     daemon->HandleRequestForFuzzer(epollFd, connectionFd, &request, &request);
344     sleep(1);
345 }
346 } // namespace HiviewDFX
347 } // namespace OHOS
348 
349 /* Fuzzer entry point */
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)350 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
351 {
352     if (data == nullptr || size == 0) {
353         return 0;
354     }
355 
356     /* Run your code on data */
357     OHOS::HiviewDFX::FaultloggerdServerTestCallOnce(data, size);
358     OHOS::HiviewDFX::FaultloggerdServerTest(data, size);
359     return 0;
360 }
361