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_perm_manager.h"
16
17 #include "sec_comp_err.h"
18 #include "sec_comp_log.h"
19
20 namespace OHOS {
21 namespace Security {
22 namespace SecurityComponent {
23 namespace {
24 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_SECURITY_COMPONENT, "SecCompPermManager"};
25 static const int32_t DELAY_REVOKE_MILLISECONDS = 10 * 1000;
26 static constexpr int32_t DELAY_SAVE_REVOKE_MILLISECONDS = 60 * 1000;
27 static const std::string REVOKE_TASK_PREFIX = "RevokeAll";
28 static const std::string REVOKE_SAVE_PERM_TASK_PREFIX = "RevokeSavePerm";
29 static std::mutex g_instanceMutex;
30 }
31
GetInstance()32 SecCompPermManager& SecCompPermManager::GetInstance()
33 {
34 static SecCompPermManager* instance = nullptr;
35 if (instance == nullptr) {
36 std::lock_guard<std::mutex> lock(g_instanceMutex);
37 if (instance == nullptr) {
38 instance = new SecCompPermManager();
39 }
40 }
41 return *instance;
42 }
43
DelaySaveRevokePermission(AccessToken::AccessTokenID tokenId,const std::string & taskName)44 bool SecCompPermManager::DelaySaveRevokePermission(AccessToken::AccessTokenID tokenId, const std::string& taskName)
45 {
46 if (secHandler_ == nullptr) {
47 SC_LOG_ERROR(LABEL, "fail to get EventHandler");
48 return false;
49 }
50
51 std::function<void()> delayed = ([tokenId]() {
52 SC_LOG_DEBUG(LABEL, "delay revoke save permission");
53 SecCompPermManager::GetInstance().RevokeTempSavePermissionCount(tokenId);
54 });
55
56 SC_LOG_DEBUG(LABEL, "revoke save permission after %{public}d ms", DELAY_SAVE_REVOKE_MILLISECONDS);
57 secHandler_->ProxyPostTask(delayed, taskName, DELAY_SAVE_REVOKE_MILLISECONDS);
58 return true;
59 }
60
RevokeSavePermissionTask(const std::string & taskName)61 bool SecCompPermManager::RevokeSavePermissionTask(const std::string& taskName)
62 {
63 if (secHandler_ == nullptr) {
64 SC_LOG_ERROR(LABEL, "fail to get EventHandler");
65 return false;
66 }
67
68 SC_LOG_DEBUG(LABEL, "revoke save permission task name:%{public}s", taskName.c_str());
69 secHandler_->ProxyRemoveTask(taskName);
70 return true;
71 }
72
GrantTempSavePermission(AccessToken::AccessTokenID tokenId)73 int32_t SecCompPermManager::GrantTempSavePermission(AccessToken::AccessTokenID tokenId)
74 {
75 auto current = static_cast<uint64_t>(std::chrono::high_resolution_clock::now().time_since_epoch().count());
76 std::string taskName = std::to_string(tokenId) + std::to_string(current);
77 if (!DelaySaveRevokePermission(tokenId, taskName)) {
78 return SC_SERVICE_ERROR_PERMISSION_OPER_FAIL;
79 }
80 std::lock_guard<std::mutex> lock(mutex_);
81 saveTaskDequeMap_[tokenId].push_back(taskName);
82 applySaveCountMap_[tokenId]++;
83 SC_LOG_DEBUG(LABEL, "tokenId: %{public}d current permission apply counts is: %{public}d.",
84 tokenId, applySaveCountMap_[tokenId]);
85 return SC_OK;
86 }
87
RevokeTempSavePermissionCount(AccessToken::AccessTokenID tokenId)88 void SecCompPermManager::RevokeTempSavePermissionCount(AccessToken::AccessTokenID tokenId)
89 {
90 std::lock_guard<std::mutex> lock(mutex_);
91 auto iter = applySaveCountMap_.find(tokenId);
92 if (iter == applySaveCountMap_.end()) {
93 SC_LOG_ERROR(LABEL, "This hap has no permissions to save files.");
94 return;
95 }
96 if (saveTaskDequeMap_[tokenId].size() == 0) {
97 SC_LOG_ERROR(LABEL, "Current no task need to be revoke.");
98 return;
99 }
100 std::string taskName = saveTaskDequeMap_[tokenId].front();
101 if (!RevokeSavePermissionTask(taskName)) {
102 return;
103 }
104 saveTaskDequeMap_[tokenId].pop_front();
105 SC_LOG_DEBUG(LABEL, "tokenId: %{public}d current permission apply counts is: %{public}d.",
106 tokenId, applySaveCountMap_[tokenId]);
107 if ((--applySaveCountMap_[tokenId]) == 0) {
108 applySaveCountMap_.erase(tokenId);
109 SC_LOG_INFO(LABEL, "tokenId: %{public}d save permission count is 0, revoke it.", tokenId);
110 }
111 return;
112 }
113
RevokeTempSavePermission(AccessToken::AccessTokenID tokenId)114 void SecCompPermManager::RevokeTempSavePermission(AccessToken::AccessTokenID tokenId)
115 {
116 std::lock_guard<std::mutex> lock(mutex_);
117 applySaveCountMap_.erase(tokenId);
118 auto& taskDeque = saveTaskDequeMap_[tokenId];
119 for (auto iter = taskDeque.begin(); iter != taskDeque.end(); ++iter) {
120 if (!RevokeSavePermissionTask(*iter)) {
121 continue;
122 }
123 }
124 taskDeque.clear();
125 SC_LOG_INFO(LABEL, "tokenId: %{public}d revoke save permission.", tokenId);
126 return;
127 }
128
VerifySavePermission(AccessToken::AccessTokenID tokenId)129 bool SecCompPermManager::VerifySavePermission(AccessToken::AccessTokenID tokenId)
130 {
131 std::lock_guard<std::mutex> lock(mutex_);
132 auto iter = applySaveCountMap_.find(tokenId);
133 if (iter == applySaveCountMap_.end() || applySaveCountMap_[tokenId] == 0) {
134 SC_LOG_ERROR(LABEL, "This hap has no permissions to save files.");
135 return false;
136 }
137 return true;
138 }
139
VerifyPermission(AccessToken::AccessTokenID tokenId,SecCompType type)140 bool SecCompPermManager::VerifyPermission(AccessToken::AccessTokenID tokenId, SecCompType type)
141 {
142 int32_t res;
143 switch (type) {
144 case LOCATION_COMPONENT:
145 res = AccessToken::AccessTokenKit::VerifyAccessToken(tokenId, "ohos.permission.LOCATION");
146 if (res != AccessToken::TypePermissionState::PERMISSION_GRANTED) {
147 return false;
148 }
149 res = AccessToken::AccessTokenKit::VerifyAccessToken(tokenId, "ohos.permission.APPROXIMATELY_LOCATION");
150 return (res == AccessToken::TypePermissionState::PERMISSION_GRANTED);
151 case PASTE_COMPONENT:
152 res = AccessToken::AccessTokenKit::VerifyAccessToken(tokenId,
153 "ohos.permission.SECURE_PASTE");
154 return (res == AccessToken::TypePermissionState::PERMISSION_GRANTED);
155 case SAVE_COMPONENT:
156 return VerifySavePermission(tokenId);
157 default:
158 SC_LOG_ERROR(LABEL, "Unknown component type.");
159 }
160 return false;
161 }
162
AddAppGrantPermissionRecord(AccessToken::AccessTokenID tokenId,const std::string & permissionName)163 void SecCompPermManager::AddAppGrantPermissionRecord(AccessToken::AccessTokenID tokenId,
164 const std::string& permissionName)
165 {
166 auto iter = grantMap_.find(tokenId);
167 if (iter != grantMap_.end()) {
168 iter->second.insert(permissionName);
169 return;
170 }
171 std::set<std::string> permSet;
172 permSet.insert(permissionName);
173 grantMap_[tokenId] = permSet;
174 }
175
RemoveAppGrantPermissionRecord(AccessToken::AccessTokenID tokenId,const std::string & permissionName)176 void SecCompPermManager::RemoveAppGrantPermissionRecord(AccessToken::AccessTokenID tokenId,
177 const std::string& permissionName)
178 {
179 auto iter = grantMap_.find(tokenId);
180 if (iter == grantMap_.end()) {
181 return;
182 }
183
184 grantMap_[tokenId].erase(permissionName);
185 }
186
GrantAppPermission(AccessToken::AccessTokenID tokenId,const std::string & permissionName)187 int32_t SecCompPermManager::GrantAppPermission(AccessToken::AccessTokenID tokenId,
188 const std::string& permissionName)
189 {
190 std::lock_guard<std::mutex> lock(grantMtx_);
191 int32_t res = AccessToken::AccessTokenKit::GrantPermission(tokenId, permissionName,
192 AccessToken::PermissionFlag::PERMISSION_COMPONENT_SET);
193 SC_LOG_INFO(LABEL, "grant permission res: %{public}d, permission: %{public}s, tokenId:%{public}d",
194 res, permissionName.c_str(), tokenId);
195
196 AddAppGrantPermissionRecord(tokenId, permissionName);
197 return res;
198 }
199
RevokeAppPermission(AccessToken::AccessTokenID tokenId,const std::string & permissionName)200 int32_t SecCompPermManager::RevokeAppPermission(AccessToken::AccessTokenID tokenId,
201 const std::string& permissionName)
202 {
203 std::lock_guard<std::mutex> lock(grantMtx_);
204 int32_t res = AccessToken::AccessTokenKit::RevokePermission(tokenId, permissionName,
205 AccessToken::PermissionFlag::PERMISSION_COMPONENT_SET);
206 SC_LOG_INFO(LABEL, "revoke permission res: %{public}d, permission: %{public}s, tokenId:%{public}d",
207 res, permissionName.c_str(), tokenId);
208
209 RemoveAppGrantPermissionRecord(tokenId, permissionName);
210 return res;
211 }
212
RevokeAppPermissions(AccessToken::AccessTokenID tokenId)213 void SecCompPermManager::RevokeAppPermissions(AccessToken::AccessTokenID tokenId)
214 {
215 RevokeAppPermisionsImmediately(tokenId);
216 CancelAppRevokingPermisions(tokenId);
217 }
218
RevokeAppPermisionsDelayed(AccessToken::AccessTokenID tokenId)219 void SecCompPermManager::RevokeAppPermisionsDelayed(AccessToken::AccessTokenID tokenId)
220 {
221 if (secHandler_ == nullptr) {
222 SC_LOG_ERROR(LABEL, "fail to get EventHandler");
223 return;
224 }
225
226 std::function<void()> delayed = ([tokenId]() {
227 SC_LOG_DEBUG(LABEL, "delay revoke token id %{public}d permissions", tokenId);
228 SecCompPermManager::GetInstance().RevokeAppPermisionsImmediately(tokenId);
229 });
230
231 SC_LOG_DEBUG(LABEL, "revoke token id %{public}d permissions after %{public}d ms",
232 tokenId, DELAY_REVOKE_MILLISECONDS);
233 std::string taskName = REVOKE_TASK_PREFIX + std::to_string(tokenId);
234 secHandler_->ProxyPostTask(delayed, taskName, DELAY_REVOKE_MILLISECONDS);
235 }
236
RevokeAppPermisionsImmediately(AccessToken::AccessTokenID tokenId)237 void SecCompPermManager::RevokeAppPermisionsImmediately(AccessToken::AccessTokenID tokenId)
238 {
239 std::lock_guard<std::mutex> lock(grantMtx_);
240 auto it = grantMap_.find(tokenId);
241 if (it == grantMap_.end()) {
242 return;
243 }
244
245 auto& grantSet = grantMap_[tokenId];
246 for (auto iter = grantSet.begin(); iter != grantSet.end(); ++iter) {
247 int32_t res = AccessToken::AccessTokenKit::RevokePermission(tokenId, *iter,
248 AccessToken::PermissionFlag::PERMISSION_COMPONENT_SET);
249 SC_LOG_INFO(LABEL, "revoke token id %{public}d permission %{public}s res %{public}d",
250 tokenId, iter->c_str(), res);
251 }
252 grantSet.clear();
253 }
254
CancelAppRevokingPermisions(AccessToken::AccessTokenID tokenId)255 void SecCompPermManager::CancelAppRevokingPermisions(AccessToken::AccessTokenID tokenId)
256 {
257 if (secHandler_ == nullptr) {
258 SC_LOG_ERROR(LABEL, "fail to get EventHandler");
259 return;
260 }
261
262 SC_LOG_DEBUG(LABEL, "cancel revoke token id %{public}d permission", tokenId);
263 std::string taskName = REVOKE_TASK_PREFIX + std::to_string(tokenId);
264 secHandler_->ProxyRemoveTask(taskName);
265 }
266
InitEventHandler(const std::shared_ptr<SecEventHandler> & secHandler)267 void SecCompPermManager::InitEventHandler(const std::shared_ptr<SecEventHandler>& secHandler)
268 {
269 secHandler_ = secHandler;
270 }
271
272 namespace {
IsDlpSandboxCalling(AccessToken::AccessTokenID tokenId)273 inline bool IsDlpSandboxCalling(AccessToken::AccessTokenID tokenId)
274 {
275 return AccessToken::AccessTokenKit::GetHapDlpFlag(tokenId) != 0;
276 }
277 }
278
GrantTempPermission(AccessToken::AccessTokenID tokenId,const std::shared_ptr<SecCompBase> & componentInfo)279 int32_t SecCompPermManager::GrantTempPermission(AccessToken::AccessTokenID tokenId,
280 const std::shared_ptr<SecCompBase>& componentInfo)
281 {
282 if ((tokenId <= 0) || (componentInfo == nullptr)) {
283 SC_LOG_ERROR(LABEL, "Grant component is null");
284 return SC_SERVICE_ERROR_PERMISSION_OPER_FAIL;
285 }
286
287 SecCompType type = componentInfo->type_;
288 int32_t res;
289 switch (type) {
290 case LOCATION_COMPONENT:
291 {
292 res = GrantAppPermission(tokenId, "ohos.permission.APPROXIMATELY_LOCATION");
293 if (res != SC_OK) {
294 return SC_SERVICE_ERROR_PERMISSION_OPER_FAIL;
295 }
296 res = GrantAppPermission(tokenId, "ohos.permission.LOCATION");
297 if (res != SC_OK) {
298 RevokeAppPermission(tokenId, "ohos.permission.APPROXIMATELY_LOCATION");
299 return SC_SERVICE_ERROR_PERMISSION_OPER_FAIL;
300 }
301 SC_LOG_INFO(LABEL, "Grant location permission, scid = %{public}d.", componentInfo->nodeId_);
302 return SC_OK;
303 }
304 case PASTE_COMPONENT:
305 res = GrantAppPermission(tokenId, "ohos.permission.SECURE_PASTE");
306 if (res != SC_OK) {
307 return SC_SERVICE_ERROR_PERMISSION_OPER_FAIL;
308 }
309 SC_LOG_INFO(LABEL, "Grant paste permission, scid = %{public}d.", componentInfo->nodeId_);
310 return SC_OK;
311 case SAVE_COMPONENT:
312 if (IsDlpSandboxCalling(tokenId)) {
313 SC_LOG_INFO(LABEL, "Dlp sandbox app are not allowed to use save component.");
314 return SC_SERVICE_ERROR_PERMISSION_OPER_FAIL;
315 }
316 SC_LOG_INFO(LABEL, "Grant save permission, scid = %{public}d.", componentInfo->nodeId_);
317 return GrantTempSavePermission(tokenId);
318 default:
319 SC_LOG_ERROR(LABEL, "Parse component type unknown");
320 break;
321 }
322 return SC_SERVICE_ERROR_PERMISSION_OPER_FAIL;
323 }
324 } // namespace SecurityComponent
325 } // namespace Security
326 } // namespace OHOS
327