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