106f6ba60Sopenharmony_ci/* 206f6ba60Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. 306f6ba60Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 406f6ba60Sopenharmony_ci * you may not use this file except in compliance with the License. 506f6ba60Sopenharmony_ci * You may obtain a copy of the License at 606f6ba60Sopenharmony_ci * 706f6ba60Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 806f6ba60Sopenharmony_ci * 906f6ba60Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1006f6ba60Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1106f6ba60Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1206f6ba60Sopenharmony_ci * See the License for the specific language governing permissions and 1306f6ba60Sopenharmony_ci * limitations under the License. 1406f6ba60Sopenharmony_ci */ 1506f6ba60Sopenharmony_ci 1606f6ba60Sopenharmony_ci#include "hook_service.h" 1706f6ba60Sopenharmony_ci 1806f6ba60Sopenharmony_ci#include "hook_manager.h" 1906f6ba60Sopenharmony_ci#include <cinttypes> 2006f6ba60Sopenharmony_ci#include <unistd.h> 2106f6ba60Sopenharmony_ci 2206f6ba60Sopenharmony_ci#include "common.h" 2306f6ba60Sopenharmony_ci#include "logging.h" 2406f6ba60Sopenharmony_ci#include "parameter.h" 2506f6ba60Sopenharmony_ci#include "socket_context.h" 2606f6ba60Sopenharmony_ci 2706f6ba60Sopenharmony_cinamespace OHOS::Developtools::NativeDaemon { 2806f6ba60Sopenharmony_ciHookService::HookService(const ClientConfig& clientConfig, std::shared_ptr<HookManager> hook, bool multipleProcesses) 2906f6ba60Sopenharmony_ci : clientConfig_(clientConfig), hookMgr_(hook), multipleProcesses_(multipleProcesses) 3006f6ba60Sopenharmony_ci{ 3106f6ba60Sopenharmony_ci serviceName_ = "HookService"; 3206f6ba60Sopenharmony_ci if (getuid() == 0) { 3306f6ba60Sopenharmony_ci StartService(DEFAULT_UNIX_SOCKET_HOOK_FULL_PATH); 3406f6ba60Sopenharmony_ci } else { 3506f6ba60Sopenharmony_ci StartService(DEFAULT_UNIX_SOCKET_HOOK_PATH); 3606f6ba60Sopenharmony_ci } 3706f6ba60Sopenharmony_ci} 3806f6ba60Sopenharmony_ci 3906f6ba60Sopenharmony_ciHookService::~HookService() 4006f6ba60Sopenharmony_ci{ 4106f6ba60Sopenharmony_ci serviceEntry_ = nullptr; 4206f6ba60Sopenharmony_ci} 4306f6ba60Sopenharmony_ci 4406f6ba60Sopenharmony_cibool HookService::StartService(const std::string& unixSocketName) 4506f6ba60Sopenharmony_ci{ 4606f6ba60Sopenharmony_ci serviceEntry_ = std::make_shared<ServiceEntry>(); 4706f6ba60Sopenharmony_ci if (!serviceEntry_->StartServer(unixSocketName)) { 4806f6ba60Sopenharmony_ci serviceEntry_ = nullptr; 4906f6ba60Sopenharmony_ci PROFILER_LOG_DEBUG(LOG_CORE, "Start IPC Service FAIL"); 5006f6ba60Sopenharmony_ci return false; 5106f6ba60Sopenharmony_ci } 5206f6ba60Sopenharmony_ci serviceEntry_->RegisterService(*this); 5306f6ba60Sopenharmony_ci return true; 5406f6ba60Sopenharmony_ci} 5506f6ba60Sopenharmony_ci 5606f6ba60Sopenharmony_cibool HookService::ProtocolProc(SocketContext &context, uint32_t pnum, const int8_t *buf, const uint32_t size) 5706f6ba60Sopenharmony_ci{ 5806f6ba60Sopenharmony_ci if (size != sizeof(int)) { 5906f6ba60Sopenharmony_ci return false; 6006f6ba60Sopenharmony_ci } 6106f6ba60Sopenharmony_ci int peerConfig = *const_cast<int *>(reinterpret_cast<const int *>(buf)); 6206f6ba60Sopenharmony_ci if (peerConfig == -1) { 6306f6ba60Sopenharmony_ci return false; 6406f6ba60Sopenharmony_ci } 6506f6ba60Sopenharmony_ci hookMgr_->SetPid(peerConfig); 6606f6ba60Sopenharmony_ci std::string filePath = "/proc/" + std::to_string(peerConfig) + "/cmdline"; 6706f6ba60Sopenharmony_ci std::string bundleName; 6806f6ba60Sopenharmony_ci if (!LoadStringFromFile(filePath, bundleName)) { 6906f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "Get process name by pid failed!, pid: %d", peerConfig); 7006f6ba60Sopenharmony_ci return false; 7106f6ba60Sopenharmony_ci } 7206f6ba60Sopenharmony_ci hookMgr_->SetPid(peerConfig); 7306f6ba60Sopenharmony_ci bundleName.resize(strlen(bundleName.c_str())); 7406f6ba60Sopenharmony_ci 7506f6ba60Sopenharmony_ci if (bundleName.substr(0, 2) == "./") { // 2: size 7606f6ba60Sopenharmony_ci bundleName = bundleName.substr(2); // 2: point 7706f6ba60Sopenharmony_ci } 7806f6ba60Sopenharmony_ci size_t found = bundleName.rfind("/"); 7906f6ba60Sopenharmony_ci std::string procName; 8006f6ba60Sopenharmony_ci if (found != std::string::npos) { 8106f6ba60Sopenharmony_ci procName = bundleName.substr(found + 1); 8206f6ba60Sopenharmony_ci } else { 8306f6ba60Sopenharmony_ci procName = bundleName; 8406f6ba60Sopenharmony_ci } 8506f6ba60Sopenharmony_ci 8606f6ba60Sopenharmony_ci std::lock_guard<std::mutex> lock(mtx_); 8706f6ba60Sopenharmony_ci if ((!firstProcess_) && (!multipleProcesses_)) { 8806f6ba60Sopenharmony_ci return false; 8906f6ba60Sopenharmony_ci } 9006f6ba60Sopenharmony_ci firstProcess_ = false; 9106f6ba60Sopenharmony_ci auto [eventFd, smbFd] = hookMgr_->GetFds(peerConfig, procName); 9206f6ba60Sopenharmony_ci if (eventFd == smbFd) { 9306f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "Get eventFd and smbFd failed!, name: %s, pid: %d", procName.c_str(), peerConfig); 9406f6ba60Sopenharmony_ci return false; 9506f6ba60Sopenharmony_ci } 9606f6ba60Sopenharmony_ci 9706f6ba60Sopenharmony_ci PROFILER_LOG_DEBUG(LOG_CORE, "ProtocolProc, receive message from hook client, and send hook config to process %d", 9806f6ba60Sopenharmony_ci peerConfig); 9906f6ba60Sopenharmony_ci context.SendHookConfig(reinterpret_cast<uint8_t *>(&clientConfig_), sizeof(clientConfig_)); 10006f6ba60Sopenharmony_ci context.SendFileDescriptor(smbFd); 10106f6ba60Sopenharmony_ci context.SendFileDescriptor(eventFd); 10206f6ba60Sopenharmony_ci hookMgr_->ResetStartupParam(); 10306f6ba60Sopenharmony_ci return true; 10406f6ba60Sopenharmony_ci} 10506f6ba60Sopenharmony_ci}