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 32namespace OHOS { 33namespace HiviewDFX { 34constexpr int32_t FAULTLOGGERD_FUZZ_READ_BUFF = 1024; 35 36void *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 46void *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 57void *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 67void 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 94std::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 128void 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 143void 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 186void 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 195bool 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 205void 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 237void 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 256void 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 307void 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 */ 350extern "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