1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "sec_comp_client.h"
16
17 #include "iservice_registry.h"
18 #include "sec_comp_load_callback.h"
19 #include "sec_comp_log.h"
20 #include "sec_comp_proxy.h"
21
22 namespace OHOS {
23 namespace Security {
24 namespace SecurityComponent {
25 namespace {
26 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_SECURITY_COMPONENT, "SecCompClient"};
27 } // namespace
28
GetInstance()29 SecCompClient& SecCompClient::GetInstance()
30 {
31 static SecCompClient instance;
32 return instance;
33 }
34
SecCompClient()35 SecCompClient::SecCompClient()
36 {}
37
~SecCompClient()38 SecCompClient::~SecCompClient()
39 {
40 if (proxy_ == nullptr) {
41 return;
42 }
43 auto remoteObj = proxy_->AsObject();
44 if ((remoteObj != nullptr) && (serviceDeathObserver_ != nullptr)) {
45 remoteObj->RemoveDeathRecipient(serviceDeathObserver_);
46 }
47 }
48
RegisterSecurityComponent(SecCompType type,const std::string & componentInfo,int32_t & scId)49 int32_t SecCompClient::RegisterSecurityComponent(SecCompType type,
50 const std::string& componentInfo, int32_t& scId)
51 {
52 auto proxy = GetProxy(true);
53 if (proxy == nullptr) {
54 SC_LOG_ERROR(LABEL, "Proxy is null");
55 return SC_SERVICE_ERROR_VALUE_INVALID;
56 }
57
58 return proxy->RegisterSecurityComponent(type, componentInfo, scId);
59 }
60
UpdateSecurityComponent(int32_t scId,const std::string & componentInfo)61 int32_t SecCompClient::UpdateSecurityComponent(int32_t scId, const std::string& componentInfo)
62 {
63 auto proxy = GetProxy(true);
64 if (proxy == nullptr) {
65 SC_LOG_ERROR(LABEL, "Proxy is null");
66 return SC_SERVICE_ERROR_VALUE_INVALID;
67 }
68
69 return proxy->UpdateSecurityComponent(scId, componentInfo);
70 }
71
UnregisterSecurityComponent(int32_t scId)72 int32_t SecCompClient::UnregisterSecurityComponent(int32_t scId)
73 {
74 auto proxy = GetProxy(true);
75 if (proxy == nullptr) {
76 SC_LOG_ERROR(LABEL, "Proxy is null");
77 return SC_SERVICE_ERROR_VALUE_INVALID;
78 }
79
80 return proxy->UnregisterSecurityComponent(scId);
81 }
82
ReportSecurityComponentClickEvent(int32_t scId,const std::string & componentInfo,const SecCompClickEvent & touchInfo,sptr<IRemoteObject> callerToken)83 int32_t SecCompClient::ReportSecurityComponentClickEvent(int32_t scId,
84 const std::string& componentInfo, const SecCompClickEvent& touchInfo, sptr<IRemoteObject> callerToken)
85 {
86 auto proxy = GetProxy(true);
87 if (proxy == nullptr) {
88 SC_LOG_ERROR(LABEL, "Proxy is null");
89 return SC_SERVICE_ERROR_VALUE_INVALID;
90 }
91
92 return proxy->ReportSecurityComponentClickEvent(scId, componentInfo, touchInfo, callerToken);
93 }
94
ReduceAfterVerifySavePermission(AccessToken::AccessTokenID tokenId)95 bool SecCompClient::ReduceAfterVerifySavePermission(AccessToken::AccessTokenID tokenId)
96 {
97 auto proxy = GetProxy(false);
98 if (proxy == nullptr) {
99 SC_LOG_ERROR(LABEL, "Proxy is null");
100 return false;
101 }
102
103 return proxy->ReduceAfterVerifySavePermission(tokenId);
104 }
105
GetEnhanceRemoteObject(bool doLoadSa)106 sptr<IRemoteObject> SecCompClient::GetEnhanceRemoteObject(bool doLoadSa)
107 {
108 auto proxy = GetProxy(doLoadSa);
109 if (proxy == nullptr) {
110 return nullptr;
111 }
112
113 return proxy->GetEnhanceRemoteObject();
114 }
115
StartLoadSecCompSa()116 bool SecCompClient::StartLoadSecCompSa()
117 {
118 {
119 std::unique_lock<std::mutex> lock(cvLock_);
120 readyFlag_ = false;
121 }
122 auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
123 if (sam == nullptr) {
124 SC_LOG_ERROR(LABEL, "GetSystemAbilityManager return null");
125 return false;
126 }
127 sptr<SecCompLoadCallback> ptrSecCompLoadCallback =
128 new (std::nothrow) SecCompLoadCallback();
129 if (ptrSecCompLoadCallback == nullptr) {
130 SC_LOG_ERROR(LABEL, "New ptrSecCompLoadCallback fail.");
131 return false;
132 }
133
134 int32_t result = sam->LoadSystemAbility(SA_ID_SECURITY_COMPONENT_SERVICE,
135 ptrSecCompLoadCallback);
136 if (result != SC_OK) {
137 SC_LOG_ERROR(LABEL, "LoadSystemAbility %{public}d failed", SA_ID_SECURITY_COMPONENT_SERVICE);
138 return false;
139 }
140 SC_LOG_INFO(LABEL, "Notify samgr load sa %{public}d, waiting for service start", SA_ID_SECURITY_COMPONENT_SERVICE);
141 return true;
142 }
143
TryToGetSecCompSa()144 bool SecCompClient::TryToGetSecCompSa()
145 {
146 auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
147 if (sam == nullptr) {
148 SC_LOG_ERROR(LABEL, "GetSystemAbilityManager return null");
149 return false;
150 }
151
152 auto secCompSa = sam->CheckSystemAbility(SA_ID_SECURITY_COMPONENT_SERVICE);
153 if (secCompSa == nullptr) {
154 SC_LOG_INFO(LABEL, "Service is not start.");
155 return false;
156 }
157 GetProxyFromRemoteObject(secCompSa);
158 return true;
159 }
160
WaitForSecCompSa()161 void SecCompClient::WaitForSecCompSa()
162 {
163 // wait_for release lock and block until time out(1s) or match the condition with notice
164 std::unique_lock<std::mutex> lock(cvLock_);
165 auto waitStatus = secComCon_.wait_for(
166 lock, std::chrono::milliseconds(SA_ID_SECURITY_COMPONENT_SERVICE), [this]() { return readyFlag_; });
167 if (!waitStatus) {
168 // time out or loadcallback fail
169 SC_LOG_ERROR(LABEL, "security component load sa timeout");
170 return;
171 }
172 }
173
FinishStartSASuccess(const sptr<IRemoteObject> & remoteObject)174 void SecCompClient::FinishStartSASuccess(const sptr<IRemoteObject>& remoteObject)
175 {
176 GetProxyFromRemoteObject(remoteObject);
177 // get lock which wait_for release and send a notice so that wait_for can out of block
178 std::unique_lock<std::mutex> lock(cvLock_);
179 readyFlag_ = true;
180 secComCon_.notify_one();
181 }
182
FinishStartSAFail()183 void SecCompClient::FinishStartSAFail()
184 {
185 SC_LOG_ERROR(LABEL, "get security component sa failed.");
186 // get lock which wait_for release and send a notice
187 std::unique_lock<std::mutex> lock(cvLock_);
188 readyFlag_ = true;
189 secComCon_.notify_one();
190 }
191
LoadSecCompSa()192 void SecCompClient::LoadSecCompSa()
193 {
194 if (!StartLoadSecCompSa()) {
195 return;
196 }
197 WaitForSecCompSa();
198 }
199
OnRemoteDiedHandle()200 void SecCompClient::OnRemoteDiedHandle()
201 {
202 SC_LOG_ERROR(LABEL, "Remote service died");
203 std::unique_lock<std::mutex> lock(proxyMutex_);
204 proxy_ = nullptr;
205 serviceDeathObserver_ = nullptr;
206 {
207 std::unique_lock<std::mutex> lock1(cvLock_);
208 readyFlag_ = false;
209 }
210 }
211
GetProxyFromRemoteObject(const sptr<IRemoteObject> & remoteObject)212 void SecCompClient::GetProxyFromRemoteObject(const sptr<IRemoteObject>& remoteObject)
213 {
214 if (remoteObject == nullptr) {
215 return;
216 }
217
218 sptr<SecCompDeathRecipient> serviceDeathObserver = new (std::nothrow) SecCompDeathRecipient();
219 if (serviceDeathObserver == nullptr) {
220 SC_LOG_ERROR(LABEL, "Alloc service death observer fail");
221 return;
222 }
223
224 if (!remoteObject->AddDeathRecipient(serviceDeathObserver)) {
225 SC_LOG_ERROR(LABEL, "Add service death observer fail");
226 return;
227 }
228
229 auto proxy = iface_cast<ISecCompService>(remoteObject);
230 if (proxy == nullptr) {
231 SC_LOG_ERROR(LABEL, "iface_cast get null");
232 return;
233 }
234 proxy_ = proxy;
235 serviceDeathObserver_ = serviceDeathObserver;
236 SC_LOG_INFO(LABEL, "GetSystemAbility %{public}d success", SA_ID_SECURITY_COMPONENT_SERVICE);
237 return;
238 }
239
GetProxy(bool doLoadSa)240 sptr<ISecCompService> SecCompClient::GetProxy(bool doLoadSa)
241 {
242 std::unique_lock<std::mutex> lock(proxyMutex_);
243 if (proxy_ != nullptr) {
244 return proxy_;
245 }
246 if (TryToGetSecCompSa() || !doLoadSa) {
247 return proxy_;
248 }
249
250 LoadSecCompSa();
251 return proxy_;
252 }
253 } // namespace SecurityComponent
254 } // namespace Security
255 } // namespace OHOS
256