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 "security_collector_log.h"
20 #include "collector_cfg_marshalling.h"
21 #include "i_collector.h"
22
23 namespace OHOS::Security::SecurityCollector {
24 namespace {
25 const char* SA_CONFIG_PATH = "/system/etc/security_audit.cfg";
26 }
27
GetInstance()28 DataCollection &DataCollection::GetInstance()
29 {
30 static DataCollection instance;
31 return instance;
32 }
33
StartCollectors(const std::vector<int64_t>& eventIds, std::shared_ptr<ICollectorFwk> api)34 bool DataCollection::StartCollectors(const std::vector<int64_t>& eventIds, std::shared_ptr<ICollectorFwk> api)
35 {
36 LOGI("StartCollectors start");
37 if (eventIds.empty() || !api) {
38 LOGE("Invalid input parameter");
39 return false;
40 }
41 std::vector<int64_t> loadedEventIds_;
42 for (int64_t eventId : eventIds) {
43 LOGI("StartCollectors eventId is 0x%{public}" PRIx64, eventId);
44 if (IsCollectorStarted(eventId)) {
45 LOGI("Collector already started, eventId is 0x%{public}" PRIx64, eventId);
46 continue;
47 }
48 std::string collectorPath;
49 ErrorCode ret = GetCollectorPath(eventId, collectorPath);
50 if (ret != SUCCESS) {
51 LOGE("GetCollectorPath failed, eventId is 0x%{public}" PRIx64, eventId);
52 StopCollectors(loadedEventIds_);
53 return false;
54 }
55 ret = LoadCollector(eventId, collectorPath, api);
56 if (ret != SUCCESS) {
57 LOGE("Load collector failed, eventId is 0x%{public}" PRIx64, eventId);
58 StopCollectors(loadedEventIds_);
59 return false;
60 }
61 loadedEventIds_.push_back(eventId);
62 }
63 LOGI("StartCollectors finish");
64 return true;
65 }
66
SecurityGuardSubscribeCollector(const std::vector<int64_t>& eventIds)67 bool DataCollection::SecurityGuardSubscribeCollector(const std::vector<int64_t>& eventIds)
68 {
69 LOGI("Start to subscribe collectors start");
70 for (int64_t eventId : eventIds) {
71 LOGI("StartCollectors eventId is 0x%{public}" PRIx64, eventId);
72 if (IsCollectorStarted(eventId)) {
73 LOGI("Collector already started, eventId is 0x%{public}" PRIx64, eventId);
74 continue;
75 }
76 std::string collectorPath;
77 ErrorCode ret = GetCollectorPath(eventId, collectorPath);
78 if (ret != SUCCESS) {
79 LOGE("GetCollectorPath failed, eventId is 0x%{public}" PRIx64, eventId);
80 continue;
81 }
82 ret = LoadCollector(eventId, collectorPath, nullptr);
83 if (ret != SUCCESS) {
84 LOGE("GetCollectorPath failed, eventId is 0x%{public}" PRIx64, eventId);
85 continue;
86 }
87 }
88 LOGI("StartCollectors finish");
89 return true;
90 }
91
IsCollectorStarted(int64_t eventId)92 bool DataCollection::IsCollectorStarted(int64_t eventId)
93 {
94 std::lock_guard<std::mutex> lock(mutex_);
95 auto it = eventIdToLoaderMap_.find(eventId);
96 return it != eventIdToLoaderMap_.end();
97 }
98
StopCollectors(const std::vector<int64_t>& eventIds)99 bool DataCollection::StopCollectors(const std::vector<int64_t>& eventIds)
100 {
101 LOGI("StopCollectors start");
102 if (eventIds.empty()) {
103 LOGW("The eventId list is empty");
104 return true;
105 }
106 bool ret = true;
107 std::lock_guard<std::mutex> lock(mutex_);
108 for (int64_t eventId : eventIds) {
109 LOGI("StopCollectors eventId is 0x%{public}" PRIx64, eventId);
110 auto loader = eventIdToLoaderMap_.find(eventId);
111 if (loader == eventIdToLoaderMap_.end()) {
112 LOGI("Collector not found, eventId is 0x%{public}" PRIx64, eventId);
113 continue;
114 }
115 ICollector* collector = loader->second.CallGetCollector();
116 if (collector == nullptr) {
117 LOGE("CallGetCollector error");
118 ret = false;
119 } else {
120 int result = collector->Stop();
121 int isStartWithSub = collector->IsStartWithSub();
122 if (isStartWithSub == 1) {
123 result = collector->Unsubscribe(eventId);
124 }
125 if (result != 0) {
126 LOGE("Failed to stop collector, eventId is 0x%{public}" PRIx64, eventId);
127 ret = false;
128 }
129 LOGI("Stop collector");
130 eventIdToLoaderMap_.erase(loader);
131 }
132 }
133 LOGI("StopCollectors finish");
134 return ret;
135 }
136
CloseLib()137 void DataCollection::CloseLib()
138 {
139 std::lock_guard<std::mutex> lock(closeLibmutex_);
140 for (auto &it : needCloseLibMap_) {
141 it.second.UnLoadLib();
142 }
143 needCloseLibMap_.clear();
144 }
LoadCollector(int64_t eventId, std::string path, std::shared_ptr<ICollectorFwk> api)145 ErrorCode DataCollection::LoadCollector(int64_t eventId, std::string path, std::shared_ptr<ICollectorFwk> api)
146 {
147 LOGI("Start LoadCollector");
148 LibLoader loader(path);
149 ErrorCode ret = loader.LoadLib();
150 if (ret != SUCCESS) {
151 LOGE("LoadLib error, ret=%{public}d, path : %{public}s", ret, path.c_str());
152 return FAILED;
153 }
154 {
155 std::lock_guard<std::mutex> lock(closeLibmutex_);
156 needCloseLibMap_.emplace(eventId, loader);
157 }
158 ICollector* collector = loader.CallGetCollector();
159 if (collector == nullptr) {
160 LOGE("CallGetCollector error");
161 return FAILED;
162 }
163 int result = collector->Start(api);
164 int isStartWithSub = collector->IsStartWithSub();
165 if (isStartWithSub == 1) {
166 result = collector->Subscribe(eventId);
167 }
168 if (result != 0) {
169 LOGE("Failed to start collector");
170 return FAILED;
171 }
172 std::lock_guard<std::mutex> lock(mutex_);
173 eventIdToLoaderMap_.emplace(eventId, loader);
174 LOGI("End LoadCollector");
175 return SUCCESS;
176 }
177
GetCollectorPath(int64_t eventId, std::string& path)178 ErrorCode DataCollection::GetCollectorPath(int64_t eventId, std::string& path)
179 {
180 LOGI("Start GetCollectorPath");
181 std::ifstream stream(SA_CONFIG_PATH, std::ios::in);
182 if (!stream.is_open()) {
183 LOGE("Stream error, %{public}s", strerror(errno));
184 return STREAM_ERROR;
185 }
186 ErrorCode ret = CheckFileStream(stream);
187 if (ret != SUCCESS) {
188 LOGE("check file stream error, ret=%{public}d", ret);
189 stream.close();
190 return ret;
191 }
192 nlohmann::json json = nlohmann::json::parse(stream, nullptr, false);
193 stream.close();
194
195 if (json.is_discarded()) {
196 LOGE("json is discarded");
197 return JSON_ERR;
198 }
199
200 std::vector<ModuleCfgSt> moduleCfgs;
201 if (!SecurityGuard::JsonCfg::Unmarshal<ModuleCfgSt>(moduleCfgs, json, MODULES)) {
202 LOGE("Unmarshal moduleCfgs error");
203 return JSON_ERR;
204 }
205
206 auto it = std::find_if(moduleCfgs.begin(), moduleCfgs.end(),
207 [eventId] (const ModuleCfgSt &module) {
208 auto ifIt = std::find(module.eventId.begin(), module.eventId.end(), eventId);
209 if (ifIt != module.eventId.end()) {
210 LOGI("success to find the event id: 0x%{public}" PRIx64, eventId);
211 return true;
212 } else {
213 return false;
214 }
215 });
216 if (it != moduleCfgs.end()) {
217 path = it->modulePath + it->moduleName;
218 return SUCCESS;
219 }
220
221 LOGE("The eventId does not exist");
222 return FAILED;
223 }
224
GetCollectorType(int64_t eventId, int32_t& collectorType)225 ErrorCode DataCollection::GetCollectorType(int64_t eventId, int32_t& collectorType)
226 {
227 LOGI("Start GetCollectorType");
228 std::ifstream stream(SA_CONFIG_PATH, std::ios::in);
229 if (!stream.is_open()) {
230 LOGE("Stream error, %{public}s", strerror(errno));
231 return STREAM_ERROR;
232 }
233
234 ErrorCode ret = CheckFileStream(stream);
235 if (ret != SUCCESS) {
236 LOGE("check file stream error, ret=%{public}d", ret);
237 stream.close();
238 return ret;
239 }
240
241 nlohmann::json json = nlohmann::json::parse(stream, nullptr, false);
242 stream.close();
243
244 if (json.is_discarded()) {
245 LOGE("json is discarded");
246 return JSON_ERR;
247 }
248
249 std::vector<ModuleCfgSt> moduleCfgs;
250 if (!SecurityGuard::JsonCfg::Unmarshal<ModuleCfgSt>(moduleCfgs, json, MODULES)) {
251 LOGE("Unmarshal moduleCfgs error");
252 return JSON_ERR;
253 }
254
255 auto it = std::find_if(moduleCfgs.begin(), moduleCfgs.end(),
256 [eventId] (const ModuleCfgSt &module) {
257 auto ifIt = std::find(module.eventId.begin(), module.eventId.end(), eventId);
258 if (ifIt != module.eventId.end()) {
259 return true;
260 } else {
261 return false;
262 }
263 });
264 if (it != moduleCfgs.end()) {
265 collectorType = it->collectorType;
266 LOGI("get event 0x%{public}" PRIx64 "collector type is %{public}d.", eventId, collectorType);
267 return SUCCESS;
268 }
269
270 LOGE("The eventId does not exist");
271 return FAILED;
272 }
273
CheckFileStream(std::ifstream &stream)274 ErrorCode DataCollection::CheckFileStream(std::ifstream &stream)
275 {
276 if (!stream.is_open()) {
277 LOGE("stream open error, %{public}s", strerror(errno));
278 return STREAM_ERROR;
279 }
280
281 stream.seekg(0, std::ios::end);
282 std::ios::pos_type len = stream.tellg();
283 if (len == 0) {
284 LOGE("stream is empty");
285 return STREAM_ERROR;
286 }
287 stream.seekg(0, std::ios::beg);
288 return SUCCESS;
289 }
290
LoadCollector(std::string path, const SecurityEventRuler &ruler, std::vector<SecurityEvent> &events)291 ErrorCode DataCollection::LoadCollector(std::string path, const SecurityEventRuler &ruler,
292 std::vector<SecurityEvent> &events)
293 {
294 LOGI("Start LoadCollector");
295 LibLoader loader(path);
296 ErrorCode ret = loader.LoadLib();
297 if (ret != SUCCESS) {
298 LOGE("LoadLib error, ret=%{public}d", ret);
299 return FAILED;
300 }
301 {
302 std::lock_guard<std::mutex> lock(closeLibmutex_);
303 needCloseLibMap_.emplace(ruler.GetEventId(), loader);
304 }
305 ICollector* collector = loader.CallGetCollector();
306 if (collector == nullptr) {
307 LOGE("CallGetCollector error");
308 return FAILED;
309 }
310 int result = collector->Query(ruler, events);
311 if (result != 0) {
312 LOGE("Failed to start collector");
313 return FAILED;
314 }
315 LOGI("End LoadCollector");
316 return SUCCESS;
317 }
318
QuerySecurityEvent(const std::vector<SecurityEventRuler> rulers, std::vector<SecurityEvent> &events)319 int32_t DataCollection::QuerySecurityEvent(const std::vector<SecurityEventRuler> rulers,
320 std::vector<SecurityEvent> &events)
321 {
322 LOGI("QuerySecurityEvent start");
323 if (rulers.empty()) {
324 LOGE("Invalid input parameter");
325 return false;
326 }
327 for (const auto &ruler : rulers) {
328 LOGI("QuerySecurityEvent eventId is 0x%{public}" PRIx64, ruler.GetEventId());
329 std::string collectorPath;
330 ErrorCode ret = GetCollectorPath(ruler.GetEventId(), collectorPath);
331 if (ret != SUCCESS) {
332 LOGE("GetCollectorPath failed, eventId is 0x%{public}" PRIx64, ruler.GetEventId());
333 return false;
334 }
335 ret = LoadCollector(collectorPath, ruler, events);
336 if (ret != SUCCESS) {
337 LOGE("Load collector failed, eventId is 0x%{public}" PRIx64, ruler.GetEventId());
338 return false;
339 }
340 }
341 LOGI("StartCollectors finish");
342 return true;
343 }
344 }