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