1/* 2 * Copyright (c) 2021-2023 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#include "faultloggerd_client.h" 16 17#include <climits> 18#include <cstdint> 19#include <cstdio> 20#include <cstdlib> 21#include <securec.h> 22#include <unistd.h> 23 24#include <sys/socket.h> 25#include <sys/syscall.h> 26#include <sys/un.h> 27#include <sys/stat.h> 28 29#include "dfx_cutil.h" 30#include "dfx_define.h" 31#include "dfx_log.h" 32#include "dfx_util.h" 33#include "faultloggerd_socket.h" 34 35static const int32_t SOCKET_TIMEOUT = 5; 36 37static std::string GetSocketConnectionName() 38{ 39 char content[NAME_BUF_LEN]; 40 GetProcessName(content, sizeof(content)); 41 if (std::string(content).find("processdump") != std::string::npos) { 42 return std::string(SERVER_CRASH_SOCKET_NAME); 43 } 44 return std::string(SERVER_SOCKET_NAME); 45} 46 47int32_t RequestFileDescriptor(int32_t type) 48{ 49 struct FaultLoggerdRequest request; 50 (void)memset_s(&request, sizeof(request), 0, sizeof(request)); 51 request.type = type; 52 request.pid = getpid(); 53 request.tid = gettid(); 54 request.uid = getuid(); 55 request.time = OHOS::HiviewDFX::GetTimeMilliSeconds(); 56 return RequestFileDescriptorEx(&request); 57} 58 59int32_t RequestLogFileDescriptor(struct FaultLoggerdRequest *request) 60{ 61 if (request == nullptr) { 62 DFXLOGE("[%{public}d]: nullptr request", __LINE__); 63 return -1; 64 } 65 request->clientType = (int32_t)FaultLoggerClientType::LOG_FILE_DES_CLIENT; 66 return RequestFileDescriptorEx(request); 67} 68 69int32_t RequestFileDescriptorEx(const struct FaultLoggerdRequest *request) 70{ 71 if (request == nullptr) { 72 DFXLOGE("[%{public}d]: nullptr request", __LINE__); 73 return -1; 74 } 75 76 int sockfd; 77 std::string name = GetSocketConnectionName(); 78 if (!StartConnect(sockfd, name.c_str(), SOCKET_TIMEOUT)) { 79 DFXLOGE("[%{public}d]: StartConnect(%{public}d) failed", __LINE__, sockfd); 80 return -1; 81 } 82 83 OHOS_TEMP_FAILURE_RETRY(write(sockfd, request, sizeof(struct FaultLoggerdRequest))); 84 int fd = ReadFileDescriptorFromSocket(sockfd); 85 DFXLOGD("RequestFileDescriptorEx(%{public}d).", fd); 86 close(sockfd); 87 return fd; 88} 89 90static bool CheckReadResp(int sockfd) 91{ 92 char ControlBuffer[SOCKET_BUFFER_SIZE] = {0}; 93 ssize_t nread = OHOS_TEMP_FAILURE_RETRY(read(sockfd, ControlBuffer, sizeof(ControlBuffer) - 1)); 94 if (nread != static_cast<ssize_t>(strlen(FAULTLOGGER_DAEMON_RESP))) { 95 DFXLOGE("nread: %{public}zd.", nread); 96 return false; 97 } 98 return true; 99} 100 101static int32_t RequestFileDescriptorByCheck(const struct FaultLoggerdRequest *request) 102{ 103 int32_t fd = -1; 104 if (request == nullptr) { 105 DFXLOGE("[%{public}d]: nullptr request", __LINE__); 106 return -1; 107 } 108 109 int sockfd = -1; 110 do { 111 std::string name = GetSocketConnectionName(); 112 if (!StartConnect(sockfd, name.c_str(), SOCKET_TIMEOUT)) { 113 DFXLOGE("[%{public}d]: StartConnect(%{public}d) failed", __LINE__, sockfd); 114 break; 115 } 116 117 OHOS_TEMP_FAILURE_RETRY(write(sockfd, request, sizeof(struct FaultLoggerdRequest))); 118 119 if (!CheckReadResp(sockfd)) { 120 break; 121 } 122 123 int data = 12345; 124 if (!SendMsgIovToSocket(sockfd, reinterpret_cast<void *>(&data), sizeof(data))) { 125 DFXLOGE("%{public}s :: Failed to sendmsg.", __func__); 126 break; 127 } 128 129 fd = ReadFileDescriptorFromSocket(sockfd); 130 DFXLOGD("RequestFileDescriptorByCheck(%{public}d).", fd); 131 } while (false); 132 close(sockfd); 133 return fd; 134} 135 136static int SendUidToServer(int sockfd) 137{ 138 int mRsp = (int)FaultLoggerCheckPermissionResp::CHECK_PERMISSION_REJECT; 139 140 int data = 12345; 141 if (!SendMsgIovToSocket(sockfd, reinterpret_cast<void *>(&data), sizeof(data))) { 142 DFXLOGE("%{public}s :: Failed to sendmsg.", __func__); 143 return mRsp; 144 } 145 146 char recvbuf[SOCKET_BUFFER_SIZE] = {'\0'}; 147 ssize_t count = OHOS_TEMP_FAILURE_RETRY(recv(sockfd, recvbuf, sizeof(recvbuf), 0)); 148 if (count < 0) { 149 DFXLOGE("%{public}s :: Failed to recv.", __func__); 150 return mRsp; 151 } 152 153 mRsp = atoi(recvbuf); 154 return mRsp; 155} 156 157bool CheckConnectStatus() 158{ 159 int sockfd = -1; 160 std::string name = GetSocketConnectionName(); 161 if (StartConnect(sockfd, name.c_str(), SOCKET_TIMEOUT)) { 162 close(sockfd); 163 return true; 164 } 165 return false; 166} 167 168static int SendRequestToServer(const FaultLoggerdRequest &request) 169{ 170 int sockfd = -1; 171 int resRsp = (int)FaultLoggerCheckPermissionResp::CHECK_PERMISSION_REJECT; 172 do { 173 std::string name = GetSocketConnectionName(); 174 if (request.clientType == FaultLoggerClientType::SDK_DUMP_CLIENT) { 175 name = std::string(SERVER_SDKDUMP_SOCKET_NAME); 176 } 177 178 if (!StartConnect(sockfd, name.c_str(), SOCKET_TIMEOUT)) { 179 DFXLOGE("[%{public}d]: StartConnect(%{public}d) failed", __LINE__, sockfd); 180 break; 181 } 182 if (OHOS_TEMP_FAILURE_RETRY(write(sockfd, &request, 183 sizeof(struct FaultLoggerdRequest))) != static_cast<long>(sizeof(request))) { 184 DFXLOGE("write failed."); 185 break; 186 } 187 188 if (!CheckReadResp(sockfd)) { 189 break; 190 } 191 resRsp = SendUidToServer(sockfd); 192 } while (false); 193 194 close(sockfd); 195 DFXLOGI("SendRequestToServer :: resRsp(%{public}d).", resRsp); 196 return resRsp; 197} 198 199bool RequestCheckPermission(int32_t pid) 200{ 201 DFXLOGI("RequestCheckPermission :: %{public}d.", pid); 202 if (pid <= 0) { 203 return false; 204 } 205 206 struct FaultLoggerdRequest request; 207 (void)memset_s(&request, sizeof(request), 0, sizeof(request)); 208 209 request.pid = pid; 210 request.clientType = (int32_t)FaultLoggerClientType::PERMISSION_CLIENT; 211 212 bool ret = false; 213 if (SendRequestToServer(request) == (int)FaultLoggerCheckPermissionResp::CHECK_PERMISSION_PASS) { 214 ret = true; 215 } 216 return ret; 217} 218 219int RequestSdkDump(int32_t pid, int32_t tid, int timeout) 220{ 221 return RequestSdkDumpJson(pid, tid, false, timeout); 222} 223 224int RequestSdkDumpJson(int32_t pid, int32_t tid, bool isJson, int timeout) 225{ 226 DFXLOGI("RequestSdkDumpJson :: pid(%{public}d), tid(%{public}d).", pid, tid); 227 if (pid <= 0 || tid < 0) { 228 return -1; 229 } 230 231 struct FaultLoggerdRequest request; 232 (void)memset_s(&request, sizeof(request), 0, sizeof(request)); 233 request.isJson = isJson; 234 request.sigCode = DUMP_TYPE_REMOTE; 235 request.pid = pid; 236 request.tid = tid; 237 request.callerPid = getpid(); 238 request.callerTid = gettid(); 239 request.clientType = (int32_t)FaultLoggerClientType::SDK_DUMP_CLIENT; 240 request.time = OHOS::HiviewDFX::GetTimeMilliSeconds(); 241 request.endTime = GetAbsTimeMilliSeconds() + static_cast<uint64_t>(timeout); 242 243 return SendRequestToServer(request); 244} 245 246int RequestPrintTHilog(const char *msg, int length) 247{ 248 if (length >= LINE_BUF_SIZE) { 249 return -1; 250 } 251 252 struct FaultLoggerdRequest request; 253 (void)memset_s(&request, sizeof(request), 0, sizeof(request)); 254 request.clientType = (int32_t)FaultLoggerClientType::PRINT_T_HILOG_CLIENT; 255 request.pid = getpid(); 256 request.uid = getuid(); 257 int sockfd = -1; 258 do { 259 std::string name = GetSocketConnectionName(); 260 if (!StartConnect(sockfd, name.c_str(), SOCKET_TIMEOUT)) { 261 DFXLOGE("[%{public}d]: StartConnect(%{public}d) failed", __LINE__, sockfd); 262 break; 263 } 264 265 if (OHOS_TEMP_FAILURE_RETRY(write(sockfd, &request, 266 sizeof(struct FaultLoggerdRequest))) != static_cast<long>(sizeof(request))) { 267 break; 268 } 269 270 if (!CheckReadResp(sockfd)) { 271 break; 272 } 273 274 int nwrite = OHOS_TEMP_FAILURE_RETRY(write(sockfd, msg, strlen(msg))); 275 if (nwrite != static_cast<long>(strlen(msg))) { 276 DFXLOGE("nwrite: %{public}d.", nwrite); 277 break; 278 } 279 close(sockfd); 280 return 0; 281 } while (false); 282 close(sockfd); 283 return -1; 284} 285 286int32_t RequestPipeFd(int32_t pid, int32_t pipeType) 287{ 288 if (pipeType < static_cast<int32_t>(FaultLoggerPipeType::PIPE_FD_READ_BUF) || 289 pipeType > static_cast<int32_t>(FaultLoggerPipeType::PIPE_FD_DELETE)) { 290 DFXLOGE("%{public}s :: pipeType(%{public}d) failed.", __func__, pipeType); 291 return -1; 292 } 293 struct FaultLoggerdRequest request; 294 (void)memset_s(&request, sizeof(request), 0, sizeof(struct FaultLoggerdRequest)); 295 296 if ((pipeType == static_cast<int32_t>(FaultLoggerPipeType::PIPE_FD_JSON_READ_BUF)) || 297 (pipeType == static_cast<int32_t>(FaultLoggerPipeType::PIPE_FD_JSON_READ_RES))) { 298 request.isJson = true; 299 } else { 300 request.isJson = false; 301 } 302 request.pipeType = pipeType; 303 request.pid = pid; 304 request.callerPid = getpid(); 305 request.callerTid = gettid(); 306 request.clientType = (int32_t)FaultLoggerClientType::PIPE_FD_CLIENT; 307 if ((pipeType == static_cast<int32_t>(FaultLoggerPipeType::PIPE_FD_READ_BUF)) || 308 (pipeType == static_cast<int32_t>(FaultLoggerPipeType::PIPE_FD_READ_RES)) || 309 (pipeType == static_cast<int32_t>(FaultLoggerPipeType::PIPE_FD_JSON_READ_BUF)) || 310 (pipeType == static_cast<int32_t>(FaultLoggerPipeType::PIPE_FD_JSON_READ_RES))) { 311 return RequestFileDescriptorByCheck(&request); 312 } 313 return RequestFileDescriptorEx(&request); 314} 315 316int32_t RequestDelPipeFd(int32_t pid) 317{ 318 struct FaultLoggerdRequest request; 319 (void)memset_s(&request, sizeof(request), 0, sizeof(struct FaultLoggerdRequest)); 320 request.pipeType = FaultLoggerPipeType::PIPE_FD_DELETE; 321 request.pid = pid; 322 request.clientType = (int32_t)FaultLoggerClientType::PIPE_FD_CLIENT; 323 324 int sockfd; 325 std::string name = GetSocketConnectionName(); 326 if (!StartConnect(sockfd, name.c_str(), SOCKET_TIMEOUT)) { 327 DFXLOGE("[%{public}d]: StartConnect(%{public}d) failed", __LINE__, sockfd); 328 return -1; 329 } 330 331 OHOS_TEMP_FAILURE_RETRY(write(sockfd, &request, sizeof(struct FaultLoggerdRequest))); 332 close(sockfd); 333 return 0; 334} 335 336int ReportDumpStats(const struct FaultLoggerdStatsRequest *request) 337{ 338 int sockfd = -1; 339 std::string name = GetSocketConnectionName(); 340 if (!StartConnect(sockfd, name.c_str(), SOCKET_TIMEOUT)) { 341 DFXLOGE("[%{public}d]: StartConnect(%{public}d) failed", __LINE__, sockfd); 342 return -1; 343 } 344 345 if (OHOS_TEMP_FAILURE_RETRY(write(sockfd, request, 346 sizeof(struct FaultLoggerdStatsRequest))) != static_cast<long int>(sizeof(struct FaultLoggerdStatsRequest))) { 347 DFXLOGE("ReportDumpCatcherStats: failed to write stats."); 348 close(sockfd); 349 return -1; 350 } 351 close(sockfd); 352 return 0; 353} 354