1 /*
2 * Copyright (c) 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
16 #include "data_collection.h"
17 #include <cinttypes>
18 #include "json_cfg.h"
19 #include "file_ex.h"
20 #include "security_collector_log.h"
21 #include "collector_cfg_marshalling.h"
22 #include "i_collector.h"
23 #include "event_define.h"
24
25 namespace OHOS::Security::SecurityCollector {
26 namespace {
27 std::string configPathPre = "/system/etc/";
28 const std::string &SA_CONFIG_PATH = configPathPre + SECURITY_GUARD_COLLECTOR_CFG_SOURCE;
29 constexpr int64_t PROCESS_ID_IN_KERNEL_MONITOR = 0x01C000004;
30 constexpr int64_t FILE_EVENT_CHANGE_ID_IN_KERNEL_MONITOR = 1011015020;
31 }
32
GetInstance()33 DataCollection &DataCollection::GetInstance()
34 {
35 static DataCollection instance;
36 return instance;
37 }
38
StartCollectors(const std::vector<int64_t> & eventIds,std::shared_ptr<ICollectorFwk> api)39 bool DataCollection::StartCollectors(const std::vector<int64_t>& eventIds, std::shared_ptr<ICollectorFwk> api)
40 {
41 LOGI("StartCollectors start");
42 if (eventIds.empty() || !api) {
43 LOGE("Invalid input parameter");
44 return false;
45 }
46 std::vector<int64_t> loadedEventIds_;
47 for (int64_t eventId : eventIds) {
48 LOGI("StartCollectors eventId is 0x%{public}" PRIx64, eventId);
49 if (IsCollectorStarted(eventId)) {
50 LOGI("Collector already started, eventId is 0x%{public}" PRIx64, eventId);
51 continue;
52 }
53 std::string collectorPath;
54 ErrorCode ret = GetCollectorPath(eventId, collectorPath);
55 if (ret != SUCCESS) {
56 LOGE("GetCollectorPath failed, eventId is 0x%{public}" PRIx64, eventId);
57 StopCollectors(loadedEventIds_);
58 return false;
59 }
60 ret = LoadCollector(eventId, collectorPath, api);
61 if (ret != SUCCESS) {
62 LOGE("Load collector failed, eventId is 0x%{public}" PRIx64, eventId);
63 StopCollectors(loadedEventIds_);
64 return false;
65 }
66 loadedEventIds_.push_back(eventId);
67 }
68 LOGI("StartCollectors finish");
69 return true;
70 }
71
SecurityGuardSubscribeCollector(const std::vector<int64_t> & eventIds)72 bool DataCollection::SecurityGuardSubscribeCollector(const std::vector<int64_t>& eventIds)
73 {
74 LOGI("Start to subscribe collectors start");
75 for (int64_t eventId : eventIds) {
76 LOGI("StartCollectors eventId is 0x%{public}" PRIx64, eventId);
77 if (IsCollectorStarted(eventId)) {
78 LOGI("Collector already started, eventId is 0x%{public}" PRIx64, eventId);
79 continue;
80 }
81 std::string collectorPath;
82 ErrorCode ret = GetCollectorPath(eventId, collectorPath);
83 if (ret != SUCCESS) {
84 LOGE("GetCollectorPath failed, eventId is 0x%{public}" PRIx64, eventId);
85 continue;
86 }
87 ret = LoadCollector(eventId, collectorPath, nullptr);
88 if (ret != SUCCESS) {
89 LOGE("LoadCollector failed, eventId is 0x%{public}" PRIx64, eventId);
90 continue;
91 }
92 }
93 LOGI("StartCollectors finish");
94 return true;
95 }
96
IsCollectorStarted(int64_t eventId)97 bool DataCollection::IsCollectorStarted(int64_t eventId)
98 {
99 std::lock_guard<std::mutex> lock(mutex_);
100 auto it = eventIdToLoaderMap_.find(eventId);
101 return it != eventIdToLoaderMap_.end();
102 }
103
StopCollectors(const std::vector<int64_t> & eventIds)104 bool DataCollection::StopCollectors(const std::vector<int64_t>& eventIds)
105 {
106 LOGI("StopCollectors start");
107 if (eventIds.empty()) {
108 LOGW("The eventId list is empty");
109 return true;
110 }
111 bool ret = true;
112 std::lock_guard<std::mutex> lock(mutex_);
113 for (int64_t eventId : eventIds) {
114 LOGI("StopCollectors eventId is 0x%{public}" PRIx64, eventId);
115 auto loader = eventIdToLoaderMap_.find(eventId);
116 if (loader == eventIdToLoaderMap_.end()) {
117 LOGI("Collector not found, eventId is 0x%{public}" PRIx64, eventId);
118 continue;
119 }
120 ICollector* collector = loader->second.CallGetCollector();
121 if (collector == nullptr) {
122 LOGE("CallGetCollector error");
123 ret = false;
124 } else {
125 int result = collector->Stop();
126 if (result != 0) {
127 LOGE("Failed to stop collector, eventId is 0x%{public}" PRIx64, eventId);
128 ret = false;
129 }
130 LOGI("Stop collector");
131 eventIdToLoaderMap_.erase(loader);
132 }
133 }
134 LOGI("StopCollectors finish");
135 return ret;
136 }
137
138 // LCOV_EXCL_START
SubscribeCollectors(const std::vector<int64_t> & eventIds,std::shared_ptr<ICollectorFwk> api)139 bool DataCollection::SubscribeCollectors(const std::vector<int64_t>& eventIds, std::shared_ptr<ICollectorFwk> api)
140 {
141 LOGI("SubscribeCollectors start");
142 if (eventIds.empty() || !api) {
143 LOGE("Invalid input parameter");
144 return false;
145 }
146 std::vector<int64_t> loadedEventIds_;
147 for (int64_t eventId : eventIds) {
148 LOGI("SubscribeCollectors eventId is 0x%{public}" PRIx64, eventId);
149 if (IsCollectorStarted(eventId)) {
150 LOGI("Collector already started, eventId is 0x%{public}" PRIx64, eventId);
151 continue;
152 }
153 std::string collectorPath;
154 ErrorCode ret = GetCollectorPath(eventId, collectorPath);
155 if (ret != SUCCESS) {
156 LOGE("GetCollectorPath failed, eventId is 0x%{public}" PRIx64, eventId);
157 UnsubscribeCollectors(loadedEventIds_);
158 return false;
159 }
160 ret = LoadCollector(eventId, collectorPath, api);
161 if (ret != SUCCESS) {
162 LOGE("Load collector failed, eventId is 0x%{public}" PRIx64, eventId);
163 UnsubscribeCollectors(loadedEventIds_);
164 return false;
165 }
166 loadedEventIds_.push_back(eventId);
167 }
168 LOGI("SubscribeCollectors finish");
169 return true;
170 }
171
UnsubscribeCollectors(const std::vector<int64_t> & eventIds)172 bool DataCollection::UnsubscribeCollectors(const std::vector<int64_t> &eventIds)
173 {
174 LOGI("UnsubscribeCollectors start");
175 if (eventIds.empty()) {
176 LOGW("The eventId list is empty");
177 return true;
178 }
179 bool ret = true;
180 std::lock_guard<std::mutex> lock(mutex_);
181 for (int64_t eventId : eventIds) {
182 LOGI("UnsubscribeCollectors eventId is 0x%{public}" PRIx64, eventId);
183 auto loader = eventIdToLoaderMap_.find(eventId);
184 if (loader == eventIdToLoaderMap_.end()) {
185 LOGI("Collector not found, eventId is 0x%{public}" PRIx64, eventId);
186 continue;
187 }
188 ICollector* collector = loader->second.CallGetCollector();
189 if (collector == nullptr) {
190 LOGE("CallGetCollector error");
191 ret = false;
192 } else {
193 int result = collector->IsStartWithSub() ? collector->Unsubscribe(eventId) : collector->Stop();
194 if (result != 0) {
195 LOGE("Failed to Unsubscribe collector, eventId is 0x%{public}" PRIx64, eventId);
196 ret = false;
197 }
198 LOGI("Unsubscribe collector");
199 eventIdToLoaderMap_.erase(loader);
200 }
201 }
202 LOGI("UnsubscribeCollectors finish");
203 return ret;
204 }
205
CloseLib()206 void DataCollection::CloseLib()
207 {
208 std::lock_guard<std::mutex> lock(closeLibmutex_);
209 for (auto &it : needCloseLibMap_) {
210 it.second.UnLoadLib();
211 }
212 needCloseLibMap_.clear();
213 }
214 // LCOV_EXCL_STOP
215
LoadCollector(int64_t eventId,std::string path,std::shared_ptr<ICollectorFwk> api)216 ErrorCode DataCollection::LoadCollector(
217 int64_t eventId, std::string path, std::shared_ptr<ICollectorFwk> api)
218 {
219 LOGI("Start LoadCollector");
220 LibLoader loader(path);
221 ErrorCode ret = loader.LoadLib();
222 if (ret != SUCCESS) {
223 LOGE("LoadLib error, ret=%{public}d, path : %{public}s", ret, path.c_str());
224 return FAILED;
225 }
226 {
227 std::lock_guard<std::mutex> lock(closeLibmutex_);
228 needCloseLibMap_.emplace(eventId, loader);
229 }
230 ICollector* collector = loader.CallGetCollector();
231 if (collector == nullptr) {
232 LOGE("CallGetCollector error");
233 return FAILED;
234 }
235 int result = collector->IsStartWithSub() ? collector->Subscribe(api, eventId) : collector->Start(api);
236 if (result != 0) {
237 LOGE("Failed to start collector");
238 return FAILED;
239 }
240 std::lock_guard<std::mutex> lock(mutex_);
241 eventIdToLoaderMap_.emplace(eventId, loader);
242 LOGI("End LoadCollector");
243 return SUCCESS;
244 }
245
GetCollectorPath(int64_t eventId,std::string & path)246 ErrorCode DataCollection::GetCollectorPath(int64_t eventId, std::string& path)
247 {
248 LOGI("Start GetCollectorPath");
249 std::ifstream stream(SA_CONFIG_PATH, std::ios::in);
250 if (!stream.is_open()) {
251 LOGE("Stream error, %{public}s", strerror(errno));
252 return STREAM_ERROR;
253 }
254 ErrorCode ret = CheckFileStream(stream);
255 if (ret != SUCCESS) {
256 LOGE("check file stream error, ret=%{public}d", ret);
257 stream.close();
258 return ret;
259 }
260 nlohmann::json json = nlohmann::json::parse(stream, nullptr, false);
261 stream.close();
262
263 if (json.is_discarded()) {
264 LOGE("json is discarded");
265 return JSON_ERR;
266 }
267
268 std::vector<ModuleCfgSt> moduleCfgs;
269 if (!SecurityGuard::JsonCfg::Unmarshal<ModuleCfgSt>(moduleCfgs, json, MODULES)) {
270 LOGE("Unmarshal moduleCfgs error");
271 return JSON_ERR;
272 }
273
274 auto it = std::find_if(moduleCfgs.begin(), moduleCfgs.end(),
275 [eventId] (const ModuleCfgSt &module) {
276 auto ifIt = std::find(module.eventId.begin(), module.eventId.end(), eventId);
277 if (ifIt != module.eventId.end()) {
278 LOGI("success to find the event id: 0x%{public}" PRIx64, eventId);
279 return true;
280 } else {
281 return false;
282 }
283 });
284 if (it != moduleCfgs.end()) {
285 path = it->modulePath + it->moduleName;
286 return SUCCESS;
287 }
288
289 LOGE("The eventId does not exist");
290 return FAILED;
291 }
292
GetCollectorType(int64_t eventId,int32_t & collectorType)293 ErrorCode DataCollection::GetCollectorType(int64_t eventId, int32_t& collectorType)
294 {
295 LOGI("Start GetCollectorType");
296 std::ifstream stream(SA_CONFIG_PATH, std::ios::in);
297 if (!stream.is_open()) {
298 LOGE("Stream error, %{public}s", strerror(errno));
299 return STREAM_ERROR;
300 }
301
302 ErrorCode ret = CheckFileStream(stream);
303 if (ret != SUCCESS) {
304 LOGE("check file stream error, ret=%{public}d", ret);
305 stream.close();
306 return ret;
307 }
308
309 nlohmann::json json = nlohmann::json::parse(stream, nullptr, false);
310 stream.close();
311
312 if (json.is_discarded()) {
313 LOGE("json is discarded");
314 return JSON_ERR;
315 }
316
317 std::vector<ModuleCfgSt> moduleCfgs;
318 if (!SecurityGuard::JsonCfg::Unmarshal<ModuleCfgSt>(moduleCfgs, json, MODULES)) {
319 LOGE("Unmarshal moduleCfgs error");
320 return JSON_ERR;
321 }
322
323 auto it = std::find_if(moduleCfgs.begin(), moduleCfgs.end(),
324 [eventId] (const ModuleCfgSt &module) {
325 auto ifIt = std::find(module.eventId.begin(), module.eventId.end(), eventId);
326 if (ifIt != module.eventId.end()) {
327 return true;
328 } else {
329 return false;
330 }
331 });
332 if (it != moduleCfgs.end()) {
333 collectorType = it->collectorType;
334 LOGI("get event 0x%{public}" PRIx64 "collector type is %{public}d.", eventId, collectorType);
335 return SUCCESS;
336 }
337
338 LOGE("The eventId does not exist");
339 return FAILED;
340 }
341
CheckFileStream(std::ifstream & stream)342 ErrorCode DataCollection::CheckFileStream(std::ifstream &stream)
343 {
344 if (!stream.is_open()) {
345 LOGE("stream open error, %{public}s", strerror(errno));
346 return STREAM_ERROR;
347 }
348
349 stream.seekg(0, std::ios::end);
350 std::ios::pos_type len = stream.tellg();
351 if (len == 0) {
352 LOGE("stream is empty");
353 return STREAM_ERROR;
354 }
355 stream.seekg(0, std::ios::beg);
356 return SUCCESS;
357 }
358
LoadCollector(std::string path,const SecurityEventRuler & ruler,std::vector<SecurityEvent> & events)359 ErrorCode DataCollection::LoadCollector(std::string path, const SecurityEventRuler &ruler,
360 std::vector<SecurityEvent> &events)
361 {
362 LOGI("Start LoadCollector");
363 LibLoader loader(path);
364 ErrorCode ret = loader.LoadLib();
365 if (ret != SUCCESS) {
366 LOGE("LoadLib error, ret=%{public}d", ret);
367 return FAILED;
368 }
369 {
370 std::lock_guard<std::mutex> lock(closeLibmutex_);
371 needCloseLibMap_.emplace(ruler.GetEventId(), loader);
372 }
373 ICollector* collector = loader.CallGetCollector();
374 if (collector == nullptr) {
375 LOGE("CallGetCollector error");
376 return FAILED;
377 }
378 int result = collector->Query(ruler, events);
379 if (result != 0) {
380 LOGE("Failed to start collector");
381 return FAILED;
382 }
383 LOGI("End LoadCollector");
384 return SUCCESS;
385 }
386
QuerySecurityEvent(const std::vector<SecurityEventRuler> rulers,std::vector<SecurityEvent> & events)387 int32_t DataCollection::QuerySecurityEvent(const std::vector<SecurityEventRuler> rulers,
388 std::vector<SecurityEvent> &events)
389 {
390 LOGI("QuerySecurityEvent start");
391 if (rulers.empty()) {
392 LOGE("Invalid input parameter");
393 return FAILED;
394 }
395 for (const auto &ruler : rulers) {
396 LOGI("QuerySecurityEvent eventId is 0x%{public}" PRIx64, ruler.GetEventId());
397 std::string collectorPath;
398 ErrorCode ret = GetCollectorPath(ruler.GetEventId(), collectorPath);
399 if (ret != SUCCESS) {
400 LOGE("GetCollectorPath failed, eventId is 0x%{public}" PRIx64, ruler.GetEventId());
401 return FAILED;
402 }
403 ret = LoadCollector(collectorPath, ruler, events);
404 if (ret != SUCCESS) {
405 LOGE("Load collector failed, eventId is 0x%{public}" PRIx64, ruler.GetEventId());
406 return FAILED;
407 }
408 }
409 LOGI("StartCollectors finish");
410 return SUCCESS;
411 }
412
AddFilter(const SecurityCollectorEventMuteFilter & filter)413 int32_t DataCollection::AddFilter(const SecurityCollectorEventMuteFilter &filter)
414 {
415 SecurityCollectorEventMuteFilter filterTmp = filter;
416 int64_t eventId = filterTmp.eventId;
417 if (FileExists("/dev/hkids")) {
418 if (filterTmp.eventId == PROCESS_EVENTID) {
419 eventId = PROCESS_ID_IN_KERNEL_MONITOR;
420 }
421 if (eventId == FILE_EVENTID) {
422 eventId = FILE_EVENT_CHANGE_ID_IN_KERNEL_MONITOR;
423 filterTmp.eventId = FILE_EVENT_CHANGE_ID_IN_KERNEL_MONITOR;
424 }
425 }
426 if (!IsCollectorStarted(eventId)) {
427 LOGE("collector not start, eventId is 0x%{public}" PRIx64, filterTmp.eventId);
428 return FAILED;
429 }
430 std::lock_guard<std::mutex> lock(mutex_);
431 auto loader = eventIdToLoaderMap_.at(eventId);
432 ICollector* collector = loader.CallGetCollector();
433 if (collector == nullptr) {
434 LOGE("CallGetCollector error");
435 return NULL_OBJECT;
436 }
437 int ret = collector->AddFilter(filterTmp);
438 if (ret != SUCCESS) {
439 LOGE("fail to set mute to collector, eventId is 0x%{public}" PRIx64, filterTmp.eventId);
440 }
441 return ret;
442 }
443
RemoveFilter(const SecurityCollectorEventMuteFilter & filter)444 int32_t DataCollection::RemoveFilter(const SecurityCollectorEventMuteFilter &filter)
445 {
446 SecurityCollectorEventMuteFilter filterTmp = filter;
447 int64_t eventId = filterTmp.eventId;
448 if (FileExists("/dev/hkids")) {
449 if (filterTmp.eventId == PROCESS_EVENTID) {
450 eventId = PROCESS_ID_IN_KERNEL_MONITOR;
451 }
452 if (eventId == FILE_EVENTID) {
453 eventId = FILE_EVENT_CHANGE_ID_IN_KERNEL_MONITOR;
454 filterTmp.eventId = FILE_EVENT_CHANGE_ID_IN_KERNEL_MONITOR;
455 }
456 }
457 if (!IsCollectorStarted(eventId)) {
458 LOGE("collector not start, eventId is 0x%{public}" PRIx64, filterTmp.eventId);
459 return FAILED;
460 }
461 std::lock_guard<std::mutex> lock(mutex_);
462 auto loader = eventIdToLoaderMap_.at(eventId);
463 ICollector* collector = loader.CallGetCollector();
464 if (collector == nullptr) {
465 LOGE("CallGetCollector error");
466 return NULL_OBJECT;
467 }
468 int ret = collector->RemoveFilter(filterTmp);
469 if (ret != SUCCESS) {
470 LOGE("fail to set unmute to collector, eventId is 0x%{public}" PRIx64, filterTmp.eventId);
471 }
472 return ret;
473 }
474 }