1800b99b8Sopenharmony_ci/* 2800b99b8Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 3800b99b8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4800b99b8Sopenharmony_ci * you may not use this file except in compliance with the License. 5800b99b8Sopenharmony_ci * You may obtain a copy of the License at 6800b99b8Sopenharmony_ci * 7800b99b8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8800b99b8Sopenharmony_ci * 9800b99b8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10800b99b8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11800b99b8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12800b99b8Sopenharmony_ci * See the License for the specific language governing permissions and 13800b99b8Sopenharmony_ci * limitations under the License. 14800b99b8Sopenharmony_ci */ 15800b99b8Sopenharmony_ci 16800b99b8Sopenharmony_ci#include "dfx_signalhandler_exception.h" 17800b99b8Sopenharmony_ci 18800b99b8Sopenharmony_ci#include <stdio.h> 19800b99b8Sopenharmony_ci#include <sys/syscall.h> 20800b99b8Sopenharmony_ci#include <sys/socket.h> 21800b99b8Sopenharmony_ci#include <sys/time.h> 22800b99b8Sopenharmony_ci#include <sys/un.h> 23800b99b8Sopenharmony_ci#include <unistd.h> 24800b99b8Sopenharmony_ci 25800b99b8Sopenharmony_ci#include "dfx_define.h" 26800b99b8Sopenharmony_ci#include "dfx_exception.h" 27800b99b8Sopenharmony_ci#include "dfx_socket_request.h" 28800b99b8Sopenharmony_ci#include "errno.h" 29800b99b8Sopenharmony_ci#include "string.h" 30800b99b8Sopenharmony_ci 31800b99b8Sopenharmony_ci#ifndef DFX_SIGNAL_LIBC 32800b99b8Sopenharmony_ci#include "dfx_log.h" 33800b99b8Sopenharmony_ci#else 34800b99b8Sopenharmony_ci#include "musl_log.h" 35800b99b8Sopenharmony_ci#endif 36800b99b8Sopenharmony_ci 37800b99b8Sopenharmony_ci#ifdef LOG_DOMAIN 38800b99b8Sopenharmony_ci#undef LOG_DOMAIN 39800b99b8Sopenharmony_ci#define LOG_DOMAIN 0xD002D11 40800b99b8Sopenharmony_ci#endif 41800b99b8Sopenharmony_ci 42800b99b8Sopenharmony_ci#ifdef LOG_TAG 43800b99b8Sopenharmony_ci#undef LOG_TAG 44800b99b8Sopenharmony_ci#define LOG_TAG "DfxSignalHandlerException" 45800b99b8Sopenharmony_ci#endif 46800b99b8Sopenharmony_ci 47800b99b8Sopenharmony_cistatic const int TIME_OUT = 2; /* seconds */ 48800b99b8Sopenharmony_cistatic const char FAULTLOGGERD_SOCKET_NAME[] = "/dev/unix/socket/faultloggerd.server"; 49800b99b8Sopenharmony_ci 50800b99b8Sopenharmony_cistatic int ConnectSocket(const char* path, const int timeout) 51800b99b8Sopenharmony_ci{ 52800b99b8Sopenharmony_ci int fd = -1; 53800b99b8Sopenharmony_ci if ((fd = syscall(SYS_socket, AF_LOCAL, SOCK_STREAM, 0)) < 0) { 54800b99b8Sopenharmony_ci DFXLOGE("Failed to create a socket, errno(%{public}d).", errno); 55800b99b8Sopenharmony_ci return -1; 56800b99b8Sopenharmony_ci } 57800b99b8Sopenharmony_ci 58800b99b8Sopenharmony_ci do { 59800b99b8Sopenharmony_ci if (timeout > 0) { 60800b99b8Sopenharmony_ci struct timeval timev = { 61800b99b8Sopenharmony_ci timeout, 62800b99b8Sopenharmony_ci 0 63800b99b8Sopenharmony_ci }; 64800b99b8Sopenharmony_ci void* pTimev = &timev; 65800b99b8Sopenharmony_ci if (OHOS_TEMP_FAILURE_RETRY(syscall(SYS_setsockopt, fd, SOL_SOCKET, SO_RCVTIMEO, 66800b99b8Sopenharmony_ci (const void*)(pTimev), sizeof(timev))) != 0) { 67800b99b8Sopenharmony_ci DFXLOGE("setsockopt SO_RCVTIMEO error, errno(%{public}d).", errno); 68800b99b8Sopenharmony_ci syscall(SYS_close, fd); 69800b99b8Sopenharmony_ci fd = -1; 70800b99b8Sopenharmony_ci break; 71800b99b8Sopenharmony_ci } 72800b99b8Sopenharmony_ci } 73800b99b8Sopenharmony_ci struct sockaddr_un server; 74800b99b8Sopenharmony_ci (void)memset(&server, 0, sizeof(server)); 75800b99b8Sopenharmony_ci server.sun_family = AF_LOCAL; 76800b99b8Sopenharmony_ci (void)strncpy(server.sun_path, path, sizeof(server.sun_path) - 1); 77800b99b8Sopenharmony_ci int len = sizeof(server.sun_family) + strlen(server.sun_path); 78800b99b8Sopenharmony_ci int connected = OHOS_TEMP_FAILURE_RETRY(connect(fd, (struct sockaddr*)(&server), len)); 79800b99b8Sopenharmony_ci if (connected < 0) { 80800b99b8Sopenharmony_ci DFXLOGE("Failed to connect to faultloggerd socket, errno = %{public}d.", errno); 81800b99b8Sopenharmony_ci syscall(SYS_close, fd); 82800b99b8Sopenharmony_ci fd = -1; 83800b99b8Sopenharmony_ci break; 84800b99b8Sopenharmony_ci } 85800b99b8Sopenharmony_ci } while (false); 86800b99b8Sopenharmony_ci return fd; 87800b99b8Sopenharmony_ci} 88800b99b8Sopenharmony_ci 89800b99b8Sopenharmony_cistatic bool CheckReadResp(int fd) 90800b99b8Sopenharmony_ci{ 91800b99b8Sopenharmony_ci char controlBuffer[MAX_FUNC_NAME_LEN] = {0}; 92800b99b8Sopenharmony_ci ssize_t nread = OHOS_TEMP_FAILURE_RETRY(read(fd, controlBuffer, sizeof(controlBuffer) - 1)); 93800b99b8Sopenharmony_ci if (nread != (ssize_t)(strlen(FAULTLOGGER_DAEMON_RESP))) { 94800b99b8Sopenharmony_ci DFXLOGE("Failed to read expected length, nread: %{public}zd, errno(%{public}d).", nread, errno); 95800b99b8Sopenharmony_ci return false; 96800b99b8Sopenharmony_ci } 97800b99b8Sopenharmony_ci return true; 98800b99b8Sopenharmony_ci} 99800b99b8Sopenharmony_ci 100800b99b8Sopenharmony_ciint ReportException(struct CrashDumpException exception) 101800b99b8Sopenharmony_ci{ 102800b99b8Sopenharmony_ci struct FaultLoggerdRequest request; 103800b99b8Sopenharmony_ci (void)memset(&request, 0, sizeof(struct FaultLoggerdRequest)); 104800b99b8Sopenharmony_ci request.clientType = (int32_t)REPORT_EXCEPTION_CLIENT; 105800b99b8Sopenharmony_ci request.pid = exception.pid; 106800b99b8Sopenharmony_ci request.uid = (uint32_t)(exception.uid); 107800b99b8Sopenharmony_ci int ret = -1; 108800b99b8Sopenharmony_ci int fd = ConnectSocket(FAULTLOGGERD_SOCKET_NAME, TIME_OUT); // connect timeout 109800b99b8Sopenharmony_ci if (fd == -1) { 110800b99b8Sopenharmony_ci DFXLOGE("Failed to connect socket."); 111800b99b8Sopenharmony_ci return ret; 112800b99b8Sopenharmony_ci } 113800b99b8Sopenharmony_ci do { 114800b99b8Sopenharmony_ci if (OHOS_TEMP_FAILURE_RETRY(write(fd, &request, sizeof(request))) != (long)sizeof(request)) { 115800b99b8Sopenharmony_ci DFXLOGE("Failed to write request message to socket, errno(%{public}d).", errno); 116800b99b8Sopenharmony_ci break; 117800b99b8Sopenharmony_ci } 118800b99b8Sopenharmony_ci 119800b99b8Sopenharmony_ci if (!CheckReadResp(fd)) { 120800b99b8Sopenharmony_ci DFXLOGE("Failed to receive socket responces."); 121800b99b8Sopenharmony_ci break; 122800b99b8Sopenharmony_ci } 123800b99b8Sopenharmony_ci 124800b99b8Sopenharmony_ci if (OHOS_TEMP_FAILURE_RETRY(write(fd, &exception, 125800b99b8Sopenharmony_ci sizeof(exception))) != (long)sizeof(exception)) { 126800b99b8Sopenharmony_ci DFXLOGE("Failed to write exception message to socket, errno(%{public}d).", errno); 127800b99b8Sopenharmony_ci break; 128800b99b8Sopenharmony_ci } 129800b99b8Sopenharmony_ci 130800b99b8Sopenharmony_ci ret = 0; 131800b99b8Sopenharmony_ci } while (false); 132800b99b8Sopenharmony_ci syscall(SYS_close, fd); 133800b99b8Sopenharmony_ci return ret; 134800b99b8Sopenharmony_ci} 135