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