From 7222ca39d882e241c88357d2282f9a1c2403f5b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BD=97=E6=AC=A3?= <15565592+lx0091029@user.noreply.gitee.com> Date: Mon, 30 Jun 2025 21:43:20 +0800 Subject: [PATCH] coredump MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 罗欣 --- interfaces/common/dfx_socket_request.h | 21 +- .../faultloggerd_client.cpp | 24 +- .../include/faultloggerd_client.h | 4 +- services/BUILD.gn | 2 + services/fault_common_util.cpp | 91 +++++ services/fault_common_util.h | 34 ++ services/fault_coredump_service.cpp | 382 ++++++++++++++++++ services/fault_coredump_service.h | 87 ++++ services/fault_logger_server.cpp | 4 +- services/fault_logger_server.h | 1 - services/fault_logger_service.cpp | 352 +--------------- services/fault_logger_service.h | 38 -- test/systemtest/faultloggerd_system_test.cpp | 51 --- test/unittest/faultloggerd/BUILD.gn | 2 + .../faultloggerd/faultlogger_server_test.cpp | 7 +- .../faultloggerd/faultloggerd_client_test.cpp | 249 ++++++++++++ 16 files changed, 891 insertions(+), 458 deletions(-) create mode 100644 services/fault_common_util.cpp create mode 100644 services/fault_common_util.h create mode 100644 services/fault_coredump_service.cpp create mode 100644 services/fault_coredump_service.h diff --git a/interfaces/common/dfx_socket_request.h b/interfaces/common/dfx_socket_request.h index 0c3f7018a..0efc622cb 100644 --- a/interfaces/common/dfx_socket_request.h +++ b/interfaces/common/dfx_socket_request.h @@ -72,9 +72,7 @@ typedef enum FaultLoggerClientType : int8_t { /** For report dump stats */ DUMP_STATS_CLIENT, /** For request to coredump */ - DO_COREDUMP_CLIENT, - /** For request to cancel coredump */ - CANCEL_COREDUMP_CLIENT, + COREDUMP_CLIENT, /** For request to report coredump status */ COREDUMP_PROCESS_DUMP_CLIENT, } FaultLoggerClientType; @@ -93,8 +91,21 @@ typedef struct CoreDumpRequestData { int32_t pid; /** endtime ms */ uint64_t endTime; + /** do or cancel coredump */ + int32_t coredumpAction; } __attribute__((packed)) CoreDumpRequestData; +/** + * @brief type of coredump Action + * +*/ +typedef enum CoreDumpAction : int32_t { + /** do coredump */ + DO_CORE_DUMP, + /** cancel coredump */ + CANCEL_CORE_DUMP, +} CoreDumpAction; + /** * @brief type of coredump Status * @@ -124,12 +135,12 @@ typedef struct CoreDumpStatusData { int32_t retCode; } __attribute__((packed)) CoreDumpStatusData; -typedef struct SocketReceiveData { +typedef struct CoreDumpResult { /** coredump file name **/ char fileName[256]; /** coredump result */ int32_t retCode; -} __attribute__((packed)) SocketReceiveData; +} __attribute__((packed)) CoreDumpResult; typedef struct SdkDumpRequestData { /** request data head **/ diff --git a/interfaces/innerkits/faultloggerd_client/faultloggerd_client.cpp b/interfaces/innerkits/faultloggerd_client/faultloggerd_client.cpp index dcaf2fb18..c997df516 100644 --- a/interfaces/innerkits/faultloggerd_client/faultloggerd_client.cpp +++ b/interfaces/innerkits/faultloggerd_client/faultloggerd_client.cpp @@ -194,9 +194,10 @@ std::string SaveCoredumpToFileTimeout(int32_t targetPid, int timeout) } struct CoreDumpRequestData request{}; - FillRequestHeadData(request.head, FaultLoggerClientType::DO_COREDUMP_CLIENT); + FillRequestHeadData(request.head, FaultLoggerClientType::COREDUMP_CLIENT); request.pid = targetPid; request.endTime = GetAbsTimeMilliSeconds() + static_cast(timeout); + request.coredumpAction = CoreDumpAction::DO_CORE_DUMP; SocketRequestData socketRequestData = {&request, sizeof(request)}; FaultLoggerdSocket faultLoggerdSocket; @@ -215,12 +216,12 @@ std::string SaveCoredumpToFileTimeout(int32_t targetPid, int timeout) return ""; } DFXLOGI("%{public}s connect request retCode : %{public}d", __func__, retCode); - SocketReceiveData socketReceiveData; - faultLoggerdSocket.GetMsgFromSocket(&socketReceiveData, sizeof(socketReceiveData)); + CoreDumpResult coredumpResult = {"", ResponseCode::RECEIVE_DATA_FAILED}; + faultLoggerdSocket.GetMsgFromSocket(&coredumpResult, sizeof(coredumpResult)); DFXLOGI("%{public}s has received retCode : %{public}d and filename: %{public}s", __func__, - socketReceiveData.retCode, socketReceiveData.fileName); - return socketReceiveData.fileName; + coredumpResult.retCode, coredumpResult.fileName); + return coredumpResult.fileName; #else return ""; #endif @@ -235,8 +236,9 @@ int32_t CancelCoredump(int32_t targetPid) } struct CoreDumpRequestData request{}; - FillRequestHeadData(request.head, FaultLoggerClientType::CANCEL_COREDUMP_CLIENT); + FillRequestHeadData(request.head, FaultLoggerClientType::COREDUMP_CLIENT); request.pid = targetPid; + request.coredumpAction = CoreDumpAction::CANCEL_CORE_DUMP; SocketRequestData socketRequestData = {&request, sizeof(request)}; int32_t retCode = @@ -249,19 +251,19 @@ int32_t CancelCoredump(int32_t targetPid) #endif } -int32_t StartCoredumpCb(int32_t targetPid, int32_t workerPid) +int32_t StartCoredumpCb(int32_t targetPid, int32_t processDumpPid) { #ifndef is_ohos_lite - DFXLOGI("%{public}s.%{public}s :: targetpid: %{public}d, workerpid: %{public}d.", - FAULTLOGGERD_CLIENT_TAG, __func__, targetPid, workerPid); - if (targetPid <= 0 || workerPid <= 0) { + DFXLOGI("%{public}s.%{public}s :: targetpid: %{public}d, processDumpPid: %{public}d.", + FAULTLOGGERD_CLIENT_TAG, __func__, targetPid, processDumpPid); + if (targetPid <= 0 || processDumpPid <= 0) { return ResponseCode::DEFAULT_ERROR_CODE; } struct CoreDumpStatusData request{}; FillRequestHeadData(request.head, FaultLoggerClientType::COREDUMP_PROCESS_DUMP_CLIENT); request.pid = targetPid; - request.processDumpPid = workerPid; + request.processDumpPid = processDumpPid; request.coredumpStatus = CoreDumpStatus::CORE_DUMP_START; SocketRequestData socketRequestData = {&request, sizeof(request)}; diff --git a/interfaces/innerkits/faultloggerd_client/include/faultloggerd_client.h b/interfaces/innerkits/faultloggerd_client/include/faultloggerd_client.h index e7dd60ab2..d8aaf650e 100644 --- a/interfaces/innerkits/faultloggerd_client/include/faultloggerd_client.h +++ b/interfaces/innerkits/faultloggerd_client/include/faultloggerd_client.h @@ -84,10 +84,10 @@ int32_t CancelCoredump(int32_t targetPid); /** * @brief start coredump request * @param targetPid target id - * @param workerPid processdump id + * @param processDumpPid processdump id * @return if succeed return 0 , otherwise return the error code */ -int32_t StartCoredumpCb(int32_t targetPid, int32_t workerPid); +int32_t StartCoredumpCb(int32_t targetPid, int32_t processDumpPid); /** * @brief finish coredump request diff --git a/services/BUILD.gn b/services/BUILD.gn index 2d7f399a8..1353fc784 100644 --- a/services/BUILD.gn +++ b/services/BUILD.gn @@ -20,6 +20,8 @@ faultloggerd_sources = [ "fault_logger_server.cpp", "fault_logger_service.cpp", "temp_file_manager.cpp", + "fault_coredump_service.cpp", + "fault_common_util.cpp" ] if (defined(ohos_lite)) { diff --git a/services/fault_common_util.cpp b/services/fault_common_util.cpp new file mode 100644 index 000000000..e574434a3 --- /dev/null +++ b/services/fault_common_util.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fault_common_util.h" + +#include +#include +#include +#include +#include "dfx_define.h" +#include "dfx_log.h" +#include "dfx_trace.h" +#include "dfx_util.h" +#include "fault_logger_daemon.h" +#include "procinfo.h" +#include "proc_util.h" + +namespace OHOS { +namespace HiviewDFX { + +namespace { +constexpr const char* const FAULTLOGGERD_SERVICE_TAG = "FAULT_COMMON_UTIL"; +} + +namespace FaultCommonUtil { +bool GetUcredByPeerCred(struct ucred& rcred, int32_t connectionFd) +{ + socklen_t credSize = sizeof(rcred); + if (getsockopt(connectionFd, SOL_SOCKET, SO_PEERCRED, &rcred, &credSize) != 0) { + DFXLOGE("%{public}s :: Failed to GetCredential, errno: %{public}d", FAULTLOGGERD_SERVICE_TAG, errno); + return false; + } + return true; +} + +int32_t SendSignalToHapWatchdogThread(pid_t pid, const siginfo_t& si) +{ + long uid = 0; + uint64_t sigBlk = 0; + if (!GetUidAndSigBlk(pid, uid, sigBlk)) { + return ResponseCode::DEFAULT_ERROR_CODE; + }; + constexpr long minUid = 10000; // 10000 : minimum uid for hap + if (uid < minUid || IsSigDumpMask(sigBlk)) { + return ResponseCode::DEFAULT_ERROR_CODE; + } + + pid_t tid = GetTidByThreadName(pid, "OS_DfxWatchdog"); + if (tid <= 0) { + return ResponseCode::DEFAULT_ERROR_CODE; + } +#ifndef FAULTLOGGERD_TEST + if (syscall(SYS_rt_tgsigqueueinfo, pid, tid, si.si_signo, &si) != 0) { + DFXLOGE("%{public}s :: Failed to SYS_rt_tgsigqueueinfo signal(%{public}d), errno(%{public}d).", + FAULTLOGGERD_SERVICE_TAG, si.si_signo, errno); + return ResponseCode::SDK_DUMP_NOPROC; + } +#endif + return ResponseCode::REQUEST_SUCCESS; +} + +int32_t SendSignalToProcess(pid_t pid, const siginfo_t& si) +{ + auto ret = SendSignalToHapWatchdogThread(pid, si); + if (ret == ResponseCode::SDK_DUMP_NOPROC || ret == ResponseCode::REQUEST_SUCCESS) { + return ret; + } +#ifndef FAULTLOGGERD_TEST + if (syscall(SYS_rt_sigqueueinfo, pid, si.si_signo, &si) != 0) { + DFXLOGE("%{public}s :: Failed to SYS_rt_sigqueueinfo signal(%{public}d), errno(%{public}d).", + FAULTLOGGERD_SERVICE_TAG, si.si_signo, errno); + return ResponseCode::SDK_DUMP_NOPROC; + } +#endif + return ResponseCode::REQUEST_SUCCESS; +} +} +} +} \ No newline at end of file diff --git a/services/fault_common_util.h b/services/fault_common_util.h new file mode 100644 index 000000000..bb1159b5a --- /dev/null +++ b/services/fault_common_util.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FAULT_COMMON_UTIL_H +#define FAULT_COMMON_UTIL_H + +#include +#include "csignal" +#include "cstdint" + +namespace OHOS { +namespace HiviewDFX { +namespace FaultCommonUtil { +int32_t SendSignalToHapWatchdogThread(pid_t pid, const siginfo_t& si); +int32_t SendSignalToProcess(pid_t pid, const siginfo_t& si); + +bool GetUcredByPeerCred(struct ucred& rcred, int32_t connectionFd); +} +} +} + +#endif \ No newline at end of file diff --git a/services/fault_coredump_service.cpp b/services/fault_coredump_service.cpp new file mode 100644 index 000000000..9e03dd840 --- /dev/null +++ b/services/fault_coredump_service.cpp @@ -0,0 +1,382 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fault_coredump_service.h" + +#include +#include +#include +#include +#include "dfx_define.h" +#include "dfx_log.h" +#include "dfx_trace.h" +#include "dfx_util.h" +#include "fault_logger_daemon.h" +#include "faultloggerd_socket.h" +#include "fault_common_util.h" +#include "procinfo.h" +#include "proc_util.h" +#include "string_printf.h" + +namespace OHOS { +namespace HiviewDFX { + +namespace { +constexpr const char* const FAULTLOGGERD_SERVICE_TAG = "FAULT_COREDUMP_SERVICE"; +bool CheckCoredumpUID(uint32_t callerUid) +{ + const uint32_t whitelist[] = { + 0, // rootUid + 1202, // dumpcatcherUid + 7005, // taskManagerUid + }; + if (std::find(std::begin(whitelist), std::end(whitelist), callerUid) == std::end(whitelist)) { + DFXLOGW("%{public}s :: CheckCoredumpUID :: Coredump Uid(%{public}d) is unexpectly.", + FAULTLOGGERD_SERVICE_TAG, callerUid); + return false; + } + return true; +} + +int32_t SendCancelSignal(int32_t processDumpPid) +{ + siginfo_t si{0}; + si.si_signo = SIGTERM; + si.si_errno = 0; + si.si_code = SIGLEAK_STACK_COREDUMP; +#ifndef FAULTLOGGERD_TEST + if (syscall(SYS_rt_sigqueueinfo, processDumpPid, si.si_signo, &si) != 0) { + DFXLOGE("%{public}s :: Failed to SYS_rt_sigqueueinfo signal(%{public}d), errno(%{public}d).", + FAULTLOGGERD_SERVICE_TAG, si.si_signo, errno); + return ResponseCode::CORE_DUMP_NOPROC; + } +#endif + return ResponseCode::REQUEST_SUCCESS; +} + +bool SendMsgToCoredumpClient(int32_t targetPid, int32_t responseCode, const std::string& fileName, + RecorderProcessMap& coredumpRecorder) +{ + int32_t savedConnectionFd = -1; + + coredumpRecorder.GetCoredumpSocketId(targetPid, savedConnectionFd); + if (savedConnectionFd < 0) { + DFXLOGE("%{public}s :: Client sockFd has been crashed.", __func__); + return false; + } + + CoreDumpResult coredumpResult; + if (strncpy_s(coredumpResult.fileName, sizeof(coredumpResult.fileName), + fileName.c_str(), fileName.size()) != 0) { + DFXLOGE("%{public}s :: strncpy failed.", __func__); + return false; + } + coredumpResult.retCode = responseCode; + + if (SendMsgToSocket(savedConnectionFd, &coredumpResult, sizeof(coredumpResult))) { + return true; + } + return false; +} + +bool HandleCoredumpAndCleanup(int32_t targetPid, int32_t retCode, const std::string& fileName, + RecorderProcessMap& coredumpRecorder) +{ + if (!SendMsgToCoredumpClient(targetPid, retCode, fileName, coredumpRecorder)) { + DFXLOGE("Send message to client failed, %{public}s %{public}d", __func__, __LINE__); + } + + if (!coredumpRecorder.ClearTargetPid(targetPid)) { + DFXLOGE("Remove targetpid %{public}d failed, %{public}s %{public}d", targetPid, __func__, __LINE__); + return false; + } + return true; +} +} + +RecorderProcessMap& RecorderProcessMap::GetInstance() +{ + static RecorderProcessMap instance; + return instance; +} + +bool RecorderProcessMap::IsEmpty() +{ + return coredumpProcessMap.empty(); +} + +bool RecorderProcessMap::HasTargetPid(int32_t targetPid) +{ + return coredumpProcessMap.find(targetPid) != coredumpProcessMap.end(); +} + +void RecorderProcessMap::AddProcessMap(int32_t targetPid, const CoredumpProcessInfo& processInfo) +{ + coredumpProcessMap.emplace( + targetPid, + CoredumpProcessInfo(processInfo.processDumpPid, processInfo.coredumpSocketId, + processInfo.endTime, processInfo.cancelFlag) + ); +} + +bool RecorderProcessMap::ClearTargetPid(int32_t targetPid) +{ + auto it = coredumpProcessMap.find(targetPid); + if (it != coredumpProcessMap.end()) { + close(it->second.coredumpSocketId); + coredumpProcessMap.erase(it); + return true; + } + return false; +} + +bool RecorderProcessMap::SetCancelFlag(int32_t targetPid, bool flag) +{ + auto it = coredumpProcessMap.find(targetPid); + if (it != coredumpProcessMap.end()) { + it->second.cancelFlag = flag; + return true; + } + return false; +} + +bool RecorderProcessMap::SetProcessDumpPid(int32_t targetPid, int32_t processDumpPid) +{ + auto it = coredumpProcessMap.find(targetPid); + if (it != coredumpProcessMap.end()) { + it->second.processDumpPid = processDumpPid; + return true; + } + return false; +} + +bool RecorderProcessMap::GetCoredumpSocketId(int32_t targetPid, int32_t& coredumpSocketId) +{ + auto it = coredumpProcessMap.find(targetPid); + if (it != coredumpProcessMap.end()) { + coredumpSocketId = it->second.coredumpSocketId; + return true; + } + return false; +} + +bool RecorderProcessMap::GetProcessDumpPid(int32_t targetPid, int32_t& processDumpPid) +{ + auto it = coredumpProcessMap.find(targetPid); + if (it != coredumpProcessMap.end()) { + processDumpPid = it->second.processDumpPid; + return true; + } + return false; +} + +bool RecorderProcessMap::GetCancelFlag(int32_t targetPid, bool& flag) +{ + auto it = coredumpProcessMap.find(targetPid); + if (it != coredumpProcessMap.end()) { + flag = it->second.cancelFlag; + return true; + } + return false; +} + +#ifndef is_ohos_lite +bool CoredumpStatusService::HandleProcessDumpPid(int32_t targetPid, int32_t processDumpPid) +{ + if (processDumpPid <= 0 || targetPid <= 0) { + return false; + } + + if (!coredumpRecorder.HasTargetPid(targetPid)) { + return false; + } + + bool cancelFlag = false; + if (coredumpRecorder.GetCancelFlag(targetPid, cancelFlag)) { + if (!cancelFlag) { + coredumpRecorder.SetProcessDumpPid(targetPid, processDumpPid); + return true; + } + } + + if (SendCancelSignal(processDumpPid) != ResponseCode::REQUEST_SUCCESS) { + return false; + } + + int32_t retCode = ResponseCode::CORE_DUMP_CANCEL; + std::string fileName = ""; + HandleCoredumpAndCleanup(targetPid, retCode, fileName, coredumpRecorder); + return true; +} + +int32_t CoredumpStatusService::OnRequest(const std::string& socketName, int32_t connectionFd, + const CoreDumpStatusData& requestData) +{ + DFX_TRACE_SCOPED("CoredumpStatusServiceOnRequest"); + DFXLOGI("Receive coredump status request for pid:%{public}d, status:%{public}d", requestData.pid, + requestData.coredumpStatus); + + int32_t res = ResponseCode::REQUEST_SUCCESS; + if (requestData.coredumpStatus == CoreDumpStatus::CORE_DUMP_START) { + DFXLOGI("Processdump start %{public}s %{public}d", __func__, __LINE__); + int32_t processDumpPid = requestData.processDumpPid; + + if (!HandleProcessDumpPid(requestData.pid, processDumpPid)) { + DFXLOGE("Handle processDumpPid %{public}d failed", processDumpPid); + res = ResponseCode::ABNORMAL_SERVICE; + return res; + } + } else if (requestData.coredumpStatus == CoreDumpStatus::CORE_DUMP_END) { + DFXLOGI("Processdump finish %{public}s %{public}d", __func__, __LINE__); + + int32_t targetPid = requestData.pid; + char cfileName[256]; + if (strncpy_s(cfileName, sizeof(cfileName), requestData.fileName, sizeof(requestData.fileName)) != 0) { + DFXLOGE("%{public}s :: strncpy failed.", __func__); + return ResponseCode::DEFAULT_ERROR_CODE; + } + int32_t retCode = requestData.retCode; + HandleCoredumpAndCleanup(targetPid, retCode, cfileName, coredumpRecorder); + } + + SendMsgToSocket(connectionFd, &res, sizeof(res)); + return res; +} + +int32_t CoredumpService::Filter(const std::string& socketName, const CoreDumpRequestData& requestData, uint32_t uid) +{ + if (requestData.pid <= 0 || socketName != SERVER_SOCKET_NAME || !CheckCoredumpUID(uid)) { + DFXLOGE("%{public}s :: HandleCoreDumpRequest :: pid(%{public}d) or socketName(%{public}s) fail.", + FAULTLOGGERD_SERVICE_TAG, requestData.pid, socketName.c_str()); + return ResponseCode::REQUEST_REJECT; + } + if (TempFileManager::CheckCrashFileRecord(requestData.pid)) { + DFXLOGW("%{public}s :: pid(%{public}d) has been crashed, break.", + FAULTLOGGERD_SERVICE_TAG, requestData.pid); + return ResponseCode::CORE_PROCESS_CRASHED; + } + return ResponseCode::REQUEST_SUCCESS; +} + +int32_t CoredumpService::DoCoredumpRequest(const std::string& socketName, int32_t connectionFd, + const CoreDumpRequestData& requestData) +{ + struct ucred creds; + if (!FaultCommonUtil::GetUcredByPeerCred(creds, connectionFd)) { + DFXLOGE("Core dump pid(%{public}d) request failed to get cred.", requestData.pid); + return ResponseCode::REQUEST_REJECT; + } + int32_t responseCode = Filter(socketName, requestData, creds.uid); + if (responseCode != ResponseCode::REQUEST_SUCCESS) { + return responseCode; + } + + int32_t res = ResponseCode::REQUEST_SUCCESS; + int32_t coredumpSocketId = dup(connectionFd); + int32_t targetPid = requestData.pid; + if (coredumpRecorder.HasTargetPid(targetPid)) { + DFXLOGE("%{public}d is generating coredump, please do not repeat dump!", targetPid); + res = ResponseCode::CORE_DUMP_REPEAT; + SendMsgToSocket(coredumpSocketId, &res, sizeof(res)); + close(coredumpSocketId); + return res; + } + + siginfo_t si{0}; + si.si_signo = SIGLEAK_STACK; + si.si_errno = 0; + si.si_code = SIGLEAK_STACK_COREDUMP; + si.si_pid = static_cast(creds.pid); + if (auto ret = FaultCommonUtil::SendSignalToProcess(targetPid, si); ret != ResponseCode::REQUEST_SUCCESS) { + SendMsgToSocket(coredumpSocketId, &ret, sizeof(ret)); + close(coredumpSocketId); + return ret; + } + + int32_t processDumpPid = -1; + uint64_t endTime = requestData.endTime; + coredumpRecorder.AddProcessMap(targetPid, {processDumpPid, coredumpSocketId, endTime, false}); + SendMsgToSocket(coredumpSocketId, &res, sizeof(res)); + + auto removeTask = [targetPid, coredumpRecorderPtr = &coredumpRecorder]() { + coredumpRecorderPtr->ClearTargetPid(targetPid); + }; + + constexpr int32_t minDelays = 60; // 60 : 60s + int32_t delays = static_cast((endTime - GetAbsTimeMilliSeconds()) / 1000); + delays = std::min(delays, minDelays); + StartDelayTask(removeTask, delays); + return res; +} + +int32_t CoredumpService::CancelCoredumpRequest(int32_t connectionFd, const CoreDumpRequestData& requestData) +{ + int32_t targetPid = requestData.pid; + int32_t res = ResponseCode::REQUEST_SUCCESS; + if (!coredumpRecorder.HasTargetPid(targetPid)) { + DFXLOGE("No need to cancel!"); + res = ResponseCode::DEFAULT_ERROR_CODE; + SendMsgToSocket(connectionFd, &res, sizeof(res)); + return res; + } + + int32_t processDumpPid = -1; + if (coredumpRecorder.GetProcessDumpPid(targetPid, processDumpPid)) { + if (processDumpPid == -1) { + DFXLOGE("Can not get processdump pid!"); + coredumpRecorder.SetCancelFlag(targetPid, true); + } else { + DFXLOGI("processDumpPid get %{public}d %{public}d", processDumpPid, __LINE__); + + res = SendCancelSignal(processDumpPid); + if (res != ResponseCode::REQUEST_SUCCESS) { + return res; + } + int32_t retCode = ResponseCode::CORE_DUMP_CANCEL; + std::string fileName = ""; + HandleCoredumpAndCleanup(targetPid, retCode, fileName, coredumpRecorder); + } + } + + SendMsgToSocket(connectionFd, &res, sizeof(res)); + return res; +} + +int32_t CoredumpService::OnRequest(const std::string& socketName, int32_t connectionFd, + const CoreDumpRequestData& requestData) +{ + DFX_TRACE_SCOPED("CoredumpServiceOnRequest"); + DFXLOGI("Receive coredump request for pid:%{public}d, action:%{public}d.", requestData.pid, + requestData.coredumpAction); + + int32_t res = ResponseCode::REQUEST_SUCCESS; + if (requestData.coredumpAction == CoreDumpAction::DO_CORE_DUMP) { + DFXLOGI("Do coredump %{public}s %{public}d", __func__, __LINE__); + res = DoCoredumpRequest(socketName, connectionFd, requestData); + } else if (requestData.coredumpAction == CoreDumpAction::CANCEL_CORE_DUMP) { + DFXLOGI("Cancel coredump %{public}s %{public}d", __func__, __LINE__); + res = CancelCoredumpRequest(connectionFd, requestData); + } + return res; +} + +void CoredumpService::StartDelayTask(std::function workFunc, int32_t delayTime) +{ + auto delayTask = DelayTask::CreateInstance(workFunc, delayTime); + FaultLoggerDaemon::GetEpollManager(EpollManagerType::MAIN_SERVER).AddListener(std::move(delayTask)); +} +#endif +} +} \ No newline at end of file diff --git a/services/fault_coredump_service.h b/services/fault_coredump_service.h new file mode 100644 index 000000000..51180318d --- /dev/null +++ b/services/fault_coredump_service.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FAULT_COREDUMP_SERVICE_H +#define FAULT_COREDUMP_SERVICE_H + +#include "csignal" +#include "cstdint" +#include "fault_logger_service.h" + +namespace OHOS { +namespace HiviewDFX { +struct CoredumpProcessInfo { + int32_t processDumpPid; + int32_t coredumpSocketId; + int endTime; + bool cancelFlag; + + CoredumpProcessInfo(int32_t processDump, int32_t connectionFd, int time, bool flag) + : processDumpPid(processDump), coredumpSocketId(connectionFd), endTime(time), cancelFlag(flag) {} +}; + +class RecorderProcessMap { +public: + RecorderProcessMap(const RecorderProcessMap&) = delete; + RecorderProcessMap& operator=(const RecorderProcessMap&) = delete; + + bool IsEmpty(); + bool HasTargetPid(int32_t targetPid); + void AddProcessMap(int32_t targetPid, const CoredumpProcessInfo& processInfo); + bool ClearTargetPid(int32_t targetPid); + bool GetCoredumpSocketId(int32_t targetPid, int32_t& coredumpSocketId); + bool GetCancelFlag(int32_t targetPid, bool& flag); + bool GetProcessDumpPid(int32_t targetPid, int32_t& processDumpPid); + bool SetCancelFlag(int32_t targetPid, bool flag); + bool SetProcessDumpPid(int32_t targetPid, int32_t processDumpPid); + static RecorderProcessMap& GetInstance(); + +private: + RecorderProcessMap() = default; + std::unordered_map coredumpProcessMap; +}; + +#ifndef is_ohos_lite +class CoredumpService : public FaultLoggerService { +public: + CoredumpService() : coredumpRecorder(RecorderProcessMap::GetInstance()) {} + int32_t OnRequest(const std::string& socketName, int32_t connectionFd, + const CoreDumpRequestData& requestData) override; + +private: + static int32_t Filter(const std::string& socketName, const CoreDumpRequestData& requestData, uint32_t uid); + void StartDelayTask(std::function workFunc, int32_t delayTime); + int32_t DoCoredumpRequest(const std::string& socketName, int32_t connectionFd, + const CoreDumpRequestData& requestData); + int32_t CancelCoredumpRequest(int32_t connectionFd, const CoreDumpRequestData& requestData); + RecorderProcessMap& coredumpRecorder; +}; + + +class CoredumpStatusService : public FaultLoggerService { +public: + CoredumpStatusService() : coredumpRecorder(RecorderProcessMap::GetInstance()) {} + int32_t OnRequest(const std::string& socketName, int32_t connectionFd, + const CoreDumpStatusData& requestData) override; + +private: + bool HandleProcessDumpPid(int32_t targetPid, int32_t processDumpPid); + RecorderProcessMap& coredumpRecorder; +}; +#endif +} +} + +#endif \ No newline at end of file diff --git a/services/fault_logger_server.cpp b/services/fault_logger_server.cpp index 7cbc9f0cf..b77241c0f 100644 --- a/services/fault_logger_server.cpp +++ b/services/fault_logger_server.cpp @@ -22,6 +22,7 @@ #include "dfx_define.h" #include "dfx_log.h" #include "faultloggerd_socket.h" +#include "fault_coredump_service.h" namespace OHOS { namespace HiviewDFX { @@ -46,8 +47,7 @@ bool SocketServer::Init() return false; } #ifndef is_ohos_lite - AddService(DO_COREDUMP_CLIENT, std::make_unique()); - AddService(CANCEL_COREDUMP_CLIENT, std::make_unique()); + AddService(COREDUMP_CLIENT, std::make_unique()); AddService(COREDUMP_PROCESS_DUMP_CLIENT, std::make_unique()); AddService(PIPE_FD_CLIENT, std::make_unique()); diff --git a/services/fault_logger_server.h b/services/fault_logger_server.h index ce925f7f4..c3840734f 100644 --- a/services/fault_logger_server.h +++ b/services/fault_logger_server.h @@ -17,7 +17,6 @@ #define FAULT_LOGGER_SERVER_H_ #include - #include "epoll_manager.h" #include "fault_logger_service.h" diff --git a/services/fault_logger_service.cpp b/services/fault_logger_service.cpp index 3621c9091..03dbef251 100644 --- a/services/fault_logger_service.cpp +++ b/services/fault_logger_service.cpp @@ -20,13 +20,13 @@ #include #include #include -#include #include "dfx_define.h" #include "dfx_log.h" #include "dfx_trace.h" #include "dfx_util.h" #include "fault_logger_daemon.h" #include "faultloggerd_socket.h" +#include "fault_common_util.h" #include "procinfo.h" #include "proc_util.h" @@ -46,16 +46,6 @@ namespace HiviewDFX { namespace { constexpr const char* const FAULTLOGGERD_SERVICE_TAG = "FAULT_LOGGER_SERVICE"; -bool GetUcredByPeerCred(struct ucred& rcred, int32_t connectionFd) -{ - socklen_t credSize = sizeof(rcred); - if (getsockopt(connectionFd, SOL_SOCKET, SO_PEERCRED, &rcred, &credSize) != 0) { - DFXLOGE("%{public}s :: Failed to GetCredential, errno: %{public}d", FAULTLOGGERD_SERVICE_TAG, errno); - return false; - } - return true; -} - bool CheckCallerUID(uint32_t callerUid) { const uint32_t whitelist[] = { @@ -63,7 +53,7 @@ bool CheckCallerUID(uint32_t callerUid) 1000, // bmsUid 1201, // hiviewUid 1212, // hidumperServiceUid - 5523 // foundationUid + 5523, // foundationUid }; if (std::find(std::begin(whitelist), std::end(whitelist), callerUid) == std::end(whitelist)) { DFXLOGW("%{public}s :: CheckCallerUID :: Caller Uid(%{public}d) is unexpectly.", @@ -76,7 +66,7 @@ bool CheckCallerUID(uint32_t callerUid) bool CheckRequestCredential(int32_t connectionFd, int32_t requestPid) { struct ucred creds{}; - if (!GetUcredByPeerCred(creds, connectionFd)) { + if (!FaultCommonUtil::GetUcredByPeerCred(creds, connectionFd)) { return false; } if (CheckCallerUID(creds.uid)) { @@ -98,7 +88,8 @@ bool ExceptionReportService::Filter(int32_t connectionFd, const CrashDumpExcepti return false; } struct ucred creds{}; - if (!GetUcredByPeerCred(creds, connectionFd) || creds.uid != static_cast(requestData.uid)) { + if (!FaultCommonUtil::GetUcredByPeerCred(creds, connectionFd) || + creds.uid != static_cast(requestData.uid)) { DFXLOGW("Failed to check request credential request uid:%{public}d: cred uid:%{public}d fd:%{public}d", requestData.uid, creds.uid, connectionFd); return false; @@ -262,293 +253,6 @@ bool FileDesService::Filter(const std::string& socketName, int32_t connectionFd, } #ifndef is_ohos_lite -namespace { - -std::unordered_map g_processMap; -int32_t SendCancelSignal(int32_t workerPid) -{ - siginfo_t si{0}; - si.si_signo = DUMPCATCHER_TIMEOUT; - si.si_errno = 0; - si.si_code = SIGLEAK_STACK_COREDUMP; - if (syscall(SYS_rt_sigqueueinfo, workerPid, si.si_signo, &si) != 0) { - DFXLOGE("%{public}s :: Failed to SYS_rt_sigqueueinfo signal(%{public}d), errno(%{public}d).", - FAULTLOGGERD_SERVICE_TAG, si.si_signo, errno); - return ResponseCode::CORE_DUMP_NOPROC; - } - return ResponseCode::REQUEST_SUCCESS; -} - -bool SendMsgToCoredumpClient(int32_t targetPid, const int32_t& responseCode, std::string& fileName) -{ - int32_t retCode = responseCode; - int32_t savedConnectionFd = -1; - - auto it = g_processMap.find(targetPid); - if (it != g_processMap.end()) { - savedConnectionFd = it->second.coredumpSocketId; - if (savedConnectionFd < 0) { - DFXLOGE("Saved sockFd has been crashed, break."); - return false; - } - } - SocketReceiveData socketReceiveData; - auto fileNameLen = sizeof(socketReceiveData.fileName); - if (strncpy_s(socketReceiveData.fileName, fileNameLen, fileName.c_str(), fileNameLen - 1) != 0) { - DFXLOGE("%{public}s :: strncpy failed.", __func__); - return false; - } - socketReceiveData.retCode = retCode; - - if (SendMsgToSocket(savedConnectionFd, &socketReceiveData, sizeof(socketReceiveData))) { - return true; - } - return false; -} - -bool CheckWorkerPid(int32_t targetPid, int32_t workerPid) -{ - if (workerPid <= 0 || targetPid <= 0) { - return false; - } - auto it = g_processMap.find(targetPid); - if (it != g_processMap.end()) { - if (it->second.deleteFlag) { - if (SendCancelSignal(workerPid) != ResponseCode::REQUEST_SUCCESS) { - return false; - } - - int32_t retCode = ResponseCode::CORE_DUMP_CANCEL; - std::string fileName = "Dump processing has been canceled!"; - SendMsgToCoredumpClient(targetPid, retCode, fileName); - - close(it->second.coredumpSocketId); - g_processMap.erase(it); - } else { - it->second.workerPid = workerPid; - } - return true; - } - return false; -} - -bool RemoveTargetPid(int32_t targetPid) -{ - if (targetPid <= 0) { - return false; - } - auto it = g_processMap.find(targetPid); - if (it != g_processMap.end()) { - close(it->second.coredumpSocketId); - g_processMap.erase(it); - return true; - } - return false; -} - -bool HandleBPAndCleanup(int32_t targetPid, int32_t retCode, std::string& fileName) -{ - if (!SendMsgToCoredumpClient(targetPid, retCode, fileName)) { - DFXLOGE("Send message to blocking interface failed, %{public}s %{public}d", __func__, __LINE__); - } - - if (!RemoveTargetPid(targetPid)) { - DFXLOGE("Remove targetpid %{public}d failed, %{public}s %{public}d", targetPid, __func__, __LINE__); - return false; - } - return true; -} -} // namespace - -int32_t CoredumpStatusService::OnRequest(const std::string& socketName, int32_t connectionFd, - const CoreDumpStatusData& requestData) -{ - DFX_TRACE_SCOPED("CoredumpStatusServiceOnRequest"); - DFXLOGI("Receive signal request for pid:%{public}d, status:%{public}d", requestData.pid, - requestData.coredumpStatus); - - int32_t res = ResponseCode::REQUEST_SUCCESS; - if (requestData.coredumpStatus == CoreDumpStatus::CORE_DUMP_START) { - DFXLOGI("Processdump start %{public}s %{public}d", __func__, __LINE__); - int32_t workerPid = requestData.processDumpPid; - - if (!CheckWorkerPid(requestData.pid, workerPid)) { - DFXLOGE("Check workerpid %{public}d failed", workerPid); - res = ResponseCode::ABNORMAL_SERVICE; - return res; - } - } else if (requestData.coredumpStatus == CoreDumpStatus::CORE_DUMP_END) { - DFXLOGI("Processdump finish %{public}s %{public}d", __func__, __LINE__); - - int32_t targetPid = requestData.pid; - char cfileName[256]; - if (strncpy_s(cfileName, sizeof(cfileName), requestData.fileName, sizeof(cfileName) - 1) != 0) { - DFXLOGE("%{public}s :: strncpy failed.", __func__); - return ResponseCode::DEFAULT_ERROR_CODE; - } - int32_t retCode = requestData.retCode; - std::string fileName = cfileName; - HandleBPAndCleanup(targetPid, retCode, fileName); - - if (g_processMap.empty()) { - DFXLOGE("clean pid success, %{public}s %{public}d", __func__, __LINE__); - } else { - for (const auto& pair : g_processMap) { - DFXLOGE("%{public}d is still dumping!", pair.first); - } - } - } - - SendMsgToSocket(connectionFd, &res, sizeof(res)); - return res; -} - -int32_t CoredumpService::Filter(const std::string& socketName, const CoreDumpRequestData& requestData, uint32_t uid) -{ - if (requestData.pid <= 0 || socketName != SERVER_SOCKET_NAME) { - DFXLOGE("%{public}s :: HandleCoreDumpRequest :: pid(%{public}d) or socketName(%{public}s) fail.", - FAULTLOGGERD_SERVICE_TAG, requestData.pid, socketName.c_str()); - return ResponseCode::REQUEST_REJECT; - } - if (TempFileManager::CheckCrashFileRecord(requestData.pid)) { - DFXLOGW("%{public}s :: pid(%{public}d) has been crashed, break.", - FAULTLOGGERD_SERVICE_TAG, requestData.pid); - return ResponseCode::CORE_PROCESS_CRASHED; - } - return ResponseCode::REQUEST_SUCCESS; -} - -int32_t CoredumpService::OnRequest(const std::string& socketName, int32_t connectionFd, - const CoreDumpRequestData& requestData) -{ - DFX_TRACE_SCOPED("CoredumpServiceOnRequest"); - DFXLOGI("Receive save coredump request for pid:%{public}d.", requestData.pid); - struct ucred creds; - if (!GetUcredByPeerCred(creds, connectionFd)) { - DFXLOGE("Core dump pid(%{public}d) request failed to get cred.", requestData.pid); - return ResponseCode::REQUEST_REJECT; - } - int32_t responseCode = Filter(socketName, requestData, creds.uid); - if (responseCode != ResponseCode::REQUEST_SUCCESS) { - return responseCode; - } - - siginfo_t si{0}; - si.si_signo = SIGLEAK_STACK; //42 - si.si_errno = 0; - si.si_code = SIGLEAK_STACK_COREDUMP; - si.si_pid = static_cast(creds.pid); - if (syscall(SYS_rt_sigqueueinfo, requestData.pid, si.si_signo, &si) != 0) { - DFXLOGE("%{public}s :: Failed to SYS_rt_sigqueueinfo signal(%{public}d), errno(%{public}d).", - FAULTLOGGERD_SERVICE_TAG, si.si_signo, errno); - return ResponseCode::CORE_DUMP_NOPROC; - } - uint64_t endTime = requestData.endTime; - int32_t targetPid = requestData.pid; - int32_t workerPid = -1; - int32_t coredumpSocketId = dup(connectionFd); - - int32_t res = ResponseCode::REQUEST_SUCCESS; - if (g_processMap.find(targetPid) != g_processMap.end()) { - DFXLOGE("%{public}d is generating coredump, please do not repeat dump!", targetPid); - res = ResponseCode::CORE_DUMP_REPEAT; - SendMsgToSocket(coredumpSocketId, &res, sizeof(res)); - return res; - } else { - g_processMap.emplace(targetPid, CoredumpProcessInfo(targetPid, workerPid, coredumpSocketId, endTime, false)); - } - SendMsgToSocket(coredumpSocketId, &res, sizeof(res)); - - auto removeTask = [targetPid]() { - auto it = g_processMap.find(targetPid); - if (it != g_processMap.end()) { - close(it->second.coredumpSocketId); - g_processMap.erase(it); - DFXLOGI("Removed targetPid: %{public}d", targetPid); - } else { - DFXLOGW("targetPid : %{public}d has been removed", targetPid); - } - }; - - int32_t delayMs = endTime - GetAbsTimeMilliSeconds(); - StartDelayTask(removeTask, delayMs); - return res; -} - -void CoredumpService::StartDelayTask(std::function workFunc, int32_t delayTime) -{ - auto delayTask = DelayTask::CreateInstance(workFunc, delayTime); - FaultLoggerDaemon::GetEpollManager(EpollManagerType::MAIN_SERVER).AddListener(std::move(delayTask)); - if (g_processMap.empty()) { - DFXLOGE("clean pid success, %{public}s %{public}d", __func__, __LINE__); - } -} - -int32_t CancelCoredumpService::Filter(const std::string& socketName, const CoreDumpRequestData& requestData, - uint32_t uid) -{ - if (requestData.pid <= 0 || socketName != SERVER_SOCKET_NAME) { - DFXLOGE("%{public}s :: HandleCoreDumpRequest :: pid(%{public}d) or socketName(%{public}s) fail.", - FAULTLOGGERD_SERVICE_TAG, requestData.pid, socketName.c_str()); - return ResponseCode::REQUEST_REJECT; - } - return ResponseCode::REQUEST_SUCCESS; -} - -int32_t CancelCoredumpService::OnRequest(const std::string& socketName, int32_t connectionFd, - const CoreDumpRequestData& requestData) -{ - DFX_TRACE_SCOPED("CancelCoredumpServiceOnRequest"); - DFXLOGI("Receive cancel coredump request for pid:%{public}d.", requestData.pid); - struct ucred creds; - if (!GetUcredByPeerCred(creds, connectionFd)) { - DFXLOGE("Cancel Core dump pid(%{public}d) request failed to get cred.", requestData.pid); - return ResponseCode::REQUEST_REJECT; - } - int32_t responseCode = Filter(socketName, requestData, creds.uid); - if (responseCode != ResponseCode::REQUEST_SUCCESS) { - return responseCode; - } - - int32_t workerPid = -1; - auto it = g_processMap.find(requestData.pid); - if (it == g_processMap.end()) { - DFXLOGE("No need to cancel!"); - int32_t res = ResponseCode::DEFAULT_ERROR_CODE; - SendMsgToSocket(connectionFd, &res, sizeof(res)); - return res; - } - - if (it->second.workerPid != -1) { - workerPid = it->second.workerPid; - DFXLOGI("workerpid get %{public}d %{public}d", workerPid, __LINE__); - - int32_t res = SendCancelSignal(workerPid); - if (res != ResponseCode::REQUEST_SUCCESS) { - return res; - } - int32_t retCode = ResponseCode::CORE_DUMP_CANCEL; - std::string fileName = "Dumping has been canceled!"; - HandleBPAndCleanup(requestData.pid, retCode, fileName); - - if (g_processMap.empty()) { - DFXLOGE("clean pid success, %{public}s %{public}d", __func__, __LINE__); - } else { - for (const auto& pair : g_processMap) { - DFXLOGE("%{public}d is still dumping!", pair.first); - } - } - } else { - DFXLOGE("Can not get processdump pid!"); - it->second.deleteFlag = true; - } - - int32_t res = ResponseCode::REQUEST_SUCCESS; - SendMsgToSocket(connectionFd, &res, sizeof(res)); - - return res; -} - int32_t SdkDumpService::Filter(const std::string& socketName, const SdkDumpRequestData& requestData, uint32_t uid) { if (requestData.pid <= 0 || socketName != SERVER_SDKDUMP_SOCKET_NAME || !CheckCallerUID(uid)) { @@ -568,55 +272,13 @@ int32_t SdkDumpService::Filter(const std::string& socketName, const SdkDumpReque return ResponseCode::REQUEST_SUCCESS; } -int32_t SdkDumpService::SendSigDumpToHapWatchdog(pid_t pid, siginfo_t& si) -{ - long uid = 0; - uint64_t sigBlk = 0; - if (!GetUidAndSigBlk(pid, uid, sigBlk)) { - return ResponseCode::DEFAULT_ERROR_CODE; - }; - constexpr long minUid = 10000; // 10000 : minimum uid for hap - if (uid < minUid || IsSigDumpMask(sigBlk)) { - return ResponseCode::DEFAULT_ERROR_CODE; - } - - pid_t tid = GetTidByThreadName(pid, "OS_DfxWatchdog"); - if (tid <= 0) { - return ResponseCode::DEFAULT_ERROR_CODE; - } -#ifndef FAULTLOGGERD_TEST - if (syscall(SYS_rt_tgsigqueueinfo, pid, tid, si.si_signo, &si) != 0) { - DFXLOGE("%{public}s :: Failed to SYS_rt_tgsigqueueinfo signal(%{public}d), errno(%{public}d).", - FAULTLOGGERD_SERVICE_TAG, si.si_signo, errno); - return ResponseCode::SDK_DUMP_NOPROC; - } -#endif - return ResponseCode::REQUEST_SUCCESS; -} - -int32_t SdkDumpService::SendSigDumpToProcess(pid_t pid, siginfo_t& si) -{ - auto ret = SendSigDumpToHapWatchdog(pid, si); - if (ret == ResponseCode::SDK_DUMP_NOPROC || ret == ResponseCode::REQUEST_SUCCESS) { - return ret; - } -#ifndef FAULTLOGGERD_TEST - if (syscall(SYS_rt_sigqueueinfo, pid, si.si_signo, &si) != 0) { - DFXLOGE("%{public}s :: Failed to SYS_rt_sigqueueinfo signal(%{public}d), errno(%{public}d).", - FAULTLOGGERD_SERVICE_TAG, si.si_signo, errno); - return ResponseCode::SDK_DUMP_NOPROC; - } -#endif - return ResponseCode::REQUEST_SUCCESS; -} - int32_t SdkDumpService::OnRequest(const std::string& socketName, int32_t connectionFd, const SdkDumpRequestData& requestData) { DFX_TRACE_SCOPED("SdkDumpServiceOnRequest"); DFXLOGI("Receive dump request for pid:%{public}d tid:%{public}d.", requestData.pid, requestData.tid); struct ucred creds; - if (!GetUcredByPeerCred(creds, connectionFd)) { + if (!FaultCommonUtil::GetUcredByPeerCred(creds, connectionFd)) { return ResponseCode::REQUEST_REJECT; } int32_t responseCode = Filter(socketName, requestData, creds.uid); @@ -672,7 +334,7 @@ int32_t SdkDumpService::OnRequest(const std::string& socketName, int32_t connect */ auto& faultLoggerPipe = FaultLoggerPipePair::CreateSdkDumpPipePair(requestData.pid, requestData.time); - if (auto ret = SendSigDumpToProcess(requestData.pid, si); ret != ResponseCode::REQUEST_SUCCESS) { + if (auto ret = FaultCommonUtil::SendSignalToProcess(requestData.pid, si); ret != ResponseCode::REQUEST_SUCCESS) { FaultLoggerPipePair::DelSdkDumpPipePair(requestData.pid); return ret; } diff --git a/services/fault_logger_service.h b/services/fault_logger_service.h index c8214294b..57c418cc2 100644 --- a/services/fault_logger_service.h +++ b/services/fault_logger_service.h @@ -23,8 +23,6 @@ #include "dfx_socket_request.h" #include "temp_file_manager.h" #include "dfx_exception.h" -#include -#include namespace OHOS { namespace HiviewDFX { @@ -83,17 +81,6 @@ struct DumpStats { std::string targetProcessName; }; -struct CoredumpProcessInfo { - int32_t targetPid; - int32_t workerPid; - int32_t coredumpSocketId; - int endTime; - bool deleteFlag; - - CoredumpProcessInfo(int32_t target, int32_t worker, int32_t connectionFd, int time, bool flag) - : targetPid(target), workerPid(worker), coredumpSocketId(connectionFd), endTime(time), deleteFlag(flag) {} -}; - class StatsService : public FaultLoggerService { public: int32_t OnRequest(const std::string& socketName, int32_t connectionFd, @@ -115,8 +102,6 @@ public: const SdkDumpRequestData& requestData) override; private: static int32_t Filter(const std::string& socketName, const SdkDumpRequestData& requestData, uint32_t uid); - static int32_t SendSigDumpToProcess(pid_t pid, siginfo_t& si); - static int32_t SendSigDumpToHapWatchdog(pid_t pid, siginfo_t& si); }; class PipeService : public FaultLoggerService { @@ -126,29 +111,6 @@ public: private: static bool Filter(const std::string& socketName, int32_t connectionFd, const PipFdRequestData& requestData); }; - -class CoredumpService : public FaultLoggerService { -public: - int32_t OnRequest(const std::string& socketName, int32_t connectionFd, - const CoreDumpRequestData& requestData) override; -private: - static int32_t Filter(const std::string& socketName, const CoreDumpRequestData& requestData, uint32_t uid); - void StartDelayTask(std::function workFunc, int32_t delayTime); -}; - -class CancelCoredumpService : public FaultLoggerService { -public: - int32_t OnRequest(const std::string& socketName, int32_t connectionFd, - const CoreDumpRequestData& requestData) override; -private: - static int32_t Filter(const std::string& socketName, const CoreDumpRequestData& requestData, uint32_t uid); -}; - -class CoredumpStatusService : public FaultLoggerService { -public: - int32_t OnRequest(const std::string& socketName, int32_t connectionFd, - const CoreDumpStatusData& requestData) override; -}; #endif } } diff --git a/test/systemtest/faultloggerd_system_test.cpp b/test/systemtest/faultloggerd_system_test.cpp index d39507e61..cd59868c9 100644 --- a/test/systemtest/faultloggerd_system_test.cpp +++ b/test/systemtest/faultloggerd_system_test.cpp @@ -1663,57 +1663,6 @@ HWTEST_F(FaultLoggerdSystemTest, FaultLoggerdSystemTest124, TestSize.Level2) } #endif -HWTEST_F(FaultLoggerdSystemTest, CoreDumpCbTest001, TestSize.Level2) -{ - GTEST_LOG_(INFO) << "CoreDumpCbTest001: start."; - - int32_t retCode = ResponseCode::REQUEST_SUCCESS; - std::string fileName = "com.ohos.sceneboard.dmp"; - ASSERT_EQ(StartCoredumpCb(getpid(), getpid()), ResponseCode::REQUEST_SUCCESS); - ASSERT_EQ(FinishCoredumpCb(getpid(), fileName, retCode), ResponseCode::REQUEST_SUCCESS); - GTEST_LOG_(INFO) << "CoreDumpCbTest001: end."; -} - -HWTEST_F(FaultLoggerdSystemTest, CoreDumpCbTest002, TestSize.Level2) -{ - GTEST_LOG_(INFO) << "CoreDumpCbTest002: start."; - -#if defined(__aarch64__) - std::string appName = "com.ohos.sceneboard"; - pid_t pid = GetProcessPid(appName); - if (pid > 0) { - auto ret = SaveCoredumpToFileTimeout(pid); - ASSERT_NE(ret.compare(""), 0); - } else { - FAIL() << "CoreDumpCbTest002: " << appName << "not running."; - } -#endif - GTEST_LOG_(INFO) << "CoreDumpCbTest002: end."; -} - -HWTEST_F(FaultLoggerdSystemTest, CoreDumpCbTest003, TestSize.Level2) -{ - GTEST_LOG_(INFO) << "CoreDumpCbTest003: start."; - -#if defined(__aarch64__) - std::string appName = "com.ohos.sceneboard"; - pid_t pid = GetProcessPid(appName); - if (pid > 0) { - auto threadFunc = [pid]() { - sleep(1); - CancelCoredump(pid); - }; - - std::thread t(threadFunc); - t.detach(); - SaveCoredumpToFileTimeout(pid); - } else { - FAIL() << "CoreDumpCbTest003: " << appName << "not running."; - } -#endif - GTEST_LOG_(INFO) << "CoreDumpCbTest003: end."; -} - /** * @tc.name: FaultLoggerdSystemTest125 * @tc.desc: Test process exit after being killed diff --git a/test/unittest/faultloggerd/BUILD.gn b/test/unittest/faultloggerd/BUILD.gn index 2355a427b..4538769eb 100644 --- a/test/unittest/faultloggerd/BUILD.gn +++ b/test/unittest/faultloggerd/BUILD.gn @@ -63,6 +63,8 @@ if (defined(ohos_lite)) { "$faultloggerd_path/services/fault_logger_server.cpp", "$faultloggerd_path/services/fault_logger_service.cpp", "$faultloggerd_path/services/temp_file_manager.cpp", + "$faultloggerd_path/services/fault_common_util.cpp", + "$faultloggerd_path/services/fault_coredump_service.cpp", "faultlogger_server_test.cpp", "faultloggerd_test.cpp", "temp_file_manager_test.cpp", diff --git a/test/unittest/faultloggerd/faultlogger_server_test.cpp b/test/unittest/faultloggerd/faultlogger_server_test.cpp index ea9f13ec0..660b3ceaa 100644 --- a/test/unittest/faultloggerd/faultlogger_server_test.cpp +++ b/test/unittest/faultloggerd/faultlogger_server_test.cpp @@ -32,6 +32,7 @@ #include "faultloggerd_client.h" #include "faultloggerd_socket.h" #include "faultloggerd_test.h" +#include "fault_common_util.h" #include "smart_fd.h" using namespace OHOS::HiviewDFX; @@ -226,13 +227,13 @@ HWTEST_F(FaultLoggerdServiceTest, SdkDumpServiceTest001, TestSize.Level2) pid_t pid; pid = getpid(); siginfo_t si; - auto ret = SdkDumpService::SendSigDumpToHapWatchdog(pid, si); + auto ret = FaultCommonUtil::SendSignalToHapWatchdogThread(pid, si); EXPECT_EQ(ret, ResponseCode::DEFAULT_ERROR_CODE); #if defined(__aarch64__) std::string appName = "com.ohos.sceneboard"; pid = GetProcessPid(appName); if (pid > 0) { - ret = SdkDumpService::SendSigDumpToHapWatchdog(pid, si); // sceneboard is mask + ret = FaultCommonUtil::SendSignalToHapWatchdogThread(pid, si); // sceneboard is mask EXPECT_EQ(ret, ResponseCode::DEFAULT_ERROR_CODE); } else { FAIL() << "SdkDumpServiceTest001: " << appName << " not running."; @@ -248,7 +249,7 @@ HWTEST_F(FaultLoggerdServiceTest, SdkDumpServiceTest002, TestSize.Level2) { pid_t pid = getpid(); siginfo_t si; - auto ret = SdkDumpService::SendSigDumpToProcess(pid, si); + auto ret = FaultCommonUtil::SendSignalToProcess(pid, si); EXPECT_EQ(ret, ResponseCode::REQUEST_SUCCESS); } /** diff --git a/test/unittest/faultloggerd/faultloggerd_client_test.cpp b/test/unittest/faultloggerd/faultloggerd_client_test.cpp index b1f0b97ef..2a832cbb3 100644 --- a/test/unittest/faultloggerd/faultloggerd_client_test.cpp +++ b/test/unittest/faultloggerd/faultloggerd_client_test.cpp @@ -29,6 +29,8 @@ #include "dfx_test_util.h" #include "dfx_util.h" #include "faultloggerd_client.h" +#include "fault_common_util.h" +#include "fault_coredump_service.h" #include "faultloggerd_test.h" #include "fault_logger_daemon.h" #include "smart_fd.h" @@ -56,6 +58,253 @@ void FaultloggerdClientTest::SetUpTestCase() std::this_thread::sleep_for(std::chrono::milliseconds(waitTime)); } +/** + * @tc.name: SendSignalToHapWatchdogThreadTest + * @tc.desc: Test send signal to watchdog thread + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdClientTest, SendSignalToHapWatchdogThreadTest, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "SendSignalToHapWatchdogThreadTest: start."; + pid_t pid = -1; + siginfo_t si = {}; + ASSERT_EQ(FaultCommonUtil::SendSignalToHapWatchdogThread(pid, si), ResponseCode::DEFAULT_ERROR_CODE); + GTEST_LOG_(INFO) << "SendSignalToHapWatchdogThreadTest: end."; +} + +/** + * @tc.name: SendSignalToProcessTest + * @tc.desc: SendSignalToProcess + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdClientTest, SendSignalToProcessTest, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "SendSignalToProcessTest: start."; + pid_t pid = -1; + siginfo_t si = {}; + ASSERT_EQ(FaultCommonUtil::SendSignalToProcess(pid, si), ResponseCode::REQUEST_SUCCESS); + GTEST_LOG_(INFO) << "SendSignalToProcessTest: end."; +} + +/** + * @tc.name: GetUcredByPeerCredTest + * @tc.desc: GetUcredByPeerCred + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdClientTest, GetUcredByPeerCredTest, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "GetUcredByPeerCredTest: start."; + int32_t connectionFd = 0; + struct ucred rcred; + bool result = FaultCommonUtil::GetUcredByPeerCred(rcred, connectionFd); + EXPECT_FALSE(result); + GTEST_LOG_(INFO) << "GetUcredByPeerCredTest: end."; +} + +/** + * @tc.name: HandleProcessDumpPidTest001 + * @tc.desc: HandleProcessDumpPid + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdClientTest, HandleProcessDumpPidTest001, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "HandleProcessDumpPidTest001: start."; + int32_t targetPid = 123; + int32_t processDumpPid = -1; + CoredumpStatusService coredumpStatusService; + EXPECT_FALSE(coredumpStatusService.HandleProcessDumpPid(targetPid, processDumpPid)); + + GTEST_LOG_(INFO) << "HandleProcessDumpPidTest001: end."; +} + +/** + * @tc.name: HandleProcessDumpPidTest002 + * @tc.desc: HandleProcessDumpPid + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdClientTest, HandleProcessDumpPidTest002, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "HandleProcessDumpPidTest002: start."; + int32_t targetPid = 123; + int32_t processDumpPid = 456; + CoredumpStatusService coredumpStatusService; + EXPECT_FALSE(coredumpStatusService.HandleProcessDumpPid(targetPid, processDumpPid)); + GTEST_LOG_(INFO) << "HandleProcessDumpPidTest002: end."; +} + +/** + * @tc.name: DoCoredumpRequestTest + * @tc.desc: DoCoredumpRequest + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdClientTest, DoCoredumpRequestTest, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "DoCoredumpRequestTest: start."; + std::string socketName = "test_socket"; + int32_t connectionFd = 1; + CoreDumpRequestData requestData = {}; + CoredumpService coredumpService; + ASSERT_EQ(coredumpService.DoCoredumpRequest(socketName, connectionFd, requestData), ResponseCode::REQUEST_REJECT); + GTEST_LOG_(INFO) << "DoCoredumpRequestTest: end."; +} + +/** + * @tc.name: RecorderProcessMapTest + * @tc.desc: RecorderProcessMap + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdClientTest, RecorderProcessMapTest, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "RecorderProcessMapTest: start."; + RecorderProcessMap recorderProcessMap; + int32_t coredumpSocketId = 0; + int32_t processDumpPid = getpid(); + bool flag = false; + EXPECT_FALSE(recorderProcessMap.ClearTargetPid(getpid())); + EXPECT_FALSE(recorderProcessMap.SetCancelFlag(getpid(), true)); + EXPECT_FALSE(recorderProcessMap.SetProcessDumpPid(getpid(), getpid())); + EXPECT_FALSE(recorderProcessMap.GetCoredumpSocketId(getpid(), coredumpSocketId)); + EXPECT_FALSE(recorderProcessMap.GetProcessDumpPid(getpid(), processDumpPid)); + EXPECT_FALSE(recorderProcessMap.GetCancelFlag(getpid(), flag)); + GTEST_LOG_(INFO) << "RecorderProcessMapTest: end."; +} + +/** + * @tc.name: CoreDumpCbTest001 + * @tc.desc: Test startcoredumpcb and finishcoredumpcb process + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdClientTest, CoreDumpCbTest001, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "CoreDumpCbTest001: start."; + int32_t retCode = ResponseCode::REQUEST_SUCCESS; + std::string fileName = "com.ohos.sceneboard.dmp"; + ASSERT_EQ(StartCoredumpCb(getpid(), getpid()), ResponseCode::ABNORMAL_SERVICE); + ASSERT_EQ(FinishCoredumpCb(getpid(), fileName, retCode), ResponseCode::REQUEST_SUCCESS); + GTEST_LOG_(INFO) << "CoreDumpCbTest001: end."; +} + +/** + * @tc.name: CoreDumpCbTest002 + * @tc.desc: Test coredump process + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdClientTest, CoreDumpCbTest002, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "CoreDumpCbTest002: start."; + int32_t retCode = ResponseCode::REQUEST_SUCCESS; + std::string fileName = "com.ohos.sceneboard.dmp"; + + auto threadFunc = [&fileName, retCode]() { + sleep(1); + StartCoredumpCb(getpid(), getpid()); + FinishCoredumpCb(getpid(), fileName, retCode); + }; + + std::thread t(threadFunc); + t.detach(); + auto ret = SaveCoredumpToFileTimeout(getpid()); + ASSERT_EQ(ret, "com.ohos.sceneboard.dmp"); + GTEST_LOG_(INFO) << "CoreDumpCbTest002: end."; +} + +/** + * @tc.name: CoreDumpCbTest003 + * @tc.desc: Test coredump cancel process + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdClientTest, CoreDumpCbTest003, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "CoreDumpCbTest003: start."; + auto threadFunc = []() { + sleep(1); + ASSERT_EQ(CancelCoredump(getpid()), ResponseCode::REQUEST_SUCCESS); + StartCoredumpCb(getpid(), getpid()); // to clean processmap + }; + + std::thread t(threadFunc); + t.detach(); + auto ret = SaveCoredumpToFileTimeout(getpid()); + ASSERT_EQ(ret, ""); + GTEST_LOG_(INFO) << "CoreDumpCbTest003: end."; +} + +/** + * @tc.name: CoreDumpCbTest004 + * @tc.desc: Test coredump cancel process + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdClientTest, CoreDumpCbTest004, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "CoreDumpCbTest004: start."; + auto threadFunc = []() { + sleep(1); + StartCoredumpCb(getpid(), getpid()); + ASSERT_EQ(CancelCoredump(getpid()), ResponseCode::REQUEST_SUCCESS); + }; + + std::thread t(threadFunc); + t.detach(); + auto ret = SaveCoredumpToFileTimeout(getpid()); + ASSERT_EQ(ret, ""); + GTEST_LOG_(INFO) << "CoreDumpCbTest004: end."; +} + +/** + * @tc.name: CoreDumpCbTest005 + * @tc.desc: Test coredump cancel process + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdClientTest, CoreDumpCbTest005, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "CoreDumpCbTest005: start."; + ASSERT_EQ(CancelCoredump(getpid()), ResponseCode::DEFAULT_ERROR_CODE); + GTEST_LOG_(INFO) << "CoreDumpCbTest005: end."; +} + +/** + * @tc.name: CoreDumpCbTest006 + * @tc.desc: Test coredump repeat process + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdClientTest, CoreDumpCbTest006, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "CoreDumpCbTest006: start."; + int32_t retCode = ResponseCode::REQUEST_SUCCESS; + std::string fileName = "com.ohos.sceneboard.dmp"; + + auto threadFunc = [&fileName, retCode]() { + sleep(1); + ASSERT_EQ(SaveCoredumpToFileTimeout(getpid()), ""); + StartCoredumpCb(getpid(), getpid()); + FinishCoredumpCb(getpid(), fileName, retCode); + }; + + std::thread t(threadFunc); + t.detach(); + auto ret = SaveCoredumpToFileTimeout(getpid()); + ASSERT_EQ(ret, "com.ohos.sceneboard.dmp"); + GTEST_LOG_(INFO) << "CoreDumpCbTest006: end."; +} + +/** + * @tc.name: CoreDumpCbTest007 + * @tc.desc: Test coredump process when targetPid = -1 + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdClientTest, CoreDumpCbTest007, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "CoreDumpCbTest007: start."; + int32_t targetPid = -1; + int32_t retCode = ResponseCode::REQUEST_SUCCESS; + std::string fileName = "com.ohos.sceneboard.dmp"; + ASSERT_EQ(SaveCoredumpToFileTimeout(targetPid), ""); + ASSERT_EQ(CancelCoredump(targetPid), ResponseCode::DEFAULT_ERROR_CODE); + ASSERT_EQ(StartCoredumpCb(targetPid, getpid()), ResponseCode::DEFAULT_ERROR_CODE); + ASSERT_EQ(FinishCoredumpCb(targetPid, fileName, retCode), ResponseCode::DEFAULT_ERROR_CODE); + GTEST_LOG_(INFO) << "CoreDumpCbTest007: end."; +} + /** * @tc.name: RequestSdkDumpTest001 * @tc.desc: test the function for RequestSdkDump. -- Gitee