diff --git a/BUILD.gn b/BUILD.gn index 0d2ed07..8a35f6d 100755 --- a/BUILD.gn +++ b/BUILD.gn @@ -82,8 +82,24 @@ group("security_collector_service_build_module") { } } +group("collector_dns_event_module") { + if (is_standard_system) { + deps = [ + "${sg_root_dir}/services/collectors/dns_event:dns_event", + ] + } +} + group("security_collector_seccomp_filter_module") { if (is_standard_system && build_seccomp) { deps = [ "${sg_root_dir}/seccomp_policy:security_collector_seccomp_filter" ] } -} \ No newline at end of file +} + +group("kernel_collector_build_module") { + if (is_standard_system) { + deps = [ + "${sg_root_dir}/services/kernel_collector:kernel_collector_sg", + ] + } +} diff --git a/bundle.json b/bundle.json index dcf2df5..ae66d75 100755 --- a/bundle.json +++ b/bundle.json @@ -37,6 +37,7 @@ "init", "ipc", "napi", + "netmanager_base", "os_account", "preferences", "relational_store", @@ -60,12 +61,14 @@ "//base/security/security_guard/oem_property:security_guard_event_cfg", "//base/security/security_guard:sg_classify_service_build_module", "//base/security/security_guard:sg_collect_service_build_module", + "//base/security/security_guard:collector_dns_event_module", "//base/security/security_guard:security_guard_napi", "//base/security/security_guard:security_guard_capi", "//base/security/security_guard/sa_profile:security_collector_sa_profile_standard", "//base/security/security_guard/sa_profile:security_collector.init", "//base/security/security_guard:security_collector_service_build_module", - "//base/security/security_guard:security_collector_seccomp_filter_module" + "//base/security/security_guard:security_collector_seccomp_filter_module", + "//base/security/security_guard:kernel_collector_build_module" ], "inner_kits": [ { diff --git a/frameworks/common/constants/include/security_guard_define.h b/frameworks/common/constants/include/security_guard_define.h index 67e9e6a..780e426 100755 --- a/frameworks/common/constants/include/security_guard_define.h +++ b/frameworks/common/constants/include/security_guard_define.h @@ -76,6 +76,12 @@ using SgUnsubscribeEvent = struct { std::string extend; }; +using ConfigUpdateEvent = struct { + std::string path; + std::string time; + int32_t ret; +}; + using RequestCondition = struct { std::vector riskEvent; std::vector auditEvent; diff --git a/frameworks/common/utils/include/security_guard_utils.h b/frameworks/common/utils/include/security_guard_utils.h index 1e65fdd..1706a3e 100755 --- a/frameworks/common/utils/include/security_guard_utils.h +++ b/frameworks/common/utils/include/security_guard_utils.h @@ -26,7 +26,7 @@ public: static bool StrToLL(const std::string &str, long long &value); static bool StrToULL(const std::string &str, unsigned long long &value); static std::string GetDate(); - static void CopyFile(const std::string &srcPath, const std::string &dstPath); + static bool CopyFile(const std::string &srcPath, const std::string &dstPath); private: SecurityGuardUtils() = default; diff --git a/frameworks/common/utils/src/security_guard_utils.cpp b/frameworks/common/utils/src/security_guard_utils.cpp index 22393ed..ed403ec 100755 --- a/frameworks/common/utils/src/security_guard_utils.cpp +++ b/frameworks/common/utils/src/security_guard_utils.cpp @@ -96,18 +96,18 @@ std::string SecurityGuardUtils::GetDate() return data; } -void SecurityGuardUtils::CopyFile(const std::string &srcPath, const std::string &dstPath) +bool SecurityGuardUtils::CopyFile(const std::string &srcPath, const std::string &dstPath) { std::ifstream src(srcPath, std::ios::binary); if (!src.is_open() || !src) { SGLOGE("copy file stream error"); src.close(); - return; + return false; } if (src.seekg(0, std::ios_base::end).tellg() > FILE_MAX_SIZE) { SGLOGE("cfg file is too large"); src.close(); - return; + return false; } src.seekg(0, std::ios::beg); std::ofstream dst(dstPath, std::ios::binary); @@ -115,11 +115,12 @@ void SecurityGuardUtils::CopyFile(const std::string &srcPath, const std::string SGLOGE("copy file stream error"); src.close(); dst.close(); - return; + return false; } dst << src.rdbuf(); src.close(); dst.close(); + return true; } } \ No newline at end of file diff --git a/frameworks/js/napi/security_guard_sdk_adaptor.cpp b/frameworks/js/napi/security_guard_sdk_adaptor.cpp index 09934e5..4c3e63f 100755 --- a/frameworks/js/napi/security_guard_sdk_adaptor.cpp +++ b/frameworks/js/napi/security_guard_sdk_adaptor.cpp @@ -13,6 +13,8 @@ * limitations under the License. */ +#include + #include "security_guard_sdk_adaptor.h" #include "iservice_registry.h" @@ -30,7 +32,7 @@ #include "collector_service_loader.h" namespace OHOS::Security::SecurityGuard { -namespace { constexpr int64_t NOTIFY_COLLECTOR_EVENT_ID = 111111; } +namespace { const std::set GRANTED_EVENT{1037000001, 1064001001}; } int32_t SecurityGuardSdkAdaptor::RequestSecurityEventInfo(std::string &devId, std::string &eventList, RequestRiskDataCallback callback) @@ -137,7 +139,8 @@ int32_t SecurityGuardSdkAdaptor::SetModelState(uint32_t modelId, bool enable) int32_t SecurityGuardSdkAdaptor::NotifyCollector(const SecurityCollector::Event &event, int64_t duration) { SGLOGI("On NotifyCollector..."); - if (event.eventId != NOTIFY_COLLECTOR_EVENT_ID) { + if (GRANTED_EVENT.find(event.eventId) == GRANTED_EVENT.end()) { + SGLOGE("NotifyCollector error event id %{public}ld, can not Notify", event.eventId); return BAD_PARAM; } auto object = SecurityCollector::CollectorServiceLoader::GetInstance().LoadCollectorService(); diff --git a/hisysevent.yaml b/hisysevent.yaml index 52757b8..065d30a 100755 --- a/hisysevent.yaml +++ b/hisysevent.yaml @@ -49,4 +49,10 @@ SC_EVENT_SUBSCRIBE: SC_EVENT_UNSUBSCRIBE: __BASE: {type: STATISTIC, level: CRITICAL, desc: security collect event unsubscribe data} CALLER_PID: {type: INT32, desc: caller pid} - UNSUB_RET: {type: INT32, desc: unsubsecribe result} \ No newline at end of file + UNSUB_RET: {type: INT32, desc: unsubsecribe result} + +SG_UPDATE_CONFIG: + __BASE: {type: STATISTIC, level: CRITICAL, desc: security config update event} + CONFIG_PATH: {type: STRING, desc: config path} + CALL_TIME: {type: STRING, desc: call time} + RET: {type: INT32, desc: update result} \ No newline at end of file diff --git a/interfaces/inner_api/collector/src/security_collector_manager_callback_service.cpp b/interfaces/inner_api/collector/src/security_collector_manager_callback_service.cpp index 39e46f2..f8aa405 100755 --- a/interfaces/inner_api/collector/src/security_collector_manager_callback_service.cpp +++ b/interfaces/inner_api/collector/src/security_collector_manager_callback_service.cpp @@ -22,7 +22,7 @@ namespace OHOS::Security::SecurityCollector { int32_t SecurityCollectorManagerCallbackService::OnNotify(const Event &event) { - LOGI(" xxxx callback eventId=%{public}ld", event.eventId); + LOGD("eventId = %{public}ld callback", event.eventId); if (subscriber_ != nullptr) { subscriber_->OnNotify(event); } diff --git a/oem_property/hos/security_audit.cfg b/oem_property/hos/security_audit.cfg index 0f6ebe4..7b1ed5c 100755 --- a/oem_property/hos/security_audit.cfg +++ b/oem_property/hos/security_audit.cfg @@ -62,6 +62,20 @@ "moduleName":"libaudit_mouse_event_collector.z.so", "modulePath":"/system/lib64/", "version":0 + }, + { + "moduleId":"9", + "eventId":1037000001, + "moduleName":"libdns_event.z.so", + "modulePath":"/system/lib64/", + "version":0 + }, + { + "moduleId":"10", + "eventId":1064001001, + "moduleName":"libkernel_collector_sg.z.so", + "modulePath":"/system/lib64/", + "version":0 } ] } \ No newline at end of file diff --git a/oem_property/hos/security_guard_event.cfg b/oem_property/hos/security_guard_event.cfg index acd8796..521b750 100755 --- a/oem_property/hos/security_guard_event.cfg +++ b/oem_property/hos/security_guard_event.cfg @@ -455,6 +455,30 @@ "storageTime" : -1, "owner":[""], "source" : 1 + }, + { + "eventId":"1037000001", + "eventName":"dns", + "version":0, + "eventType":0, + "dataSensitivityLevel":1, + "storageRamNums":1, + "storageRomNums":5, + "storageTime" : -1, + "owner":[""], + "source" : 0 + }, + { + "eventId" : "1064001001", + "eventName" : "collect kernel message", + "version" : 0, + "eventType" : 0, + "dataSensitivityLevel":1, + "storageRamNums" : 1, + "storageRomNums" : 5, + "storageTime" : -1, + "owner":[""], + "source" : 0 } ] } diff --git a/oem_property/hos/security_guard_model.cfg b/oem_property/hos/security_guard_model.cfg index 992df9c..6d4bb0a 100755 --- a/oem_property/hos/security_guard_model.cfg +++ b/oem_property/hos/security_guard_model.cfg @@ -292,7 +292,7 @@ "format": "so", "start-mode": 2, "preload": [""], - "eventList": [""], + "eventList": ["1037000001"], "permissions": "ohos.permission.securityguard.REQUEST_SECURITY_MODEL_RESULT", "db_table": "risk_event", "running_cntl": 0, diff --git a/services/bigdata/include/bigdata.h b/services/bigdata/include/bigdata.h index 866fb67..36ea2a3 100755 --- a/services/bigdata/include/bigdata.h +++ b/services/bigdata/include/bigdata.h @@ -26,6 +26,7 @@ public: static void ReportClassifyEvent(const ClassifyEvent &event); static void ReportSgSubscribeEvent(const SgSubscribeEvent &event); static void ReportSgUnsubscribeEvent(const SgUnsubscribeEvent &event); + static void ReportConfigUpdateEvent(const ConfigUpdateEvent &event); }; } // namespace OHOS::Security::SecurityGuard diff --git a/services/bigdata/src/bigdata.cpp b/services/bigdata/src/bigdata.cpp index b360052..0094c9f 100755 --- a/services/bigdata/src/bigdata.cpp +++ b/services/bigdata/src/bigdata.cpp @@ -27,6 +27,8 @@ namespace { const std::string EVENT_ID = "EVENT_ID"; const std::string SUB_RET = "SUB_RET"; const std::string UNSUB_RET = "UNSUB_RET"; + const std::string CONFIG_PATH = "CONFIG_PATH"; + const std::string RET = "RET"; } void BigData::ReportObatinDataEvent(const ObatinDataEvent &event) @@ -56,4 +58,11 @@ void BigData::ReportSgUnsubscribeEvent(const SgUnsubscribeEvent &event) OHOS::HiviewDFX::HiSysEvent::EventType::STATISTIC, CALLER_PID, event.pid, CALL_TIME, event.time, UNSUB_RET, event.ret); } + +void BigData::ReportConfigUpdateEvent(const ConfigUpdateEvent &event) +{ + HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::SECURITY_GUARD, "SG_UPDATE_CONFIG", + OHOS::HiviewDFX::HiSysEvent::EventType::STATISTIC, CONFIG_PATH, event.path, + CALL_TIME, event.time, RET, event.ret); +} } \ No newline at end of file diff --git a/services/collectors/dns_event/BUILD.gn b/services/collectors/dns_event/BUILD.gn new file mode 100755 index 0000000..5c2d7f3 --- /dev/null +++ b/services/collectors/dns_event/BUILD.gn @@ -0,0 +1,57 @@ +# Copyright (c) 2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//base/security/security_guard/security_guard.gni") +import("//build/ohos.gni") + +ohos_shared_library("dns_event") { + subsystem_name = "security" + part_name = "security_guard" + + include_dirs = [ + "//third_party/json/include", + "include", + ] + + sources = [ + "${sg_root_dir}/services/collectors/dns_event/src/dns_subscriber_manager.cpp", + "${sg_root_dir}/services/collectors/dns_event/src/dns_subscriber.cpp", + "${sg_root_dir}/services/collectors/dns_event/src/interface.cpp", + "${sg_root_dir}/services/collectors/dns_event/src/dns_cache.cpp", + ] + + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${sg_root_dir}/cfi_blocklist.txt" + } + stack_protector_ret = true + + cflags_cc = [ "-DHILOG_ENABLE" ] + + deps = [ + "${sg_root_dir}/interfaces/inner_api/collect:libsg_collect_sdk", + "${sg_root_dir}/interfaces/inner_api/collector:libsg_collector_sdk", + ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "netmanager_base:netsys_controller", + "netmanager_base:net_native_manager_if", + ] +} diff --git a/services/collectors/dns_event/include/dns_cache.h b/services/collectors/dns_event/include/dns_cache.h new file mode 100755 index 0000000..5b6b385 --- /dev/null +++ b/services/collectors/dns_event/include/dns_cache.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SECURITY_GUARD_DNS_CACHE_H +#define SECURITY_GUARD_DNS_CACHE_H + +#include +#include +#include + +#include "netsys_net_dns_result_data.h" + +namespace OHOS::Security::SecurityGuard { +struct DnsResult { + std::set host; + std::set ipv4Addr; + std::set ipv6Addr; +}; + +class DnsCache { +public: + explicit DnsCache() {}; + bool Add(const NetsysNative::NetDnsResultReport&); + DnsResult GetDnsResult(uint32_t) const; + void Clear(); + size_t Length() const; +private: + struct UidIp { + std::set uid; + std::set ipv4Addr; + std::set ipv6Addr; + }; + std::map cache_{}; +}; +} // OHOS::Security::SecurityGuard +#endif // SECURITY_GUARD_DNS_CACHE_H \ No newline at end of file diff --git a/services/collectors/dns_event/include/dns_subscriber.h b/services/collectors/dns_event/include/dns_subscriber.h new file mode 100755 index 0000000..f9d0557 --- /dev/null +++ b/services/collectors/dns_event/include/dns_subscriber.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SECURITY_GUARD_DNS_SUBCCRIBER_H +#define SECURITY_GUARD_DNS_SUBCCRIBER_H + +#include +#include + +#include "netsys_dns_report_callback.h" + +#include "i_collector_fwk.h" +#include "event_define.h" + +#include "dns_cache.h" + +namespace OHOS::Security::SecurityGuard { +namespace { + const std::string DNS_VERSION = "1.0"; + constexpr int64_t DNS_EVENT_ID = 1037000001; +} +class DnsSubscriber : public NetManagerStandard::NetsysDnsReportCallback { +public: + explicit DnsSubscriber(std::shared_ptr, std::map&); + int32_t OnDnsResultReport(uint32_t, const std::list) override; +private: + void ReportAll(); + void Report(const std::string& bundleName, const DnsResult& result); + std::shared_ptr api_{}; + std::map uidBundlename_{}; + DnsCache cache_{}; + SecurityCollector::Event reportEvent_ = { + .eventId = DNS_EVENT_ID, + .version = DNS_VERSION + }; + std::chrono::steady_clock::time_point startTime_{}; +}; +} // OHOS::Security::SecurityGuard +#endif // SECURITY_GUARD_DNS_SUBCCRIBER_H diff --git a/services/collectors/dns_event/include/dns_subscriber_manager.h b/services/collectors/dns_event/include/dns_subscriber_manager.h new file mode 100755 index 0000000..a77dadb --- /dev/null +++ b/services/collectors/dns_event/include/dns_subscriber_manager.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SECURITY_GUARD_DNS_SUBSCRIBER_MANAGER_H +#define SECURITY_GUARD_DNS_SUBSCRIBER_MANAGER_H + +#include +#include + +#include "i_collector.h" +#include "i_collector_fwk.h" +#include "netsys_dns_report_callback.h" +#include "singleton.h" + +namespace OHOS::Security::SecurityGuard { +class DnsSubscriberManager : public SecurityCollector::ICollector, + public Singleton { +public: + ~DnsSubscriberManager() { Stop(); } // 析构时,如果已经注册事件监听,则主动注销 + int Start(std::shared_ptr api) override; + int Stop() override; + +private: + std::map ParseExtra(const std::string& extra); + sptr dnsSubscriber_{nullptr}; + std::mutex subscriberMutex_{}; +}; +} // OHOS::Security::SecurityGuard +#endif // SECURITY_GUARD_DNS_SUBSCRIBER_MANAGER_H \ No newline at end of file diff --git a/services/collectors/dns_event/src/dns_cache.cpp b/services/collectors/dns_event/src/dns_cache.cpp new file mode 100755 index 0000000..5c21bcf --- /dev/null +++ b/services/collectors/dns_event/src/dns_cache.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "hilog/log.h" +#include "netsys_net_dns_result_data.h" + +#include "dns_cache.h" + +namespace OHOS::Security::SecurityGuard { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0xD002F07, "SG_DNS_COLLECTOR" }; +} +bool DnsCache::Add(const NetsysNative::NetDnsResultReport& result) +{ + HiviewDFX::HiLog::Info(LABEL, "Cache adding ..."); + if (result.queryresult_ != 0) { + HiviewDFX::HiLog::Debug(LABEL, "Invalid result"); + return false; + } + if (cache_.find(result.host_) == cache_.end()) { + HiviewDFX::HiLog::Info(LABEL, "New host"); + UidIp uidIp{}; + cache_[result.host_] = uidIp; + } + cache_[result.host_].uid.insert(result.uid_); + for (auto &it : result.addrlist_) { + if (it.type_ == NetsysNative::ADDR_TYPE_IPV4) { + cache_[result.host_].ipv4Addr.insert(it.addr_); + } else if (it.type_ == NetsysNative::ADDR_TYPE_IPV6) { + cache_[result.host_].ipv6Addr.insert(it.addr_); + } + } + HiviewDFX::HiLog::Info(LABEL, "Cache add end"); + return true; +} + +DnsResult DnsCache::GetDnsResult(uint32_t uid) const +{ + HiviewDFX::HiLog::Info(LABEL, "Getting DNS result ..."); + DnsResult dnsResult; + for (auto &[host, uidIp] : cache_) { + if (uidIp.uid.find(uid) == uidIp.uid.end()) { + continue; + } + dnsResult.host.insert(host); + dnsResult.ipv4Addr.insert(uidIp.ipv4Addr.begin(), uidIp.ipv4Addr.end()); + dnsResult.ipv6Addr.insert(uidIp.ipv6Addr.begin(), uidIp.ipv6Addr.end()); + } + HiviewDFX::HiLog::Info(LABEL, "Get DNS result end"); + return dnsResult; +} + +size_t DnsCache::Length() const +{ + return cache_.size(); +} + +void DnsCache::Clear() +{ + cache_.clear(); +} +} // OHOS::Security::SecurityGuard \ No newline at end of file diff --git a/services/collectors/dns_event/src/dns_subscriber.cpp b/services/collectors/dns_event/src/dns_subscriber.cpp new file mode 100755 index 0000000..961505d --- /dev/null +++ b/services/collectors/dns_event/src/dns_subscriber.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "hilog/log.h" + +#include "dns_subscriber.h" + +namespace OHOS::Security::SecurityGuard { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0xD002F07, "SG_DNS_COLLECTOR" }; + constexpr int SUCCESS = 0; + constexpr long long DURATION_SECONDS = 10 * 60; + constexpr uint32_t MAX_HOST = 100; + const std::string BUNDLENAME = "pkg"; + const std::string IPV6_ADDR = "ip6_addr"; + const std::string IPV4_ADDR = "ip4_addr"; + const std::string HOST = "host"; +} +DnsSubscriber::DnsSubscriber(std::shared_ptr api, + std::map& uidBundlename) + : uidBundlename_(uidBundlename), startTime_(std::chrono::steady_clock::now()) +{ + if (!api) { + HiviewDFX::HiLog::Error(LABEL, "Null reporter"); + } + api_ = api; +} + +int32_t DnsSubscriber::OnDnsResultReport(uint32_t size, + const std::list netDnsResultReport) +{ + HiviewDFX::HiLog::Info(LABEL, "On DnsResult listening ..."); + for (auto &it : netDnsResultReport) { + if (uidBundlename_.find(it.uid_) == uidBundlename_.end()) { + HiviewDFX::HiLog::Debug(LABEL, "Invalid uid"); + continue; + } + cache_.Add(it); + } + auto duration = std::chrono::duration_cast + (std::chrono::steady_clock::now() - startTime_).count(); + if (duration >= DURATION_SECONDS || cache_.Length() >= MAX_HOST) { + HiviewDFX::HiLog::Info(LABEL, "Reporting DNS resolution result, %{public}zu items, duration %{public}lld s.", + cache_.Length(), duration); + ReportAll(); + cache_.Clear(); + startTime_ = std::chrono::steady_clock::now(); + } + HiviewDFX::HiLog::Info(LABEL, "DnsResult listen end ..."); + return SUCCESS; +} + +void DnsSubscriber::ReportAll() +{ + HiviewDFX::HiLog::Info(LABEL, "Reporting DnsResult ..."); + for (auto& [uid, bundlename] : uidBundlename_) { + DnsResult re = cache_.GetDnsResult(uid); + if (!re.host.empty()) { + Report(bundlename, re); + } + } + HiviewDFX::HiLog::Info(LABEL, "Report DnsResult end"); +} + +void DnsSubscriber::Report(const std::string& bundleName, const DnsResult& result) +{ + nlohmann::json jsonObj { + {BUNDLENAME, bundleName}, + {HOST, result.host}, + {IPV4_ADDR, result.ipv4Addr}, + {IPV6_ADDR, result.ipv6Addr} + }; + reportEvent_.content = jsonObj.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace); + api_->OnNotify(reportEvent_); +} +} // OHOS::Security::SecurityGuard diff --git a/services/collectors/dns_event/src/dns_subscriber_manager.cpp b/services/collectors/dns_event/src/dns_subscriber_manager.cpp new file mode 100755 index 0000000..f1f0de5 --- /dev/null +++ b/services/collectors/dns_event/src/dns_subscriber_manager.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "nlohmann/json.hpp" + +#include "hilog/log.h" +#include "netsys_controller.h" +#include "dns_subscriber_manager.h" + +#include "dns_subscriber.h" + +namespace OHOS::Security::SecurityGuard { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0xD002F07, "SG_DNS_COLLECTOR" }; + constexpr int FAILED = -1; + constexpr int SUCCESS = 0; +} +int DnsSubscriberManager::Start(std::shared_ptr api) +{ + HiviewDFX::HiLog::Info(LABEL, "Start DNS resolution audit ..."); + if (!api) { + HiviewDFX::HiLog::Error(LABEL, "Reporter null"); + return FAILED; + } + std::lock_guard lock(subscriberMutex_); + if (dnsSubscriber_) { + HiviewDFX::HiLog::Error(LABEL, "Restart DNS resolution audit"); + return FAILED; + } + std::map uidBundlename = ParseExtra(api->GetExtraInfo()); + if (uidBundlename.empty()) { + HiviewDFX::HiLog::Error(LABEL, "Extra error"); + return FAILED; + } + dnsSubscriber_ = new(std::nothrow) DnsSubscriber(api, uidBundlename); + if (!dnsSubscriber_) { + HiviewDFX::HiLog::Error(LABEL, "Get subscriber failed"); + return FAILED; + } + int32_t regDnsResult = + NetManagerStandard::NetsysController::GetInstance().RegisterDnsResultCallback(dnsSubscriber_, 0); + if (regDnsResult != 0) { + HiviewDFX::HiLog::Info(LABEL, "Register dns result callback failed"); + return FAILED; + } + HiviewDFX::HiLog::Error(LABEL, "Start DNS resolution seccuss, register dns result callback"); + return SUCCESS; +} + +int DnsSubscriberManager::Stop() +{ + HiviewDFX::HiLog::Info(LABEL, "Stop DNS resolution audit ..."); + std::lock_guard lock(subscriberMutex_); + if (!dnsSubscriber_) { + HiviewDFX::HiLog::Error(LABEL, "Restop DNS resolution audit"); + return FAILED; + } + int32_t regDnsResult = + NetManagerStandard::NetsysController::GetInstance().UnregisterDnsResultCallback(dnsSubscriber_); + if (regDnsResult != 0) { + dnsSubscriber_ = nullptr; + HiviewDFX::HiLog::Info(LABEL, "Unregister dns result callback failed"); + return FAILED; + } + dnsSubscriber_ = nullptr; + HiviewDFX::HiLog::Error(LABEL, "Stop DNS resolution seccuss, unregister dns result callback"); + return SUCCESS; +} + +std::map DnsSubscriberManager::ParseExtra(const std::string& extra) +{ + HiviewDFX::HiLog::Info(LABEL, "On Parse Extra"); + nlohmann::json extraJson = nlohmann::json::parse(extra, nullptr, false); + if (extraJson.is_discarded()) { + HiviewDFX::HiLog::Error(LABEL, "Parse Extra error"); + return {}; + } + std::map result{}; + for (auto& [key, val] : extraJson.items()) { + if (key.empty()) { + HiviewDFX::HiLog::Error(LABEL, "Parse Extra key empty"); + continue; + } + if (val.empty() || !val.is_number_unsigned()) { + HiviewDFX::HiLog::Error(LABEL, "Parse Extra value error"); + continue; + } + result[val.get()] = key; + } + HiviewDFX::HiLog::Info(LABEL, "Extra parsed"); + return result; +} +} // OHOS::Security::SecurityGuard \ No newline at end of file diff --git a/services/collectors/dns_event/src/interface.cpp b/services/collectors/dns_event/src/interface.cpp new file mode 100755 index 0000000..7760b19 --- /dev/null +++ b/services/collectors/dns_event/src/interface.cpp @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "dns_subscriber_manager.h" +#include "i_collector.h" + +extern "C" OHOS::Security::SecurityCollector::ICollector *GetCollector() +{ + return &OHOS::Security::SecurityGuard::DnsSubscriberManager::GetInstance(); +} \ No newline at end of file diff --git a/services/config_manager/BUILD.gn b/services/config_manager/BUILD.gn index a5ae74c..d19471d 100755 --- a/services/config_manager/BUILD.gn +++ b/services/config_manager/BUILD.gn @@ -25,6 +25,7 @@ ohos_shared_library("sg_config_manager") { "${sg_root_dir}/frameworks/common/json/include", "${sg_root_dir}/frameworks/common/log/include", "${sg_root_dir}/frameworks/common/utils/include", + "${sg_root_dir}/services/bigdata/include", ] sources = [ @@ -51,6 +52,8 @@ ohos_shared_library("sg_config_manager") { } stack_protector_ret = true + deps = [ "${sg_root_dir}/services/bigdata:sg_bigdata_stamp", ] + external_deps = [ "c_utils:utils", "common_event_service:cesfwk_innerkits", diff --git a/services/config_manager/src/config_subscriber.cpp b/services/config_manager/src/config_subscriber.cpp index 3ea6ea0..de438d5 100755 --- a/services/config_manager/src/config_subscriber.cpp +++ b/services/config_manager/src/config_subscriber.cpp @@ -21,6 +21,7 @@ #include "directory_ex.h" #include "string_ex.h" +#include "bigdata.h" #include "event_config.h" #include "config_define.h" #include "config_manager.h" @@ -84,17 +85,25 @@ void ConfigSubscriber::OnReceiveEvent(const EventFwk::CommonEventData &eventData const std::string configPath = CONFIG_ROOT_PATH + names[0] + PATH_SEP + names[1]; std::vector files; GetDirFiles(configPath, files); + ConfigUpdateEvent event{}; for (const std::string &file : files) { + bool isSuccess = false; SGLOGD("file path=%{public}s", file.c_str()); if (file == CONFIG_CACHE_FILES[EVENT_CFG_INDEX]) { - (void)ConfigManager::UpdataConfig(); + isSuccess = ConfigManager::UpdataConfig(); } else if (file == CONFIG_CACHE_FILES[MODEL_CFG_INDEX]) { - (void)ConfigManager::UpdataConfig(); + isSuccess = ConfigManager::UpdataConfig(); } else if (file == CONFIG_CACHE_FILES[SIG_RULE_CFG_INDEX]) { - SecurityGuardUtils::CopyFile(file, CONFIG_UPTATE_FILES[SIG_RULE_CFG_INDEX]); + isSuccess = SecurityGuardUtils::CopyFile(file, CONFIG_UPTATE_FILES[SIG_RULE_CFG_INDEX]); } else if (file == CONFIG_CACHE_FILES[URL_RULE_CFG_INDEX]) { - SecurityGuardUtils::CopyFile(file, CONFIG_UPTATE_FILES[URL_RULE_CFG_INDEX]); + isSuccess = SecurityGuardUtils::CopyFile(file, CONFIG_UPTATE_FILES[URL_RULE_CFG_INDEX]); } + event.path = file; + event.time = SecurityGuardUtils::GetDate(); + event.ret = isSuccess ? SUCCESS : FAILED; + SGLOGD("file path=%{public}s, TIME=%{public}s, ret=%{public}d", event.path.c_str(), event.time.c_str(), + event.ret); + BigData::ReportConfigUpdateEvent(event); bool success = RemoveFile(file); if (!success) { SGLOGW("remove file error, %{public}s", strerror(errno)); diff --git a/services/kernel_collector/BUILD.gn b/services/kernel_collector/BUILD.gn new file mode 100755 index 0000000..a10a4d5 --- /dev/null +++ b/services/kernel_collector/BUILD.gn @@ -0,0 +1,56 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//base/security/security_guard/security_guard.gni") +import("//build/ohos.gni") + +ohos_shared_library("kernel_collector_sg") { + subsystem_name = "security" + part_name = "security_guard" + + include_dirs = [ + "//third_party/json/include", + "${sg_root_dir}/frameworks/common/interfaces", + "${sg_root_dir}/interfaces/inner_api/collector/include", + "${sg_root_dir}/services/kernel_collector/include", + "${sg_root_dir}/frameworks/common/log/include", + "${sg_root_dir}/frameworks/common/constants/include", + "${sg_root_dir}/frameworks/common/json/include", + ] + + sources = [ + "${sg_root_dir}/frameworks/common/json/src/json_cfg.cpp", + "${sg_root_dir}/services/kernel_collector/src/interface.cpp", + "${sg_root_dir}/services/kernel_collector/src/kernel_collector.cpp", + ] + + deps = [ + "${sg_root_dir}/interfaces/inner_api/collect:libsg_collect_sdk", + ] + + external_deps = [ + "access_token:libaccesstoken_sdk", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "device_manager:devicemanagersdk", + "hisysevent:libhisysevent", + "hisysevent:libhisyseventmanager", + "hilog:libhilog", + "ipc:ipc_core", + "os_account:os_account_innerkits", + "preferences:native_preferences", + "relational_store:native_rdb", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] +} diff --git a/services/kernel_collector/include/kernel_collector.h b/services/kernel_collector/include/kernel_collector.h new file mode 100755 index 0000000..6769f62 --- /dev/null +++ b/services/kernel_collector/include/kernel_collector.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SECURITY_GUARD_KERNEL_COLLECTOR_H +#define SECURITY_GUARD_KERNEL_COLLECTOR_H + +#include "i_collector.h" +#include "i_collector_fwk.h" +#include "singleton.h" +#include "hilog/log.h" + +namespace OHOS::Security::SecurityGuard { +constexpr OHOS::HiviewDFX::HiLogLabel KLABEL = { + LOG_CORE, + 0xD002F07, + "SG_KCOLLECTOR" +}; + +#define KLOGD(fmt, ...) \ + (void)OHOS::HiviewDFX::HiLog::Debug(KLABEL, "[%{public}s]" fmt, __func__, ##__VA_ARGS__) +#define KLOGE(fmt, ...) \ + (void)OHOS::HiviewDFX::HiLog::Error(KLABEL, "[%{public}s]" fmt, __func__, ##__VA_ARGS__) +#define KLOGF(fmt, ...) \ + (void)OHOS::HiviewDFX::HiLog::Fatal(KLABEL, "[%{public}s]" fmt, __func__, ##__VA_ARGS__) +#define KLOGI(fmt, ...) \ + (void)OHOS::HiviewDFX::HiLog::Info(KLABEL, "[%{public}s]" fmt, __func__, ##__VA_ARGS__) +#define KLOGW(fmt, ...) \ + (void)OHOS::HiviewDFX::HiLog::Warn(KLABEL, "[%{public}s]" fmt, __func__, ##__VA_ARGS__) + +struct KernelCollectorUdkSmcArg { + uint32_t inputNum; + void *inputList; + void *outData; +}; + +struct inputFilePath { + unsigned int pathLen; // includes the null terminator + char *path; +}; + +class KernelCollector : public SecurityCollector::ICollector, public Singleton { +public: + ~KernelCollector() { Stop(); } + int Start(std::shared_ptr api) override; + int Stop() override; + +private: + std::shared_ptr api_{}; +}; +} // OHOS::Security::SecurityGuard +#endif // SECURITY_GUARD_KERNEL_COLLECTOR_H \ No newline at end of file diff --git a/services/kernel_collector/src/interface.cpp b/services/kernel_collector/src/interface.cpp new file mode 100755 index 0000000..bc9467c --- /dev/null +++ b/services/kernel_collector/src/interface.cpp @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "kernel_collector.h" +#include "i_collector.h" + +extern "C" OHOS::Security::SecurityCollector::ICollector *GetCollector() +{ + return &OHOS::Security::SecurityGuard::KernelCollector::GetInstance(); +} \ No newline at end of file diff --git a/services/kernel_collector/src/kernel_collector.cpp b/services/kernel_collector/src/kernel_collector.cpp new file mode 100755 index 0000000..b6e85e9 --- /dev/null +++ b/services/kernel_collector/src/kernel_collector.cpp @@ -0,0 +1,395 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "if_system_ability_manager.h" +#include +#include +#include +#include +#include +#include "event_define.h" +#include "nlohmann/json.hpp" +#include "i_collector_fwk.h" +#include "kernel_collector.h" +#include "security_guard_log.h" +#include "security_guard_define.h" +#include "securec.h" + +namespace OHOS::Security::SecurityGuard { +namespace { + const int UDK_SMC_MSG_PROC_MAP = 1; + const int UDK_SMC_MSG_FILE_HASH = 2; + const int UDK_SMC_MAX_PID_NUM = 5; + const int UDK_SMC_MAX_FILE_NUM = 5; + const int UDK_SMC_SUCCESS = 0; + const int UDK_SMC_MAX_MAP_STORE_LEN = 100; + const int UDK_SMC_OUT_MAX_LEN = 1024 * 1024; + const int64_t UDK_SMC_EVENT_ID = 1064001001; + const std::string UDK_SMC_EVENT_VERSION = "1.0"; +} +void FreekcusArg(int type, struct KernelCollectorUdkSmcArg *kcua) +{ + uint32_t i; + switch (type) { + case UDK_SMC_MSG_PROC_MAP: + if (kcua->inputList != nullptr) { + free(kcua->inputList); + kcua->inputList = nullptr; + } + break; + case UDK_SMC_MSG_FILE_HASH: + if (kcua->inputList == nullptr) { + break; + } + for (i = 0; i < kcua->inputNum; i++) { + struct inputFilePath *fp = static_cast(kcua->inputList); + if (fp[i].path != nullptr) { + free(fp[i].path); + fp[i].path = nullptr; + } + } + free(kcua->inputList); + kcua->inputList = nullptr; + break; + default: + break; + } + if (kcua->outData != nullptr) { + free(kcua->outData); + kcua->outData = nullptr; + } +} + +int ToKernelCollectorUdkSmcHashArg(nlohmann::json input, struct KernelCollectorUdkSmcArg *kcua) +{ + int i = 0; + int fileTotalLen = 0; + struct inputFilePath *files = nullptr; + kcua->inputNum = input["inputMsg"].size(); + if (kcua->inputNum > UDK_SMC_MAX_FILE_NUM) { + KLOGE("smc input file number too big = %{public}d", kcua->inputNum); + return FAILED; + } + fileTotalLen = kcua->inputNum * sizeof(struct inputFilePath); + files = static_cast(malloc(fileTotalLen)); + if (files == nullptr) { + KLOGI("smc malloc fail files number = %{public}d", kcua->inputNum); + return FAILED; + } + (void)memset_s(reinterpret_cast(files), fileTotalLen, 0, fileTotalLen); + kcua->inputList = files; + nlohmann::json arrays = input["inputMsg"]; + for (const auto& element:arrays) { + if (!element.is_string()) { + KLOGE("input is not string"); + return FAILED; + } + std::string file = element.get(); + files[i].pathLen = file.size(); + if (files[i].pathLen == 0) { + KLOGE("input 0 len file path"); + return FAILED; + } + files[i].path = (char *)malloc(files[i].pathLen); + if (files[i].path == nullptr) { + KLOGE("smc kernel collect hash malloc fail i = %{public}d", i); + return FAILED; + } + errno_t rc = memcpy_s(files[i].path, files[i].pathLen, (char *)file.c_str(), files[i].pathLen); + if (rc != EOK) { + return FAILED; + } + KLOGD("smc in path = %{public}s", files[i].path); + i++; + } + + return SUCCESS; +} + +int ToKernelCollectorUdkSmcMapArg(nlohmann::json input, struct KernelCollectorUdkSmcArg *kcua) +{ + int i = 0; + int *pids = nullptr; + kcua->inputNum = input["inputMsg"].size(); + if (kcua->inputNum > UDK_SMC_MAX_PID_NUM || kcua->inputNum == 0) { + KLOGE("smc input pid number error = %{public}d", kcua->inputNum); + return FAILED; + } + pids = static_cast(malloc(kcua->inputNum * sizeof(int))); + if (pids == nullptr) { + KLOGE("smc malloc fail pid number = %{public}d", kcua->inputNum); + return FAILED; + } + kcua->inputList = pids; + nlohmann::json arrays = input["inputMsg"]; + for (auto &item : arrays) { + if (!item.is_number()) { + KLOGE("smc input error pid number"); + return FAILED; + } + pids[i] = item.get(); + if (pids[i] < 0) { + KLOGE("smc input error pid number %{public}d", pids[i]); + return FAILED; + } + KLOGD("kernel collect pid = %{public}d", pids[i]); + i++; + } + return SUCCESS; +} + +int ToKernelCollectorUdkSmcArg(nlohmann::json input, struct KernelCollectorUdkSmcArg *kcua) +{ + int type = input["infoType"]; + int ret = SUCCESS; + switch (type) { + case UDK_SMC_MSG_PROC_MAP: + ret = ToKernelCollectorUdkSmcMapArg(input, kcua); + break; + case UDK_SMC_MSG_FILE_HASH: + ret = ToKernelCollectorUdkSmcHashArg(input, kcua); + break; + default: + KLOGE("smc input error collect type %{public}d", type); + return FAILED; + } + return ret; +} + +int ProcPidOutInfo(nlohmann::json &output, char *outData, int outDataMaxLen) +{ + int outLen = *(reinterpret_cast(outData)); + int readLen = 0; + int pid = 0; + int mapsLen = 0; + int storeMapLen = 0; + if (outLen < 0 || outLen > outDataMaxLen) { + KLOGE("smc pid out len=%{public}d error", outLen); + return FAILED; + } + outData = outData + sizeof(int); + while (readLen < outLen) { + readLen += sizeof(int); + if (readLen > outLen) { + KLOGE("smc read pid readLen =%{public}d error", readLen); + return FAILED; + } + pid = *(reinterpret_cast(outData + readLen - sizeof(int))); + readLen += sizeof(int); + if (readLen > outLen) { + KLOGE("smc read maps len readLen =%{public}d error", readLen); + return FAILED; + } + mapsLen = *(reinterpret_cast(outData + readLen - sizeof(int))); + readLen += mapsLen; + if (readLen > outLen) { + KLOGE("smc read maps readLen =%{public}d error", readLen); + return FAILED; + } + + char *maps = (outData + readLen - mapsLen); + std::string mapsStr(maps, mapsLen); + mapsStr.erase(std::remove(mapsStr.begin(), mapsStr.end(), ' '), mapsStr.end()); + mapsLen = mapsStr.size(); + storeMapLen = std::min(mapsLen, UDK_SMC_MAX_MAP_STORE_LEN); + std::string storeStr = mapsStr.substr(0, storeMapLen); + KLOGD("smc read pid=%{public}d, masLen = %{public}d, storeMapLen = %{public}zu", + pid, mapsLen, storeStr.size()); + output["outputMsg"].push_back({pid, storeStr}); + } + return SUCCESS; +} + +std::string HashToStr(char *hash, int hashLen) +{ + int destLen = hashLen * 2 + 1; + int fixLen = 2; + char dest[destLen]; + (void)memset_s(dest, destLen, 0, destLen); + int i; + int useLen = 0; + for (i = 0; i < hashLen; i++) { + if (sprintf_s(dest + useLen, destLen - useLen, "%02x", hash[i]) < 0) { + return ""; + } + useLen = useLen + fixLen; + } + return std::string(dest); +} + +int ProcHashOutInfo(nlohmann::json &output, char *outData, int outDataMaxLen) +{ + int outLen = *(reinterpret_cast(outData)); + int readLen = 0; + int filePathLen = 0; + int hashLen = 0; + if (outLen < 0 || outLen > outDataMaxLen) { + KLOGE("smc pid out len=%{public}d error", outLen); + return FAILED; + } + outData = outData + sizeof(int); + while (readLen < outLen) { + readLen += sizeof(int); + if (readLen > outLen) { + KLOGE("smc read hash readLen =%{public}d error", readLen); + return FAILED; + } + filePathLen = *(reinterpret_cast(outData + readLen - sizeof(int))); + readLen += filePathLen; + if (readLen > outLen) { + KLOGE("smc read file path len readLen =%{public}d error", readLen); + return FAILED; + } + char *filePath = outData + readLen - filePathLen; + readLen += sizeof(int); + if (readLen > outLen) { + KLOGE("smc read hash len readLen =%{public}d error", readLen); + return FAILED; + } + hashLen = *(reinterpret_cast(outData + readLen - sizeof(int))); + if (readLen > outLen) { + KLOGE("smc read hash readLen =%{public}d error", readLen); + return FAILED; + } + readLen += hashLen; + if (readLen > outLen) { + KLOGE("smc read file path len readLen =%{public}d error", readLen); + return FAILED; + } + char *hash = outData + readLen - hashLen; + std::string hashStr = HashToStr(hash, hashLen); + output["outputMsg"].push_back({std::string(filePath, filePathLen), hashStr.c_str()}); + KLOGD("smc read file=%{public}s, hash = %{public}s", filePath, hashStr.c_str()); + } + return SUCCESS; +} + +int ToJson(nlohmann::json &output, char *data, int dataMaxLen, int type) +{ + int ret = 0; + output["infoType"] = type; + switch (type) { + case UDK_SMC_MSG_PROC_MAP: + ret = ProcPidOutInfo(output, data, dataMaxLen); + break; + case UDK_SMC_MSG_FILE_HASH: + ret = ProcHashOutInfo(output, data, dataMaxLen); + break; + default: + KLOGE("smc kernel collect out error type = %{public}d", type); + return FAILED; + } + return ret; +} + +bool InputCheck(nlohmann::json inJson) +{ + if (inJson.is_discarded()) { + KLOGE("smc input json is discarded"); + return false; + } + if (!inJson.contains("infoType") || !inJson.contains("inputMsg")) { + KLOGE("smc input json need conatains infoType and inputMsg"); + return false; + } + if (!inJson.at("infoType").is_number()) { + KLOGE("smc input json infoType need number"); + return false; + } + if (!inJson.at("inputMsg").is_array()) { + KLOGE("smc input json infoType need number"); + return false; + } + return true; +} + +int CollectData(std::shared_ptr api, std::string input) +{ + int ret = SUCCESS; + nlohmann::json inJson = nlohmann::json::parse(input.c_str(), nullptr, false); + if (!InputCheck(inJson)) { + return FAILED; + } + struct KernelCollectorUdkSmcArg kc; + (void)memset_s((char *)&kc, sizeof(struct KernelCollectorUdkSmcArg), 0, sizeof(struct KernelCollectorUdkSmcArg)); + int type = inJson["infoType"].get(); + ret = ToKernelCollectorUdkSmcArg(inJson, &kc); + if (ret != SUCCESS) { + FreekcusArg(type, &kc); + return ret; + } + char *out = (char *)malloc(UDK_SMC_OUT_MAX_LEN); + if (out == nullptr) { + FreekcusArg(type, &kc); + KLOGE("smc malloc out data failed"); + return FAILED; + } + kc.outData = (void *)out; + errno = 0; + int fd = open("/dev/smc", O_RDONLY); + if (fd < 0) { + FreekcusArg(type, &kc); + KLOGE("smc init devices fail errno = %{public}d", errno); + return FAILED; + } + ret = ioctl(fd, type, &kc); + if (ret != SUCCESS) { + FreekcusArg(type, &kc); + KLOGE("smc proc type %{public}d error res = %{public}d", type, ret); + return ret; + } + nlohmann::json output; + ret = ToJson(output, (char *)kc.outData, UDK_SMC_OUT_MAX_LEN, inJson["infoType"].get()); + if (ret != UDK_SMC_SUCCESS) { + FreekcusArg(type, &kc); + KLOGE("smc proc res = %{public}d", ret); + return ret; + } + struct SecurityCollector::Event outEvent = {0}; + outEvent.content = output.dump(); + outEvent.eventId = UDK_SMC_EVENT_ID; + outEvent.version = UDK_SMC_EVENT_VERSION; + api->OnNotify(outEvent); + FreekcusArg(type, &kc); + close(fd); + return ret; +} + +int KernelCollector::Start(std::shared_ptr api) +{ + if (!api) { + return FAILED; + } + KLOGI("smc proc maps start"); + api_ = api; + + std::string input = api->GetExtraInfo(); + KLOGD("smc parse inJson %{public}s", input.c_str()); + std::thread work([api, input] () { + CollectData(api, input); + }); + work.detach(); + KLOGI("smc proc maps end"); + return SUCCESS; +} + +int KernelCollector::Stop() +{ + KLOGI("smc kernel collector stop"); + return 0; +} + +} // namespace OHOS::Security::SecurityGuard \ No newline at end of file diff --git a/services/risk_classify/model_library/app_risk_detection/app_risk_detection_model.cpp b/services/risk_classify/model_library/app_risk_detection/app_risk_detection_model.cpp index 7e7791a..b131b91 100755 --- a/services/risk_classify/model_library/app_risk_detection/app_risk_detection_model.cpp +++ b/services/risk_classify/model_library/app_risk_detection/app_risk_detection_model.cpp @@ -41,9 +41,10 @@ namespace { constexpr const char *RISK_RESULT_STR[] = {"unknown", "risk", "safe"}; constexpr uint32_t UNKNOWN_RESULT = 0; - constexpr uint32_t SAFE_RESULT = 1; - constexpr uint32_t RISK_REAULT = 2; + constexpr uint32_t RISK_REAULT = 1; + constexpr uint32_t SAFE_RESULT = 2; constexpr uint32_t CHECK_SIGNATURE = 1; + constexpr uint32_t CHECK_URL = 2; constexpr int64_t APP_SCAN_RESULT_ID = 1011016001; constexpr uint32_t CFG_FILE_MAX_SIZE = 1 * 1024 * 1024; // byte @@ -54,6 +55,13 @@ struct DetectionCfg { std::unordered_set rules; }; +struct UrlContentSt { + std::string pkgName; + std::unordered_set urls; + std::unordered_set ip4Addr; + std::unordered_set ip6Addr; +}; + struct DetectionResult { std::string ToString() const { @@ -177,7 +185,84 @@ public: ~UrlChecker() override = default; std::string Run() override { - return DetectionResult{}.ToString(); + HiLog::Info(LABEL, "UrlChecker start"); + auto config = LoadCfg("/data/service/el1/public/security_guard/url_rule.cfg", "url"); + if (!config) { + HiLog::Error(LABEL, "LoadCfg error"); + return DetectionResult{}.ToString(); + } + std::unordered_set visitedUrls; + bool ret = QueryVisitedUrls(visitedUrls); + if (!ret) { + HiLog::Error(LABEL, "QueryVisitedUrls error"); + return DetectionResult{}.ToString(); + } + DetectionResult result{}; + result.type = CHECK_URL; + result.packageName = param_; + if (visitedUrls.empty()) { + result.result = UNKNOWN_RESULT; + } else { + auto iter = std::find_first_of(config->rules.begin(), config->rules.end(), + visitedUrls.begin(), visitedUrls.end()); + result.result = ((iter == config->rules.end()) ? SAFE_RESULT : RISK_REAULT); + } + HiLog::Info(LABEL, "check url finish, result = [%{public}s]", result.ToString().c_str()); + if (result.result != UNKNOWN_RESULT) { + ReportResultEvent(result); + } + return result.ToString(); + } +private: + bool QueryVisitedUrls(std::unordered_set& visitedUrls) + { + HiLog::Info(LABEL, "QueryVisitedUrls start"); + int64_t eventId = 1037000001; + std::vector secEvents; + int32_t ret = dbOpt_->QueryEventByEventId(eventId, secEvents); + if (ret != SUCCESS) { + HiLog::Error(LABEL, "query event error, ret=%{public}d", ret); + return false; + } + for (const auto& event : secEvents) { + nlohmann::json jsonObj = nlohmann::json::parse(event.content, nullptr, false); + if (jsonObj.is_discarded()) { + HiLog::Error(LABEL, "json error"); + continue; + } + UrlContentSt content = UnmarshalDb(jsonObj); + if (content.pkgName.empty() || content.urls.empty()) { + HiLog::Error(LABEL, "content is empty"); + continue; + } + if (content.pkgName == param_) { + visitedUrls.insert(content.urls.begin(), content.urls.end()); + } + } + return true; + } + + UrlContentSt UnmarshalDb(const nlohmann::json &jsonObj) const + { + HiLog::Info(LABEL, "UnmarshalDb start"); + UrlContentSt content{}; + if (IS_VALID_JSON(jsonObj, "pkg", string)) { + content.pkgName = jsonObj.at("pkg").get(); + HiLog::Error(LABEL, "UnmarshalDb pkg = [%{public}s]", content.pkgName.c_str()); + } + if (IS_VALID_JSON(jsonObj, "host", array)) { + content.urls = jsonObj.at("host").get>(); + HiLog::Error(LABEL, "UnmarshalDb urls=%{public}lu", content.urls.size()); + } + if (IS_VALID_JSON(jsonObj, "ip4Addr", array)) { + content.ip4Addr = jsonObj.at("ip4Addr").get>(); + HiLog::Error(LABEL, "UnmarshalDb ip4Addr=%{public}lu", content.ip4Addr.size()); + } + if (IS_VALID_JSON(jsonObj, "ip6Addr", array)) { + content.ip6Addr = jsonObj.at("ip6Addr").get>(); + HiLog::Error(LABEL, "UnmarshalDb ip6Addr=%{public}lu", content.ip6Addr.size()); + } + return content; } }; @@ -208,7 +293,7 @@ public: DetectionResult result{}; result.type = CHECK_SIGNATURE; result.packageName = packageName; - result.result = ((config->rules.count(signature) != 0) ? SAFE_RESULT : RISK_REAULT); + result.result = ((config->rules.count(signature) == 0) ? SAFE_RESULT : RISK_REAULT); FileSampling(result.hash, result.size, result.offset, result.sample); HiLog::Info(LABEL, "check signature finish, result = [%{public}s]", result.ToString().c_str()); if (result.result != UNKNOWN_RESULT) { diff --git a/services/security_collector/include/security_collector_subscriber_manager.h b/services/security_collector/include/security_collector_subscriber_manager.h index f1834be..156ced1 100755 --- a/services/security_collector/include/security_collector_subscriber_manager.h +++ b/services/security_collector/include/security_collector_subscriber_manager.h @@ -43,14 +43,15 @@ private: int32_t GetAppSubscribeCount(const std::string &appName); int32_t GetAppSubscribeCount(const std::string &appName, int64_t eventId); void CleanSubscriber(const sptr &remote) { unsubscribeHandler_(remote); } + void NotifySubscriber(const Event &event); class CollectorListenner : public ICollectorFwk { public: - using OnNotifyHandler = std::function; - CollectorListenner(OnNotifyHandler onNotifyHandler) : onNotifyHandler_(onNotifyHandler) {} + CollectorListenner(const std::shared_ptr &subscriber) : subscriber_(subscriber) {} + std::string GetExtraInfo() override; void OnNotify(const Event &event) override; private: - OnNotifyHandler onNotifyHandler_; + std::shared_ptr subscriber_; }; class CleanupTimer { @@ -84,10 +85,10 @@ private: }; UnsubscribeHandler unsubscribeHandler_{}; - std::shared_ptr collectorListenner_{}; std::mutex collectorMutex_{}; std::map>> eventToSubscribers_{}; std::map, std::shared_ptr> timers_{}; + std::map> eventToListenner_; }; } #endif // SECURITY_GUARD_SECURITY_COLLECTOR_SUBSCRIBLER_MANAGER_H \ No newline at end of file diff --git a/services/security_collector/src/security_collector_manager_service.cpp b/services/security_collector/src/security_collector_manager_service.cpp index 346ca54..b2448dc 100755 --- a/services/security_collector/src/security_collector_manager_service.cpp +++ b/services/security_collector/src/security_collector_manager_service.cpp @@ -114,10 +114,9 @@ int32_t SecurityCollectorManagerService::Subscribe(const SecurityCollectorSubscr const sptr &callback) { Event event = subscribeInfo.GetEvent(); - LOGI("in subscribe, subscribinfo: duration:%{public}ld, isNotify:%{public}d, \n" - "eventid:%{public}ld, version:%{public}s, content:%{public}s, extra:%{public}s,", - subscribeInfo.GetDuration(), (int)subscribeInfo.IsNotify(), - event.eventId, event.version.c_str(), event.content.c_str(), event.extra.c_str()); + LOGI("in subscribe, subscribinfo: duration:%{public}ld, isNotify:%{public}d, eventid:%{public}ld, \n" + "version:%{public}s, extra:%{public}s", subscribeInfo.GetDuration(), (int)subscribeInfo.IsNotify(), + event.eventId, event.version.c_str(), event.extra.c_str()); if (!HasPermission()) { LOGE("caller no permission"); @@ -131,9 +130,8 @@ int32_t SecurityCollectorManagerService::Subscribe(const SecurityCollectorSubscr return NULL_OBJECT; } auto eventHandler = [] (const std::string &appName, const sptr &remote, const Event &event) { - LOGE("xxxx OnChange eventid:%{public}ld ", event.eventId); if (appName == NOTIFY_APP_NAME) { - LOGI(" xxxx report to SG "); + LOGI("eventid:%{public}ld callback default", event.eventId); auto reportEvent = [event] () { auto info = std::make_shared(event.eventId, event.version, event.content); (void)SecurityGuard::NativeDataCollectKit::ReportSecurityInfo(info); @@ -143,11 +141,13 @@ int32_t SecurityCollectorManagerService::Subscribe(const SecurityCollectorSubscr } auto proxy = iface_cast(remote); if (proxy != nullptr) { + LOGI("report to proxy"); proxy->OnNotify(event); + } else { + LOGE("report proxy is null"); } }; auto subscriber = std::make_shared(appName, subscribeInfo, callback, eventHandler); - ScSubscribeEvent subEvent; subEvent.pid = IPCSkeleton::GetCallingPid(); subEvent.version = event.version; diff --git a/services/security_collector/src/security_collector_subscriber_manager.cpp b/services/security_collector/src/security_collector_subscriber_manager.cpp index 68fb8dd..112e0a4 100755 --- a/services/security_collector/src/security_collector_subscriber_manager.cpp +++ b/services/security_collector/src/security_collector_subscriber_manager.cpp @@ -24,27 +24,34 @@ namespace { } SecurityCollectorSubscriberManager::SecurityCollectorSubscriberManager() { - auto onNotifyHandler = [this] (const Event &event) { - std::lock_guard lock(collectorMutex_); - LOGE("publish event: eventid:%{public}ld, version:%{public}s, content:%{public}s, extra:%{public}s", - event.eventId, event.version.c_str(), event.content.c_str(), event.extra.c_str()); - const auto it = eventToSubscribers_.find(event.eventId); - if (it == eventToSubscribers_.end()) { - return; - } - for (const auto &subscriber : it->second) { - if (subscriber != nullptr) { - subscriber->OnChange(event); - } - } - }; - collectorListenner_ = std::make_shared(onNotifyHandler); +} + +std::string SecurityCollectorSubscriberManager::CollectorListenner::GetExtraInfo() +{ + if (subscriber_) { + return subscriber_->GetSecurityCollectorSubscribeInfo().GetEvent().extra; + } + return {}; } void SecurityCollectorSubscriberManager::CollectorListenner::OnNotify(const Event &event) { - if (onNotifyHandler_) { - onNotifyHandler_(event); + SecurityCollectorSubscriberManager::GetInstance().NotifySubscriber(event); +} + +void SecurityCollectorSubscriberManager::NotifySubscriber(const Event &event) +{ + std::lock_guard lock(collectorMutex_); + LOGE("publish event: eventid:%{public}ld, version:%{public}s, content:%{public}s, extra:%{public}s", + event.eventId, event.version.c_str(), event.content.c_str(), event.extra.c_str()); + const auto it = eventToSubscribers_.find(event.eventId); + if (it == eventToSubscribers_.end()) { + return; + } + for (const auto &subscriber : it->second) { + if (subscriber != nullptr) { + subscriber->OnChange(event); + } } } @@ -123,15 +130,19 @@ bool SecurityCollectorSubscriberManager::SubscribeCollector( LOGE("Already subscribed eventId:%{public}ld", eventId); return false; } - - LOGI("Scheduling start collecctor, eventId:%{public}ld", eventId); - if (!DataCollection::GetInstance().StartCollectors(std::vector{eventId}, collectorListenner_)) { - LOGE("failed to start collectors"); - return false; + if (eventToListenner_.count(eventId) == 0) { + auto collectorListenner = std::make_shared(subscriber); + LOGI("Scheduling start collector, eventId:%{public}ld", eventId); + if (!DataCollection::GetInstance().StartCollectors(std::vector{eventId}, collectorListenner)) { + LOGE("failed to start collectors"); + return false; + } + eventToListenner_.emplace(eventId, collectorListenner); + } else { + LOGI("Scheduling do not start collecctor, eventId:%{public}ld", eventId); } eventToSubscribers_[eventId].emplace(subscriber); LOGI("eventId:%{public}ld, callbackCount:%{public}ld", eventId, eventToSubscribers_[eventId].size()); - int64_t duration = subscriber->GetSecurityCollectorSubscribeInfo().GetDuration(); if (duration > 0) { auto remote = subscriber->GetRemote(); @@ -165,6 +176,7 @@ bool SecurityCollectorSubscriberManager::UnsubscribeCollector(const sptr