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
16 #include "verify_manager_host_impl.h"
17
18 #include <sys/wait.h>
19
20 #include "bundle_mgr_service.h"
21 #include "bundle_permission_mgr.h"
22 #include "installd_client.h"
23 #include "ipc_skeleton.h"
24 #include "verify_util.h"
25
26 namespace OHOS {
27 namespace AppExecFwk {
28 namespace {
29 const std::string SEPARATOR = "/";
30 const std::string ABCS_DIR = "abcs";
31 const std::string ABCS_TEMP_DIR = "temp/";
32 const std::string DATA_STORAGE_BUNDLE = "/data/storage/el1/bundle/";
33 const std::string DATA_STORAGE_EL1_BASE = "/data/storage/el1/base/";
34 const std::string DATA_STORAGE_EL1_DATABASE = "/data/storage/el1/database/";
35 const std::string DATA_STORAGE_EL2_BASE = "/data/storage/el2/base/";
36 const std::string DATA_STORAGE_EL2_DATABASE = "/data/storage/el2/database/";
37 const std::string DATA_STORAGE_EL3_BASE = "/data/storage/el3/base/";
38 const std::string DATA_STORAGE_EL3_DATABASE = "/data/storage/el3/database/";
39 const std::string DATA_STORAGE_EL4_BASE = "/data/storage/el4/base/";
40 const std::string DATA_STORAGE_EL4_DATABASE = "/data/storage/el4/database/";
41 constexpr const char* ABC_FILE_SUFFIX = ".abc";
42
IsValidPath(const std::string & path)43 bool IsValidPath(const std::string &path)
44 {
45 if (path.empty()) {
46 return false;
47 }
48 if (path.find("..") != std::string::npos) {
49 return false;
50 }
51 return true;
52 }
53
GetRootDir(const std::string & bundleName)54 std::string GetRootDir(const std::string &bundleName)
55 {
56 std::string rootDir;
57 rootDir.append(Constants::BUNDLE_CODE_DIR).append(ServiceConstants::PATH_SEPARATOR)
58 .append(bundleName).append(ServiceConstants::PATH_SEPARATOR)
59 .append(ABCS_DIR).append(ServiceConstants::PATH_SEPARATOR);
60 return rootDir;
61 }
62
GetTempRootDir(const std::string & bundleName)63 std::string GetTempRootDir(const std::string &bundleName)
64 {
65 std::string tempRootDir;
66 tempRootDir.append(Constants::BUNDLE_CODE_DIR).append(ServiceConstants::PATH_SEPARATOR)
67 .append(bundleName).append(ServiceConstants::PATH_SEPARATOR).append(ABCS_DIR)
68 .append(ServiceConstants::PATH_SEPARATOR).append(ABCS_TEMP_DIR);
69 return tempRootDir;
70 }
71
GetDataDir(const std::string & path,std::string & suffix,std::string & el,std::string & baseType)72 bool GetDataDir(const std::string &path, std::string &suffix, std::string &el, std::string &baseType)
73 {
74 if (BundleUtil::StartWith(path, DATA_STORAGE_EL1_BASE)) {
75 suffix = path.substr(DATA_STORAGE_EL1_BASE.size());
76 el = ServiceConstants::DIR_EL1;
77 baseType = ServiceConstants::BASE;
78 return true;
79 }
80
81 if (BundleUtil::StartWith(path, DATA_STORAGE_EL1_DATABASE)) {
82 suffix = path.substr(DATA_STORAGE_EL1_DATABASE.size());
83 el = ServiceConstants::DIR_EL1;
84 baseType = ServiceConstants::DATABASE;
85 return true;
86 }
87
88 if (BundleUtil::StartWith(path, DATA_STORAGE_EL2_BASE)) {
89 suffix = path.substr(DATA_STORAGE_EL2_BASE.size());
90 el = ServiceConstants::DIR_EL2;
91 baseType = ServiceConstants::BASE;
92 return true;
93 }
94
95 if (BundleUtil::StartWith(path, DATA_STORAGE_EL2_DATABASE)) {
96 suffix = path.substr(DATA_STORAGE_EL2_DATABASE.size());
97 el = ServiceConstants::DIR_EL2;
98 baseType = ServiceConstants::DATABASE;
99 return true;
100 }
101
102 if (BundleUtil::StartWith(path, DATA_STORAGE_EL3_BASE)) {
103 suffix = path.substr(DATA_STORAGE_EL3_BASE.size());
104 el = ServiceConstants::DIR_EL3;
105 baseType = ServiceConstants::BASE;
106 return true;
107 }
108
109 if (BundleUtil::StartWith(path, DATA_STORAGE_EL3_DATABASE)) {
110 suffix = path.substr(DATA_STORAGE_EL3_DATABASE.size());
111 el = ServiceConstants::DIR_EL3;
112 baseType = ServiceConstants::DATABASE;
113 return true;
114 }
115
116 if (BundleUtil::StartWith(path, DATA_STORAGE_EL4_BASE)) {
117 suffix = path.substr(DATA_STORAGE_EL4_BASE.size());
118 el = ServiceConstants::DIR_EL4;
119 baseType = ServiceConstants::BASE;
120 return true;
121 }
122
123 if (BundleUtil::StartWith(path, DATA_STORAGE_EL4_DATABASE)) {
124 suffix = path.substr(DATA_STORAGE_EL4_DATABASE.size());
125 el = ServiceConstants::DIR_EL4;
126 baseType = ServiceConstants::DATABASE;
127 return true;
128 }
129
130 return false;
131 }
132 }
133
VerifyManagerHostImpl()134 VerifyManagerHostImpl::VerifyManagerHostImpl()
135 {
136 APP_LOGI("create VerifyManagerHostImpl");
137 }
138
~VerifyManagerHostImpl()139 VerifyManagerHostImpl::~VerifyManagerHostImpl()
140 {
141 APP_LOGI("destroy VerifyManagerHostImpl");
142 }
143
Verify(const std::vector<std::string> & abcPaths)144 ErrCode VerifyManagerHostImpl::Verify(const std::vector<std::string> &abcPaths)
145 {
146 if (!BundlePermissionMgr::IsSystemApp() &&
147 !BundlePermissionMgr::VerifyCallingBundleSdkVersion(ServiceConstants::API_VERSION_TWELVE)) {
148 APP_LOGE("non-system app calling system api");
149 return ERR_BUNDLE_MANAGER_SYSTEM_API_DENIED;
150 }
151
152 if (!BundlePermissionMgr::VerifyCallingPermissionForAll(Constants::PERMISSION_RUN_DYN_CODE)) {
153 APP_LOGE("verify permission failed");
154 return ERR_BUNDLE_MANAGER_VERIFY_PERMISSION_DENIED;
155 }
156
157 std::string bundleName;
158 int32_t userId = BundleUtil::GetUserIdByCallingUid();
159 if (!GetCallingBundleName(bundleName) || bundleName.empty()) {
160 APP_LOGE("GetCallingBundleName failed");
161 return ERR_BUNDLE_MANAGER_VERIFY_PARAM_ERROR;
162 }
163
164 auto &mtx = GetBundleMutex(bundleName);
165 std::lock_guard lock {mtx};
166 if (!CheckFileParam(abcPaths)) {
167 APP_LOGE("CheckFile failed");
168 return ERR_BUNDLE_MANAGER_VERIFY_PARAM_ERROR;
169 }
170
171 if (!CopyFilesToTempDir(bundleName, userId, abcPaths)) {
172 APP_LOGE("Copy failed");
173 RemoveTempFiles(bundleName);
174 return ERR_BUNDLE_MANAGER_VERIFY_PARAM_ERROR;
175 }
176
177 ErrCode ret = InnerVerify(bundleName, abcPaths);
178 RemoveTempFiles(bundleName);
179 return ret;
180 }
181
GetCallingBundleName(std::string & bundleName)182 bool VerifyManagerHostImpl::GetCallingBundleName(std::string &bundleName)
183 {
184 auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
185 if (dataMgr == nullptr) {
186 APP_LOGE("verify failed, dataMgr is null");
187 return false;
188 }
189
190 int32_t callingUid = IPCSkeleton::GetCallingUid();
191 InnerBundleInfo innerBundleInfo;
192 if (dataMgr->GetInnerBundleInfoByUid(callingUid, innerBundleInfo) != ERR_OK) {
193 APP_LOGE("verify failed, callingUid is %{public}d", callingUid);
194 return false;
195 }
196
197 bundleName = innerBundleInfo.GetBundleName();
198 return true;
199 }
200
CopyFilesToTempDir(const std::string & bundleName,int32_t userId,const std::vector<std::string> & abcPaths)201 bool VerifyManagerHostImpl::CopyFilesToTempDir(
202 const std::string &bundleName,
203 int32_t userId,
204 const std::vector<std::string> &abcPaths)
205 {
206 std::string tempRootDir = GetTempRootDir(bundleName);
207 ErrCode result = MkdirIfNotExist(tempRootDir);
208 if (result != ERR_OK) {
209 APP_LOGE("mkdir tempRootDir %{public}s faild %{public}d", tempRootDir.c_str(), result);
210 return false;
211 }
212
213 for (size_t i = 0; i < abcPaths.size(); ++i) {
214 std::string tempCopyPath = tempRootDir + abcPaths[i];
215 std::string realPath = GetRealPath(bundleName, userId, abcPaths[i]);
216 if (realPath.empty()) {
217 APP_LOGE("abcPath %{public}s is illegal", abcPaths[i].c_str());
218 return false;
219 }
220
221 APP_LOGD("realPath is %{public}s", realPath.c_str());
222 std::string fileDir;
223 if (!GetFileDir(tempCopyPath, fileDir)) {
224 APP_LOGE("GetFileDir failed %{public}s", realPath.c_str());
225 return false;
226 }
227
228 result = MkdirIfNotExist(fileDir);
229 if (result != ERR_OK) {
230 APP_LOGE("mkdir fileDir %{public}s faild %{public}d", fileDir.c_str(), result);
231 return false;
232 }
233
234 result = InstalldClient::GetInstance()->CopyFile(realPath, tempCopyPath, "");
235 if (result != ERR_OK) {
236 APP_LOGE("CopyFile tempDir %{public}s faild %{public}d", realPath.c_str(), result);
237 return false;
238 }
239 }
240
241 return true;
242 }
243
GetRealPath(const std::string & bundleName,int32_t userId,const std::string & relativePath)244 std::string VerifyManagerHostImpl::GetRealPath(
245 const std::string &bundleName, int32_t userId, const std::string &relativePath)
246 {
247 auto path = relativePath;
248 if (!BundleUtil::StartWith(path, ServiceConstants::PATH_SEPARATOR)) {
249 path = ServiceConstants::PATH_SEPARATOR + path;
250 }
251
252 std::string filePath;
253 if (BundleUtil::StartWith(path, DATA_STORAGE_BUNDLE)) {
254 auto suffix = path.substr(DATA_STORAGE_BUNDLE.size());
255 filePath.append(Constants::BUNDLE_CODE_DIR).append(ServiceConstants::PATH_SEPARATOR)
256 .append(bundleName).append(ServiceConstants::PATH_SEPARATOR).append(suffix);
257 return filePath;
258 }
259
260 std::string suffix;
261 std::string el;
262 std::string baseType;
263 if (!GetDataDir(path, suffix, el, baseType)) {
264 APP_LOGW("The path %{public}s is illegal", path.c_str());
265 return filePath;
266 }
267
268 filePath.append(ServiceConstants::BUNDLE_APP_DATA_BASE_DIR).append(el)
269 .append(ServiceConstants::PATH_SEPARATOR).append(std::to_string(userId)).append(baseType)
270 .append(bundleName).append(ServiceConstants::PATH_SEPARATOR).append(suffix);
271 return filePath;
272 }
273
InnerVerify(const std::string & bundleName,const std::vector<std::string> & abcPaths)274 ErrCode VerifyManagerHostImpl::InnerVerify(
275 const std::string &bundleName,
276 const std::vector<std::string> &abcPaths)
277 {
278 if (!VerifyAbc(GetTempRootDir(bundleName), abcPaths)) {
279 APP_LOGE("verify abc failed");
280 return ERR_BUNDLE_MANAGER_VERIFY_VERIFY_ABC_FAILED;
281 }
282
283 if (!MoveAbc(bundleName, abcPaths)) {
284 APP_LOGE("move abc failed");
285 return ERR_BUNDLE_MANAGER_VERIFY_VERIFY_ABC_FAILED;
286 }
287
288 APP_LOGI("verify abc success");
289 return ERR_OK;
290 }
291
CheckFileParam(const std::vector<std::string> & abcPaths)292 bool VerifyManagerHostImpl::CheckFileParam(const std::vector<std::string> &abcPaths)
293 {
294 if (abcPaths.empty()) {
295 APP_LOGE("CheckFile abcPath failed due to abcPaths is empty");
296 return false;
297 }
298
299 for (const auto &abcPath : abcPaths) {
300 if (!IsValidPath(abcPath)) {
301 APP_LOGE("CheckFile abcPath(%{public}s) failed due to invalid path", abcPath.c_str());
302 return false;
303 }
304 if (!BundleUtil::CheckFileType(abcPath, ABC_FILE_SUFFIX)) {
305 APP_LOGE("CheckFile abcPath(%{public}s) failed due to not abc suffix", abcPath.c_str());
306 return false;
307 }
308 }
309
310 return true;
311 }
312
VerifyAbc(const std::string & rootDir,const std::vector<std::string> & names)313 bool VerifyManagerHostImpl::VerifyAbc(
314 const std::string &rootDir, const std::vector<std::string> &names)
315 {
316 std::vector<std::string> paths;
317 paths.reserve(names.size());
318 for (const auto &name : names) {
319 paths.emplace_back(rootDir + name);
320 }
321
322 return VerifyAbc(paths);
323 }
324
VerifyAbc(const std::vector<std::string> & abcPaths)325 bool VerifyManagerHostImpl::VerifyAbc(const std::vector<std::string> &abcPaths)
326 {
327 APP_LOGD("current process pid: %{public}d, ppid: %{public}d", getpid(), getppid());
328 pid_t pid = fork();
329 if (pid < 0) {
330 APP_LOGE("fork child process failed");
331 return false;
332 } else if (pid == 0) {
333 APP_LOGD("child process pid: %{public}d, ppid: %{public}d", getpid(), getppid());
334 for (const auto &abcPath : abcPaths) {
335 if (!BundleUtil::IsExistFile(abcPath)) {
336 APP_LOGE("abcPath is not exist: %{public}s", abcPath.c_str());
337 _exit(1);
338 }
339
340 if (!VerifyUtil::VerifyAbc(abcPath)) {
341 APP_LOGE("verify abc failed");
342 _exit(1);
343 }
344 }
345 APP_LOGI("verify abc successfully");
346 _exit(0);
347 } else {
348 int status;
349 pid_t childPid = waitpid(pid, &status, 0);
350 if (childPid == -1) {
351 APP_LOGE("waitpid failed");
352 return false;
353 }
354 if (WIFEXITED(status)) {
355 int exitStatus = WEXITSTATUS(status);
356 if (exitStatus != 0) {
357 APP_LOGE("verify abc failed");
358 return false;
359 }
360 } else {
361 APP_LOGE("child process did not exit normally");
362 return false;
363 }
364 }
365 APP_LOGD("end process pid: %{public}d, ppid: %{public}d", getpid(), getppid());
366 return true;
367 }
368
RemoveTempFiles(const std::string & bundleName)369 void VerifyManagerHostImpl::RemoveTempFiles(const std::string &bundleName)
370 {
371 APP_LOGI("RemoveTempFiles");
372 auto tempRootDir = GetTempRootDir(bundleName);
373 InstalldClient::GetInstance()->RemoveDir(tempRootDir);
374 }
375
RemoveTempFiles(const std::vector<std::string> & paths)376 void VerifyManagerHostImpl::RemoveTempFiles(const std::vector<std::string> &paths)
377 {
378 APP_LOGI("RemoveTempFiles");
379 for (const auto &path : paths) {
380 if (!BundleUtil::DeleteDir(path)) {
381 APP_LOGW("RemoveFile %{private}s failed", path.c_str());
382 }
383 }
384 }
385
GetFileName(const std::string & sourcePath,std::string & fileName)386 bool VerifyManagerHostImpl::GetFileName(const std::string &sourcePath, std::string &fileName)
387 {
388 size_t pos = sourcePath.find_last_of(SEPARATOR);
389 if (pos == std::string::npos) {
390 APP_LOGE("invalid sourcePath");
391 return false;
392 }
393
394 fileName = sourcePath.substr(pos + 1);
395 return !fileName.empty();
396 }
397
GetFileDir(const std::string & sourcePath,std::string & fileDir)398 bool VerifyManagerHostImpl::GetFileDir(const std::string &sourcePath, std::string &fileDir)
399 {
400 size_t pos = sourcePath.find_last_of(SEPARATOR);
401 if (pos == std::string::npos) {
402 APP_LOGE("invalid sourcePath");
403 return false;
404 }
405
406 fileDir = sourcePath.substr(0, pos);
407 return !fileDir.empty();
408 }
409
MkdirIfNotExist(const std::string & dir)410 ErrCode VerifyManagerHostImpl::MkdirIfNotExist(const std::string &dir)
411 {
412 bool isDirExist = false;
413 ErrCode result = InstalldClient::GetInstance()->IsExistDir(dir, isDirExist);
414 if (result != ERR_OK) {
415 APP_LOGE("Check if dir exist failed %{public}d", result);
416 return result;
417 }
418
419 if (!isDirExist) {
420 result = InstalldClient::GetInstance()->CreateBundleDir(dir);
421 if (result != ERR_OK) {
422 APP_LOGE("Create dir failed %{public}d", result);
423 return result;
424 }
425 }
426 return result;
427 }
428
MoveAbc(const std::string & bundleName,const std::vector<std::string> & abcPaths)429 bool VerifyManagerHostImpl::MoveAbc(
430 const std::string &bundleName,
431 const std::vector<std::string> &abcPaths)
432 {
433 auto rootDir = GetRootDir(bundleName);
434 auto tempRootDir = GetTempRootDir(bundleName);
435 std::vector<std::string> hasMovePaths;
436 ErrCode result = ERR_OK;
437 for (size_t i = 0; i < abcPaths.size(); ++i) {
438 std::string tempPath = tempRootDir + abcPaths[i];
439 std::string targetPath = rootDir + abcPaths[i];
440 std::string fileDir;
441 if (!GetFileDir(targetPath, fileDir)) {
442 APP_LOGE("GetFileDir failed %{public}s", targetPath.c_str());
443 Rollback(hasMovePaths);
444 return false;
445 }
446
447 result = MkdirIfNotExist(fileDir);
448 if (result != ERR_OK) {
449 APP_LOGE("mkdir fileDir %{public}s faild %{public}d", fileDir.c_str(), result);
450 Rollback(hasMovePaths);
451 return false;
452 }
453
454 result = InstalldClient::GetInstance()->MoveFile(tempPath, targetPath);
455 if (result != ERR_OK) {
456 APP_LOGE("move file to real path failed %{public}d", result);
457 Rollback(hasMovePaths);
458 return false;
459 }
460
461 hasMovePaths.emplace_back(targetPath);
462 }
463
464 return true;
465 }
466
Rollback(const std::string & rootDir,const std::vector<std::string> & names)467 void VerifyManagerHostImpl::Rollback(
468 const std::string &rootDir, const std::vector<std::string> &names)
469 {
470 std::vector<std::string> paths;
471 for (const auto &name : names) {
472 paths.emplace_back(rootDir + name);
473 }
474
475 Rollback(paths);
476 }
477
Rollback(const std::vector<std::string> & paths)478 void VerifyManagerHostImpl::Rollback(const std::vector<std::string> &paths)
479 {
480 for (const auto &abcPath : paths) {
481 auto result = BundleUtil::DeleteDir(abcPath);
482 if (result != ERR_OK) {
483 APP_LOGE("move file to real path failed %{public}d", result);
484 }
485 }
486 }
487
DeleteAbc(const std::string & path)488 ErrCode VerifyManagerHostImpl::DeleteAbc(const std::string &path)
489 {
490 if (!BundlePermissionMgr::IsSystemApp() &&
491 !BundlePermissionMgr::VerifyCallingBundleSdkVersion(ServiceConstants::API_VERSION_TWELVE)) {
492 APP_LOGE("non-system app calling system api");
493 return ERR_BUNDLE_MANAGER_SYSTEM_API_DENIED;
494 }
495
496 if (!BundlePermissionMgr::VerifyCallingPermissionForAll(Constants::PERMISSION_RUN_DYN_CODE)) {
497 APP_LOGE("DeleteAbc failed due to permission denied");
498 return ERR_BUNDLE_MANAGER_VERIFY_PERMISSION_DENIED;
499 }
500 if (!IsValidPath(path)) {
501 APP_LOGE("DeleteAbc failed due to invalid path");
502 return ERR_BUNDLE_MANAGER_DELETE_ABC_PARAM_ERROR;
503 }
504 if (!BundleUtil::CheckFileType(path, ABC_FILE_SUFFIX)) {
505 APP_LOGE("DeleteAbc failed due to not abc file");
506 return ERR_BUNDLE_MANAGER_DELETE_ABC_PARAM_ERROR;
507 }
508 auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
509 if (dataMgr == nullptr) {
510 APP_LOGE("DeleteAbc failed due to dataMgr is null");
511 return ERR_BUNDLE_MANAGER_DELETE_ABC_FAILED;
512 }
513 int32_t callingUid = IPCSkeleton::GetCallingUid();
514 InnerBundleInfo innerBundleInfo;
515 if (dataMgr->GetInnerBundleInfoByUid(callingUid, innerBundleInfo) != ERR_OK) {
516 APP_LOGE("DeleteAbc failed due to get callingUid failed");
517 return ERR_BUNDLE_MANAGER_DELETE_ABC_FAILED;
518 }
519
520 auto &mtx = GetBundleMutex(innerBundleInfo.GetBundleName());
521 std::lock_guard lock {mtx};
522 std::string realPath;
523 realPath.append(Constants::BUNDLE_CODE_DIR).append(ServiceConstants::PATH_SEPARATOR)
524 .append(innerBundleInfo.GetBundleName()).append(ServiceConstants::PATH_SEPARATOR)
525 .append(ABCS_DIR).append(ServiceConstants::PATH_SEPARATOR).append(path);
526 bool isExist = false;
527 auto result = InstalldClient::GetInstance()->IsExistFile(realPath, isExist);
528 if (result != ERR_OK) {
529 APP_LOGE("DeleteAbc %{public}s failed due to call IsExistFile failed %{public}d",
530 realPath.c_str(), result);
531 return ERR_BUNDLE_MANAGER_DELETE_ABC_FAILED;
532 }
533 if (!isExist) {
534 APP_LOGE("DeleteAbc failed due to path %{public}s is not exist", realPath.c_str());
535 return ERR_BUNDLE_MANAGER_DELETE_ABC_FAILED;
536 }
537 result = InstalldClient::GetInstance()->RemoveDir(realPath);
538 if (result != ERR_OK) {
539 APP_LOGE("DeleteAbc failed due to remove path %{public}s failed %{public}d",
540 realPath.c_str(), result);
541 return ERR_BUNDLE_MANAGER_DELETE_ABC_FAILED;
542 }
543 return ERR_OK;
544 }
545
GetBundleMutex(const std::string & bundleName)546 std::mutex &VerifyManagerHostImpl::GetBundleMutex(const std::string &bundleName)
547 {
548 bundleMutex_.lock_shared();
549 auto it = bundleMutexMap_.find(bundleName);
550 if (it == bundleMutexMap_.end()) {
551 bundleMutex_.unlock_shared();
552 std::unique_lock lock {bundleMutex_};
553 return bundleMutexMap_[bundleName];
554 }
555 bundleMutex_.unlock_shared();
556 return it->second;
557 }
558 } // AppExecFwk
559 } // namespace OHOS
560