1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved.
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
16 #include "hook_service.h"
17
18 #include "hook_manager.h"
19 #include <cinttypes>
20 #include <unistd.h>
21
22 #include "common.h"
23 #include "logging.h"
24 #include "parameter.h"
25 #include "socket_context.h"
26
27 namespace OHOS::Developtools::NativeDaemon {
HookService(const ClientConfig & clientConfig,std::shared_ptr<HookManager> hook,bool multipleProcesses)28 HookService::HookService(const ClientConfig& clientConfig, std::shared_ptr<HookManager> hook, bool multipleProcesses)
29 : clientConfig_(clientConfig), hookMgr_(hook), multipleProcesses_(multipleProcesses)
30 {
31 serviceName_ = "HookService";
32 StartService(DEFAULT_UNIX_SOCKET_HOOK_PATH);
33 }
34
~HookService()35 HookService::~HookService()
36 {
37 serviceEntry_ = nullptr;
38 }
39
StartService(const std::string & unixSocketName)40 bool HookService::StartService(const std::string& unixSocketName)
41 {
42 serviceEntry_ = std::make_shared<ServiceEntry>();
43 if (!serviceEntry_->StartServer(unixSocketName)) {
44 serviceEntry_ = nullptr;
45 PROFILER_LOG_DEBUG(LOG_CORE, "Start IPC Service FAIL");
46 return false;
47 }
48 serviceEntry_->RegisterService(*this);
49 return true;
50 }
51
ProtocolProc(SocketContext & context,uint32_t pnum,const int8_t * buf,const uint32_t size)52 bool HookService::ProtocolProc(SocketContext &context, uint32_t pnum, const int8_t *buf, const uint32_t size)
53 {
54 if (size != sizeof(int)) {
55 return false;
56 }
57 int peerConfig = *const_cast<int *>(reinterpret_cast<const int *>(buf));
58 if (peerConfig == -1) {
59 return false;
60 }
61 hookMgr_->SetPid(peerConfig);
62 std::string filePath = "/proc/" + std::to_string(peerConfig) + "/cmdline";
63 std::string bundleName;
64 if (!LoadStringFromFile(filePath, bundleName)) {
65 PROFILER_LOG_ERROR(LOG_CORE, "Get process name by pid failed!, pid: %d", peerConfig);
66 return false;
67 }
68 hookMgr_->SetPid(peerConfig);
69 bundleName.resize(strlen(bundleName.c_str()));
70
71 if (bundleName.size() >= 2 && bundleName.substr(0, 2) == "./") { // 2: size
72 bundleName = bundleName.substr(2); // 2: point
73 }
74 size_t found = bundleName.rfind("/");
75 std::string procName;
76 if (found != std::string::npos) {
77 procName = bundleName.substr(found + 1);
78 } else {
79 procName = bundleName;
80 }
81
82 std::lock_guard<std::mutex> lock(mtx_);
83 if ((!firstProcess_) && (!multipleProcesses_)) {
84 return false;
85 }
86 firstProcess_ = false;
87 auto [eventFd, smbFd] = hookMgr_->GetFds(peerConfig, procName);
88 if (eventFd == smbFd) {
89 PROFILER_LOG_ERROR(LOG_CORE, "Get eventFd and smbFd failed!, name: %s, pid: %d", procName.c_str(), peerConfig);
90 return false;
91 }
92
93 PROFILER_LOG_DEBUG(LOG_CORE, "ProtocolProc, receive message from hook client, and send hook config to process %d",
94 peerConfig);
95 context.SendHookConfig(reinterpret_cast<uint8_t *>(&clientConfig_), sizeof(clientConfig_));
96 context.SendFileDescriptor(smbFd);
97 context.SendFileDescriptor(eventFd);
98 hookMgr_->ResetStartupParam();
99 return true;
100 }
101 }