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 "faultlogger_service_ohos.h" 16 17#include <functional> 18#include <string> 19#include <vector> 20 21#include "if_system_ability_manager.h" 22#include "ipc_skeleton.h" 23#include "iservice_registry.h" 24#include "system_ability_definition.h" 25 26#include "hiview_logger.h" 27 28#include "faultlog_info.h" 29#include "faultlog_info_ohos.h" 30#include "faultlog_query_result_inner.h" 31#include "faultlog_query_result_ohos.h" 32#include "faultlogger.h" 33 34DEFINE_LOG_LABEL(0xD002D11, "FaultloggerServiceOhos"); 35namespace OHOS { 36namespace HiviewDFX { 37namespace { 38constexpr int32_t UID_SHELL = 2000; 39constexpr int32_t UID_ROOT = 0; 40constexpr int32_t UID_HIDUMPER = 1212; 41constexpr int32_t UID_HIVIEW = 1201; 42} 43void FaultloggerServiceOhos::ClearQueryStub(int32_t uid) 44{ 45 std::lock_guard<std::mutex> lock(mutex_); 46 queries_.erase(uid); 47} 48 49int32_t FaultloggerServiceOhos::Dump(int32_t fd, const std::vector<std::u16string> &args) 50{ 51 int32_t uid = IPCSkeleton::GetCallingUid(); 52 if ((uid != UID_SHELL) && (uid != UID_ROOT) && (uid != UID_HIDUMPER)) { 53 dprintf(fd, "No permission for uid:%d.\n", uid); 54 return -1; 55 } 56 57 std::vector<std::string> cmdList; 58 for (auto arg : args) { 59 for (auto c : arg) { 60 if (!isalnum(c) && c != '-' && c != ' ' && c != '_' && c != '.') { 61 dprintf(fd, "string arg contain invalid char:%c.\n", c); 62 return -1; 63 } 64 } 65 } 66 std::transform(args.begin(), args.end(), std::back_inserter(cmdList), [](const std::u16string &arg) { 67 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> converter; 68 return converter.to_bytes(arg); 69 }); 70 71 auto service = GetOrSetFaultlogger(); 72 if (service == nullptr) { 73 dprintf(fd, "Service is not ready.\n"); 74 return -1; 75 } 76 77 service->Dump(fd, cmdList); 78 return 0; 79} 80 81void FaultloggerServiceOhos::StartService(OHOS::HiviewDFX::Faultlogger *service) 82{ 83 GetOrSetFaultlogger(service); 84 sptr<ISystemAbilityManager> serviceManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 85 if (serviceManager == nullptr) { 86 HIVIEW_LOGE("Failed to find samgr, exit."); 87 return; 88 } 89 90 static sptr<FaultloggerServiceOhos> instance = new FaultloggerServiceOhos(); 91 serviceManager->AddSystemAbility(DFX_FAULT_LOGGER_ABILITY_ID, instance); 92 HIVIEW_LOGI("FaultLogger Service started."); 93} 94 95OHOS::HiviewDFX::Faultlogger *FaultloggerServiceOhos::GetOrSetFaultlogger( 96 OHOS::HiviewDFX::Faultlogger *service) 97{ 98 static OHOS::HiviewDFX::Faultlogger *ref = nullptr; 99 if (service != nullptr) { 100 ref = service; 101 } 102 return ref; 103} 104 105void FaultloggerServiceOhos::AddFaultLog(const FaultLogInfoOhos& info) 106{ 107 auto service = GetOrSetFaultlogger(); 108 if (service == nullptr) { 109 return; 110 } 111 112 int32_t uid = IPCSkeleton::GetCallingUid(); 113 HIVIEW_LOGD("info.uid:%{public}d uid:%{public}d info.pid:%{public}d", info.uid, uid, info.pid); 114 if (((uid != static_cast<int32_t>(getuid()))) && (uid != info.uid)) { 115 HIVIEW_LOGW("Fail to add fault log, mismatch uid:%{public}d(%{public}d)", uid, info.uid); 116 return; 117 } 118 119 FaultLogInfo outInfo; 120 outInfo.time = info.time; 121 outInfo.id = info.uid; 122 outInfo.pid = info.pid; 123 auto fdDeleter = [] (int32_t *ptr) { 124 if (*ptr > 0) { 125 close(*ptr); 126 } 127 delete ptr; 128 }; 129 outInfo.pipeFd.reset(new int32_t(info.pipeFd), fdDeleter); 130 outInfo.faultLogType = info.faultLogType; 131 outInfo.fd = (info.fd > 0) ? dup(info.fd) : -1; 132 outInfo.module = info.module; 133 outInfo.reason = info.reason; 134 outInfo.summary = info.summary; 135 if (uid == UID_HIVIEW) { 136 outInfo.logPath = info.logPath; 137 } 138 outInfo.registers = info.registers; 139 outInfo.sectionMap = info.sectionMaps; 140 service->AddFaultLog(outInfo); 141} 142 143sptr<IRemoteObject> FaultloggerServiceOhos::QuerySelfFaultLog(int32_t faultType, int32_t maxNum) 144{ 145 auto service = GetOrSetFaultlogger(); 146 if (service == nullptr) { 147 return nullptr; 148 } 149 150 int32_t uid = IPCSkeleton::GetCallingUid(); 151 int32_t pid = IPCSkeleton::GetCallingPid(); 152 std::lock_guard<std::mutex> lock(mutex_); 153 if ((queries_.find(uid) != queries_.end()) && 154 (queries_[uid]->pid == pid)) { 155 HIVIEW_LOGW("Ongoing query is still alive for uid:%d", uid); 156 return nullptr; 157 } 158 159 auto queryResult = service->QuerySelfFaultLog(uid, pid, faultType, maxNum); 160 if (queryResult == nullptr) { 161 HIVIEW_LOGW("Fail to query fault log for uid:%d", uid); 162 return nullptr; 163 } 164 165 sptr<FaultLogQueryResultOhos> resultRef = 166 new FaultLogQueryResultOhos(std::move(queryResult)); 167 auto queryStub = std::make_unique<FaultLogQuery>(); 168 queryStub->pid = pid; 169 queryStub->ptr = resultRef; 170 queries_[uid] = std::move(queryStub); 171 return resultRef->AsObject(); 172} 173 174void FaultloggerServiceOhos::Destroy() 175{ 176 auto service = GetOrSetFaultlogger(); 177 if (service == nullptr) { 178 return; 179 } 180 181 int32_t uid = IPCSkeleton::GetCallingUid(); 182 HIVIEW_LOGI("Destroy Query from uid:%d", uid); 183 ClearQueryStub(uid); 184} 185} // namespace HiviewDFX 186} // namespace OHOS