1 /*
2 * Copyright (c) 2021-2022 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
16 #include "hook_socket_client.h"
17
18 #include "common.h"
19 #include "hook_common.h"
20 #include "unix_socket_client.h"
21 #include "logging.h"
22
23 namespace {
24 const int MOVE_BIT_8 = 8;
25 const int MOVE_BIT_32 = 32;
26 const int MOVE_BIT_48 = 48;
27 const int MOVE_BIT_56 = 56;
28 constexpr int FLUSH_FLAG = 20;
29 int g_flushCount = 0;
30 } // namespace
31
HookSocketClient(int pid,ClientConfig * config)32 HookSocketClient::HookSocketClient(int pid, ClientConfig *config) : pid_(pid), config_(config)
33 {
34 smbFd_ = 0;
35 eventFd_ = 0;
36 unixSocketClient_ = nullptr;
37 serviceName_ = "HookService";
38 Connect(DEFAULT_UNIX_SOCKET_HOOK_FULL_PATH);
39 }
40
~HookSocketClient()41 HookSocketClient::~HookSocketClient()
42 {
43 unixSocketClient_ = nullptr;
44 stackWriter_ = nullptr;
45 }
46
Connect(const std::string addrname)47 bool HookSocketClient::Connect(const std::string addrname)
48 {
49 if (unixSocketClient_ != nullptr) {
50 return false;
51 }
52 unixSocketClient_ = std::make_shared<UnixSocketClient>();
53 if (!unixSocketClient_->Connect(addrname, *this)) {
54 unixSocketClient_ = nullptr;
55 return false;
56 }
57
58 unixSocketClient_->SendHookConfig(pid_);
59 return true;
60 }
61
62 // config |F F F F F F F F F F F F F F F F|
63 // malloctype stack depth filtersize sharememory size
ProtocolProc(SocketContext & context,uint32_t pnum,const int8_t * buf,const uint32_t size)64 bool HookSocketClient::ProtocolProc(SocketContext &context, uint32_t pnum, const int8_t *buf, const uint32_t size)
65 {
66 if (size != sizeof(uint64_t)) {
67 HILOG_ERROR(LOG_CORE, "HookSocketClient::config config size not match = %u\n", size);
68 return true;
69 }
70 uint64_t config = *(uint64_t *)buf;
71 uint32_t smbSize = (uint32_t)config;
72 config_->filterSize_ = (uint16_t)(config >> MOVE_BIT_32);
73
74 uint16_t mask = (uint16_t)(config >> MOVE_BIT_48);
75 config_->maxStackDepth_ = (uint8_t)(mask >> MOVE_BIT_8);
76 config_->maxStackDepth_ = config_->maxStackDepth_ > MAX_UNWIND_DEPTH ? MAX_UNWIND_DEPTH : config_->maxStackDepth_;
77 smbFd_ = context.ReceiveFileDiscriptor();
78 eventFd_ = context.ReceiveFileDiscriptor();
79
80 if (mask & MALLOCDISABLE) {
81 config_->mallocDisable_ = true;
82 }
83 if (mask & MMAPDISABLE) {
84 config_->mmapDisable_ = true;
85 }
86 if (mask & FREEMSGSTACK) {
87 config_->freeStackData_ = true;
88 }
89 if (mask & MUNMAPMSGSTACK) {
90 config_->munmapStackData_ = true;
91 }
92 if (mask & FPUNWIND) {
93 config_->fpunwind_ = true;
94 }
95 if ((mask & BLOCKED) != 0) {
96 config_->isBlocked = true;
97 }
98 HILOG_INFO(LOG_CORE, "%s: mallocDisable = %d mmapDisable = %d", __func__,
99 config_->mallocDisable_, config_->mmapDisable_);
100 HILOG_INFO(LOG_CORE, "%s: freeStackData = %d munmapStackData = %d", __func__,
101 config_->freeStackData_, config_->munmapStackData_);
102 HILOG_INFO(LOG_CORE, "%s: filter size = %u smb size = %u", __func__, config_->filterSize_, smbSize);
103 HILOG_INFO(LOG_CORE, "%s: maxStackDepth = %u fpunwind = %d isBlocked = %d", __func__, config_->maxStackDepth_,
104 config_->fpunwind_, config_->isBlocked);
105 stackWriter_ = std::make_shared<StackWriter>("hooknativesmb", smbSize, smbFd_, eventFd_, config_->isBlocked);
106
107 COMMON::PrintMallinfoLog("stackWriter init(byte) => ");
108 return true;
109 }
110
SendStack(const void * data,size_t size)111 bool HookSocketClient::SendStack(const void* data, size_t size)
112 {
113 if (stackWriter_ == nullptr || unixSocketClient_ == nullptr) {
114 return true;
115 }
116
117 if (!unixSocketClient_->SendHeartBeat()) {
118 return false;
119 }
120
121 stackWriter_->WriteTimeout(data, size);
122 stackWriter_->Flush();
123
124 return true;
125 }
126
SendStackWithPayload(const void * data,size_t size,const void * payload,size_t payloadSize)127 bool HookSocketClient::SendStackWithPayload(const void* data, size_t size, const void* payload, size_t payloadSize)
128 {
129 if (stackWriter_ == nullptr || unixSocketClient_ == nullptr) {
130 return true;
131 }
132
133 stackWriter_->WriteWithPayloadTimeout(data, size, payload, payloadSize);
134 g_flushCount++;
135 if (g_flushCount % FLUSH_FLAG == 0) {
136 stackWriter_->Flush();
137 }
138 return true;
139 }
140
Flush()141 void HookSocketClient::Flush()
142 {
143 if (stackWriter_ == nullptr || unixSocketClient_ == nullptr) {
144 return;
145 }
146 stackWriter_->Flush();
147 }
148