• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }