Add DNS collector and URL detection

Match-id-1128c6b2ed2226cb8e6e385364c51a712df06588
This commit is contained in:
zhaoguojian 2023-12-19 17:59:24 +08:00
parent 87dbb4df5a
commit 68af3f805c
31 changed files with 1280 additions and 54 deletions

View File

@ -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") { group("security_collector_seccomp_filter_module") {
if (is_standard_system && build_seccomp) { if (is_standard_system && build_seccomp) {
deps = [ "${sg_root_dir}/seccomp_policy:security_collector_seccomp_filter" ] deps = [ "${sg_root_dir}/seccomp_policy:security_collector_seccomp_filter" ]
} }
} }
group("kernel_collector_build_module") {
if (is_standard_system) {
deps = [
"${sg_root_dir}/services/kernel_collector:kernel_collector_sg",
]
}
}

View File

@ -37,6 +37,7 @@
"init", "init",
"ipc", "ipc",
"napi", "napi",
"netmanager_base",
"os_account", "os_account",
"preferences", "preferences",
"relational_store", "relational_store",
@ -60,12 +61,14 @@
"//base/security/security_guard/oem_property:security_guard_event_cfg", "//base/security/security_guard/oem_property:security_guard_event_cfg",
"//base/security/security_guard:sg_classify_service_build_module", "//base/security/security_guard:sg_classify_service_build_module",
"//base/security/security_guard:sg_collect_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_napi",
"//base/security/security_guard:security_guard_capi", "//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_sa_profile_standard",
"//base/security/security_guard/sa_profile:security_collector.init", "//base/security/security_guard/sa_profile:security_collector.init",
"//base/security/security_guard:security_collector_service_build_module", "//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": [ "inner_kits": [
{ {

View File

@ -76,6 +76,12 @@ using SgUnsubscribeEvent = struct {
std::string extend; std::string extend;
}; };
using ConfigUpdateEvent = struct {
std::string path;
std::string time;
int32_t ret;
};
using RequestCondition = struct { using RequestCondition = struct {
std::vector<int64_t> riskEvent; std::vector<int64_t> riskEvent;
std::vector<int64_t> auditEvent; std::vector<int64_t> auditEvent;

View File

@ -26,7 +26,7 @@ public:
static bool StrToLL(const std::string &str, long long &value); static bool StrToLL(const std::string &str, long long &value);
static bool StrToULL(const std::string &str, unsigned long long &value); static bool StrToULL(const std::string &str, unsigned long long &value);
static std::string GetDate(); 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: private:
SecurityGuardUtils() = default; SecurityGuardUtils() = default;

View File

@ -96,18 +96,18 @@ std::string SecurityGuardUtils::GetDate()
return data; 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); std::ifstream src(srcPath, std::ios::binary);
if (!src.is_open() || !src) { if (!src.is_open() || !src) {
SGLOGE("copy file stream error"); SGLOGE("copy file stream error");
src.close(); src.close();
return; return false;
} }
if (src.seekg(0, std::ios_base::end).tellg() > FILE_MAX_SIZE) { if (src.seekg(0, std::ios_base::end).tellg() > FILE_MAX_SIZE) {
SGLOGE("cfg file is too large"); SGLOGE("cfg file is too large");
src.close(); src.close();
return; return false;
} }
src.seekg(0, std::ios::beg); src.seekg(0, std::ios::beg);
std::ofstream dst(dstPath, std::ios::binary); 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"); SGLOGE("copy file stream error");
src.close(); src.close();
dst.close(); dst.close();
return; return false;
} }
dst << src.rdbuf(); dst << src.rdbuf();
src.close(); src.close();
dst.close(); dst.close();
return true;
} }
} }

View File

@ -13,6 +13,8 @@
* limitations under the License. * limitations under the License.
*/ */
#include <set>
#include "security_guard_sdk_adaptor.h" #include "security_guard_sdk_adaptor.h"
#include "iservice_registry.h" #include "iservice_registry.h"
@ -30,7 +32,7 @@
#include "collector_service_loader.h" #include "collector_service_loader.h"
namespace OHOS::Security::SecurityGuard { namespace OHOS::Security::SecurityGuard {
namespace { constexpr int64_t NOTIFY_COLLECTOR_EVENT_ID = 111111; } namespace { const std::set<int64_t> GRANTED_EVENT{1037000001, 1064001001}; }
int32_t SecurityGuardSdkAdaptor::RequestSecurityEventInfo(std::string &devId, std::string &eventList, int32_t SecurityGuardSdkAdaptor::RequestSecurityEventInfo(std::string &devId, std::string &eventList,
RequestRiskDataCallback callback) 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) int32_t SecurityGuardSdkAdaptor::NotifyCollector(const SecurityCollector::Event &event, int64_t duration)
{ {
SGLOGI("On NotifyCollector..."); 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; return BAD_PARAM;
} }
auto object = SecurityCollector::CollectorServiceLoader::GetInstance().LoadCollectorService(); auto object = SecurityCollector::CollectorServiceLoader::GetInstance().LoadCollectorService();

View File

@ -49,4 +49,10 @@ SC_EVENT_SUBSCRIBE:
SC_EVENT_UNSUBSCRIBE: SC_EVENT_UNSUBSCRIBE:
__BASE: {type: STATISTIC, level: CRITICAL, desc: security collect event unsubscribe data} __BASE: {type: STATISTIC, level: CRITICAL, desc: security collect event unsubscribe data}
CALLER_PID: {type: INT32, desc: caller pid} CALLER_PID: {type: INT32, desc: caller pid}
UNSUB_RET: {type: INT32, desc: unsubsecribe result} 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}

View File

@ -22,7 +22,7 @@ namespace OHOS::Security::SecurityCollector {
int32_t SecurityCollectorManagerCallbackService::OnNotify(const Event &event) 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) { if (subscriber_ != nullptr) {
subscriber_->OnNotify(event); subscriber_->OnNotify(event);
} }

View File

@ -62,6 +62,20 @@
"moduleName":"libaudit_mouse_event_collector.z.so", "moduleName":"libaudit_mouse_event_collector.z.so",
"modulePath":"/system/lib64/", "modulePath":"/system/lib64/",
"version":0 "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
} }
] ]
} }

View File

@ -455,6 +455,30 @@
"storageTime" : -1, "storageTime" : -1,
"owner":[""], "owner":[""],
"source" : 1 "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
} }
] ]
} }

View File

@ -292,7 +292,7 @@
"format": "so", "format": "so",
"start-mode": 2, "start-mode": 2,
"preload": [""], "preload": [""],
"eventList": [""], "eventList": ["1037000001"],
"permissions": "ohos.permission.securityguard.REQUEST_SECURITY_MODEL_RESULT", "permissions": "ohos.permission.securityguard.REQUEST_SECURITY_MODEL_RESULT",
"db_table": "risk_event", "db_table": "risk_event",
"running_cntl": 0, "running_cntl": 0,

View File

@ -26,6 +26,7 @@ public:
static void ReportClassifyEvent(const ClassifyEvent &event); static void ReportClassifyEvent(const ClassifyEvent &event);
static void ReportSgSubscribeEvent(const SgSubscribeEvent &event); static void ReportSgSubscribeEvent(const SgSubscribeEvent &event);
static void ReportSgUnsubscribeEvent(const SgUnsubscribeEvent &event); static void ReportSgUnsubscribeEvent(const SgUnsubscribeEvent &event);
static void ReportConfigUpdateEvent(const ConfigUpdateEvent &event);
}; };
} // namespace OHOS::Security::SecurityGuard } // namespace OHOS::Security::SecurityGuard

View File

@ -27,6 +27,8 @@ namespace {
const std::string EVENT_ID = "EVENT_ID"; const std::string EVENT_ID = "EVENT_ID";
const std::string SUB_RET = "SUB_RET"; const std::string SUB_RET = "SUB_RET";
const std::string UNSUB_RET = "UNSUB_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) 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, OHOS::HiviewDFX::HiSysEvent::EventType::STATISTIC, CALLER_PID, event.pid,
CALL_TIME, event.time, UNSUB_RET, event.ret); 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);
}
} }

View File

@ -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",
]
}

View File

@ -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 <map>
#include <set>
#include <string>
#include "netsys_net_dns_result_data.h"
namespace OHOS::Security::SecurityGuard {
struct DnsResult {
std::set<std::string> host;
std::set<std::string> ipv4Addr;
std::set<std::string> 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<uint32_t> uid;
std::set<std::string> ipv4Addr;
std::set<std::string> ipv6Addr;
};
std::map<std::string, UidIp> cache_{};
};
} // OHOS::Security::SecurityGuard
#endif // SECURITY_GUARD_DNS_CACHE_H

View File

@ -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 <list>
#include <map>
#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<SecurityCollector::ICollectorFwk>, std::map<uint32_t, std::string>&);
int32_t OnDnsResultReport(uint32_t, const std::list<NetsysNative::NetDnsResultReport>) override;
private:
void ReportAll();
void Report(const std::string& bundleName, const DnsResult& result);
std::shared_ptr<SecurityCollector::ICollectorFwk> api_{};
std::map<uint32_t, std::string> 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

View File

@ -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 <mutex>
#include <map>
#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<DnsSubscriberManager> {
public:
~DnsSubscriberManager() { Stop(); } // 析构时,如果已经注册事件监听,则主动注销
int Start(std::shared_ptr<SecurityCollector::ICollectorFwk> api) override;
int Stop() override;
private:
std::map<uint32_t, std::string> ParseExtra(const std::string& extra);
sptr<OHOS::NetManagerStandard::NetsysDnsReportCallback> dnsSubscriber_{nullptr};
std::mutex subscriberMutex_{};
};
} // OHOS::Security::SecurityGuard
#endif // SECURITY_GUARD_DNS_SUBSCRIBER_MANAGER_H

View File

@ -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 <map>
#include <set>
#include <list>
#include <string>
#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

View File

@ -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 <map>
#include <chrono>
#include <thread>
#include <nlohmann/json.hpp>
#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<SecurityCollector::ICollectorFwk> api,
std::map<uint32_t, std::string>& 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<NetsysNative::NetDnsResultReport> 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::seconds>
(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

View File

@ -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 <mutex>
#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<SecurityCollector::ICollectorFwk> api)
{
HiviewDFX::HiLog::Info(LABEL, "Start DNS resolution audit ...");
if (!api) {
HiviewDFX::HiLog::Error(LABEL, "Reporter null");
return FAILED;
}
std::lock_guard<std::mutex> lock(subscriberMutex_);
if (dnsSubscriber_) {
HiviewDFX::HiLog::Error(LABEL, "Restart DNS resolution audit");
return FAILED;
}
std::map<uint32_t, std::string> 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<std::mutex> 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<uint32_t, std::string> 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<uint32_t, std::string> 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<uint32_t>()] = key;
}
HiviewDFX::HiLog::Info(LABEL, "Extra parsed");
return result;
}
} // OHOS::Security::SecurityGuard

View File

@ -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();
}

View File

@ -25,6 +25,7 @@ ohos_shared_library("sg_config_manager") {
"${sg_root_dir}/frameworks/common/json/include", "${sg_root_dir}/frameworks/common/json/include",
"${sg_root_dir}/frameworks/common/log/include", "${sg_root_dir}/frameworks/common/log/include",
"${sg_root_dir}/frameworks/common/utils/include", "${sg_root_dir}/frameworks/common/utils/include",
"${sg_root_dir}/services/bigdata/include",
] ]
sources = [ sources = [
@ -51,6 +52,8 @@ ohos_shared_library("sg_config_manager") {
} }
stack_protector_ret = true stack_protector_ret = true
deps = [ "${sg_root_dir}/services/bigdata:sg_bigdata_stamp", ]
external_deps = [ external_deps = [
"c_utils:utils", "c_utils:utils",
"common_event_service:cesfwk_innerkits", "common_event_service:cesfwk_innerkits",

View File

@ -21,6 +21,7 @@
#include "directory_ex.h" #include "directory_ex.h"
#include "string_ex.h" #include "string_ex.h"
#include "bigdata.h"
#include "event_config.h" #include "event_config.h"
#include "config_define.h" #include "config_define.h"
#include "config_manager.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]; const std::string configPath = CONFIG_ROOT_PATH + names[0] + PATH_SEP + names[1];
std::vector<std::string> files; std::vector<std::string> files;
GetDirFiles(configPath, files); GetDirFiles(configPath, files);
ConfigUpdateEvent event{};
for (const std::string &file : files) { for (const std::string &file : files) {
bool isSuccess = false;
SGLOGD("file path=%{public}s", file.c_str()); SGLOGD("file path=%{public}s", file.c_str());
if (file == CONFIG_CACHE_FILES[EVENT_CFG_INDEX]) { if (file == CONFIG_CACHE_FILES[EVENT_CFG_INDEX]) {
(void)ConfigManager::UpdataConfig<EventConfig>(); isSuccess = ConfigManager::UpdataConfig<EventConfig>();
} else if (file == CONFIG_CACHE_FILES[MODEL_CFG_INDEX]) { } else if (file == CONFIG_CACHE_FILES[MODEL_CFG_INDEX]) {
(void)ConfigManager::UpdataConfig<ModelConfig>(); isSuccess = ConfigManager::UpdataConfig<ModelConfig>();
} else if (file == CONFIG_CACHE_FILES[SIG_RULE_CFG_INDEX]) { } 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]) { } 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); bool success = RemoveFile(file);
if (!success) { if (!success) {
SGLOGW("remove file error, %{public}s", strerror(errno)); SGLOGW("remove file error, %{public}s", strerror(errno));

View File

@ -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",
]
}

View File

@ -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<KernelCollector> {
public:
~KernelCollector() { Stop(); }
int Start(std::shared_ptr<SecurityCollector::ICollectorFwk> api) override;
int Stop() override;
private:
std::shared_ptr<SecurityCollector::ICollectorFwk> api_{};
};
} // OHOS::Security::SecurityGuard
#endif // SECURITY_GUARD_KERNEL_COLLECTOR_H

View File

@ -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();
}

View File

@ -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 <system_ability_definition.h>
#include "if_system_ability_manager.h"
#include <mutex>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <thread>
#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<struct inputFilePath *>(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<struct inputFilePath *>(malloc(fileTotalLen));
if (files == nullptr) {
KLOGI("smc malloc fail files number = %{public}d", kcua->inputNum);
return FAILED;
}
(void)memset_s(reinterpret_cast<char *>(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<std::string>();
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<int *>(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<int32_t>();
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<int *>(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<int *>(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<int *>(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<int *>(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<int *>(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<int *>(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<SecurityCollector::ICollectorFwk> 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<int>();
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<int>());
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<SecurityCollector::ICollectorFwk> 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

View File

@ -41,9 +41,10 @@ namespace {
constexpr const char *RISK_RESULT_STR[] = {"unknown", "risk", "safe"}; constexpr const char *RISK_RESULT_STR[] = {"unknown", "risk", "safe"};
constexpr uint32_t UNKNOWN_RESULT = 0; constexpr uint32_t UNKNOWN_RESULT = 0;
constexpr uint32_t SAFE_RESULT = 1; constexpr uint32_t RISK_REAULT = 1;
constexpr uint32_t RISK_REAULT = 2; constexpr uint32_t SAFE_RESULT = 2;
constexpr uint32_t CHECK_SIGNATURE = 1; constexpr uint32_t CHECK_SIGNATURE = 1;
constexpr uint32_t CHECK_URL = 2;
constexpr int64_t APP_SCAN_RESULT_ID = 1011016001; constexpr int64_t APP_SCAN_RESULT_ID = 1011016001;
constexpr uint32_t CFG_FILE_MAX_SIZE = 1 * 1024 * 1024; // byte constexpr uint32_t CFG_FILE_MAX_SIZE = 1 * 1024 * 1024; // byte
@ -54,6 +55,13 @@ struct DetectionCfg {
std::unordered_set<std::string> rules; std::unordered_set<std::string> rules;
}; };
struct UrlContentSt {
std::string pkgName;
std::unordered_set<std::string> urls;
std::unordered_set<std::string> ip4Addr;
std::unordered_set<std::string> ip6Addr;
};
struct DetectionResult { struct DetectionResult {
std::string ToString() const std::string ToString() const
{ {
@ -177,7 +185,84 @@ public:
~UrlChecker() override = default; ~UrlChecker() override = default;
std::string Run() override 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<std::string> 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<std::string>& visitedUrls)
{
HiLog::Info(LABEL, "QueryVisitedUrls start");
int64_t eventId = 1037000001;
std::vector<SecEvent> 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<std::string>();
HiLog::Error(LABEL, "UnmarshalDb pkg = [%{public}s]", content.pkgName.c_str());
}
if (IS_VALID_JSON(jsonObj, "host", array)) {
content.urls = jsonObj.at("host").get<std::unordered_set<std::string>>();
HiLog::Error(LABEL, "UnmarshalDb urls=%{public}lu", content.urls.size());
}
if (IS_VALID_JSON(jsonObj, "ip4Addr", array)) {
content.ip4Addr = jsonObj.at("ip4Addr").get<std::unordered_set<std::string>>();
HiLog::Error(LABEL, "UnmarshalDb ip4Addr=%{public}lu", content.ip4Addr.size());
}
if (IS_VALID_JSON(jsonObj, "ip6Addr", array)) {
content.ip6Addr = jsonObj.at("ip6Addr").get<std::unordered_set<std::string>>();
HiLog::Error(LABEL, "UnmarshalDb ip6Addr=%{public}lu", content.ip6Addr.size());
}
return content;
} }
}; };
@ -208,7 +293,7 @@ public:
DetectionResult result{}; DetectionResult result{};
result.type = CHECK_SIGNATURE; result.type = CHECK_SIGNATURE;
result.packageName = packageName; 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); FileSampling(result.hash, result.size, result.offset, result.sample);
HiLog::Info(LABEL, "check signature finish, result = [%{public}s]", result.ToString().c_str()); HiLog::Info(LABEL, "check signature finish, result = [%{public}s]", result.ToString().c_str());
if (result.result != UNKNOWN_RESULT) { if (result.result != UNKNOWN_RESULT) {

View File

@ -43,14 +43,15 @@ private:
int32_t GetAppSubscribeCount(const std::string &appName); int32_t GetAppSubscribeCount(const std::string &appName);
int32_t GetAppSubscribeCount(const std::string &appName, int64_t eventId); int32_t GetAppSubscribeCount(const std::string &appName, int64_t eventId);
void CleanSubscriber(const sptr<IRemoteObject> &remote) { unsubscribeHandler_(remote); } void CleanSubscriber(const sptr<IRemoteObject> &remote) { unsubscribeHandler_(remote); }
void NotifySubscriber(const Event &event);
class CollectorListenner : public ICollectorFwk { class CollectorListenner : public ICollectorFwk {
public: public:
using OnNotifyHandler = std::function<void(const Event &event)>; CollectorListenner(const std::shared_ptr<SecurityCollectorSubscriber> &subscriber) : subscriber_(subscriber) {}
CollectorListenner(OnNotifyHandler onNotifyHandler) : onNotifyHandler_(onNotifyHandler) {} std::string GetExtraInfo() override;
void OnNotify(const Event &event) override; void OnNotify(const Event &event) override;
private: private:
OnNotifyHandler onNotifyHandler_; std::shared_ptr<SecurityCollectorSubscriber> subscriber_;
}; };
class CleanupTimer { class CleanupTimer {
@ -84,10 +85,10 @@ private:
}; };
UnsubscribeHandler unsubscribeHandler_{}; UnsubscribeHandler unsubscribeHandler_{};
std::shared_ptr<ICollectorFwk> collectorListenner_{};
std::mutex collectorMutex_{}; std::mutex collectorMutex_{};
std::map<int64_t, std::set<std::shared_ptr<SecurityCollectorSubscriber>>> eventToSubscribers_{}; std::map<int64_t, std::set<std::shared_ptr<SecurityCollectorSubscriber>>> eventToSubscribers_{};
std::map<sptr<IRemoteObject>, std::shared_ptr<CleanupTimer>> timers_{}; std::map<sptr<IRemoteObject>, std::shared_ptr<CleanupTimer>> timers_{};
std::map<int64_t, std::shared_ptr<ICollectorFwk>> eventToListenner_;
}; };
} }
#endif // SECURITY_GUARD_SECURITY_COLLECTOR_SUBSCRIBLER_MANAGER_H #endif // SECURITY_GUARD_SECURITY_COLLECTOR_SUBSCRIBLER_MANAGER_H

View File

@ -114,10 +114,9 @@ int32_t SecurityCollectorManagerService::Subscribe(const SecurityCollectorSubscr
const sptr<IRemoteObject> &callback) const sptr<IRemoteObject> &callback)
{ {
Event event = subscribeInfo.GetEvent(); Event event = subscribeInfo.GetEvent();
LOGI("in subscribe, subscribinfo: duration:%{public}ld, isNotify:%{public}d, \n" LOGI("in subscribe, subscribinfo: duration:%{public}ld, isNotify:%{public}d, eventid:%{public}ld, \n"
"eventid:%{public}ld, version:%{public}s, content:%{public}s, extra:%{public}s,", "version:%{public}s, extra:%{public}s", subscribeInfo.GetDuration(), (int)subscribeInfo.IsNotify(),
subscribeInfo.GetDuration(), (int)subscribeInfo.IsNotify(), event.eventId, event.version.c_str(), event.extra.c_str());
event.eventId, event.version.c_str(), event.content.c_str(), event.extra.c_str());
if (!HasPermission()) { if (!HasPermission()) {
LOGE("caller no permission"); LOGE("caller no permission");
@ -131,9 +130,8 @@ int32_t SecurityCollectorManagerService::Subscribe(const SecurityCollectorSubscr
return NULL_OBJECT; return NULL_OBJECT;
} }
auto eventHandler = [] (const std::string &appName, const sptr<IRemoteObject> &remote, const Event &event) { auto eventHandler = [] (const std::string &appName, const sptr<IRemoteObject> &remote, const Event &event) {
LOGE("xxxx OnChange eventid:%{public}ld ", event.eventId);
if (appName == NOTIFY_APP_NAME) { if (appName == NOTIFY_APP_NAME) {
LOGI(" xxxx report to SG "); LOGI("eventid:%{public}ld callback default", event.eventId);
auto reportEvent = [event] () { auto reportEvent = [event] () {
auto info = std::make_shared<SecurityGuard::EventInfo>(event.eventId, event.version, event.content); auto info = std::make_shared<SecurityGuard::EventInfo>(event.eventId, event.version, event.content);
(void)SecurityGuard::NativeDataCollectKit::ReportSecurityInfo(info); (void)SecurityGuard::NativeDataCollectKit::ReportSecurityInfo(info);
@ -143,11 +141,13 @@ int32_t SecurityCollectorManagerService::Subscribe(const SecurityCollectorSubscr
} }
auto proxy = iface_cast<SecurityCollectorManagerCallbackProxy>(remote); auto proxy = iface_cast<SecurityCollectorManagerCallbackProxy>(remote);
if (proxy != nullptr) { if (proxy != nullptr) {
LOGI("report to proxy");
proxy->OnNotify(event); proxy->OnNotify(event);
} else {
LOGE("report proxy is null");
} }
}; };
auto subscriber = std::make_shared<SecurityCollectorSubscriber>(appName, subscribeInfo, callback, eventHandler); auto subscriber = std::make_shared<SecurityCollectorSubscriber>(appName, subscribeInfo, callback, eventHandler);
ScSubscribeEvent subEvent; ScSubscribeEvent subEvent;
subEvent.pid = IPCSkeleton::GetCallingPid(); subEvent.pid = IPCSkeleton::GetCallingPid();
subEvent.version = event.version; subEvent.version = event.version;

View File

@ -24,27 +24,34 @@ namespace {
} }
SecurityCollectorSubscriberManager::SecurityCollectorSubscriberManager() SecurityCollectorSubscriberManager::SecurityCollectorSubscriberManager()
{ {
auto onNotifyHandler = [this] (const Event &event) { }
std::lock_guard<std::mutex> lock(collectorMutex_);
LOGE("publish event: eventid:%{public}ld, version:%{public}s, content:%{public}s, extra:%{public}s", std::string SecurityCollectorSubscriberManager::CollectorListenner::GetExtraInfo()
event.eventId, event.version.c_str(), event.content.c_str(), event.extra.c_str()); {
const auto it = eventToSubscribers_.find(event.eventId); if (subscriber_) {
if (it == eventToSubscribers_.end()) { return subscriber_->GetSecurityCollectorSubscribeInfo().GetEvent().extra;
return; }
} return {};
for (const auto &subscriber : it->second) {
if (subscriber != nullptr) {
subscriber->OnChange(event);
}
}
};
collectorListenner_ = std::make_shared<SecurityCollectorSubscriberManager::CollectorListenner>(onNotifyHandler);
} }
void SecurityCollectorSubscriberManager::CollectorListenner::OnNotify(const Event &event) void SecurityCollectorSubscriberManager::CollectorListenner::OnNotify(const Event &event)
{ {
if (onNotifyHandler_) { SecurityCollectorSubscriberManager::GetInstance().NotifySubscriber(event);
onNotifyHandler_(event); }
void SecurityCollectorSubscriberManager::NotifySubscriber(const Event &event)
{
std::lock_guard<std::mutex> 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); LOGE("Already subscribed eventId:%{public}ld", eventId);
return false; return false;
} }
if (eventToListenner_.count(eventId) == 0) {
LOGI("Scheduling start collecctor, eventId:%{public}ld", eventId); auto collectorListenner = std::make_shared<SecurityCollectorSubscriberManager::CollectorListenner>(subscriber);
if (!DataCollection::GetInstance().StartCollectors(std::vector<int64_t>{eventId}, collectorListenner_)) { LOGI("Scheduling start collector, eventId:%{public}ld", eventId);
LOGE("failed to start collectors"); if (!DataCollection::GetInstance().StartCollectors(std::vector<int64_t>{eventId}, collectorListenner)) {
return false; 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); eventToSubscribers_[eventId].emplace(subscriber);
LOGI("eventId:%{public}ld, callbackCount:%{public}ld", eventId, eventToSubscribers_[eventId].size()); LOGI("eventId:%{public}ld, callbackCount:%{public}ld", eventId, eventToSubscribers_[eventId].size());
int64_t duration = subscriber->GetSecurityCollectorSubscribeInfo().GetDuration(); int64_t duration = subscriber->GetSecurityCollectorSubscribeInfo().GetDuration();
if (duration > 0) { if (duration > 0) {
auto remote = subscriber->GetRemote(); auto remote = subscriber->GetRemote();
@ -165,6 +176,7 @@ bool SecurityCollectorSubscriberManager::UnsubscribeCollector(const sptr<IRemote
LOGE("failed to stop collectors"); LOGE("failed to stop collectors");
} }
eventToSubscribers_.erase(eventId); eventToSubscribers_.erase(eventId);
eventToListenner_.erase(eventId);
} }
} }
} }