• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <fcntl.h>
19 #include <unistd.h>
20 
21 #include "app_log_wrapper.h"
22 #include "appexecfwk_errors.h"
23 #include "bundle_mgr_service.h"
24 #include "bundle_permission_mgr.h"
25 #include "bundle_util.h"
26 #include "installd_client.h"
27 #include "ipc_skeleton.h"
28 #include "verify_util.h"
29 
30 namespace OHOS {
31 namespace AppExecFwk {
32 namespace {
33 const std::string SEPARATOR = "/";
34 const std::string ABCS_DIR = "abcs";
35 
IsFileNameValid(const std::string & fileName)36 bool IsFileNameValid(const std::string &fileName)
37 {
38     if (fileName.find("..") != std::string::npos
39         || fileName.find("/") != std::string::npos
40         || fileName.find("\\") != std::string::npos
41         || fileName.find("%") != std::string::npos) {
42         return false;
43     }
44     return true;
45 }
46 
IsValidPath(const std::string & path)47 bool IsValidPath(const std::string &path)
48 {
49     if (path.empty()) {
50         return false;
51     }
52     if (path.find("..") != std::string::npos) {
53         return false;
54     }
55     return true;
56 }
57 }
VerifyManagerHostImpl()58 VerifyManagerHostImpl::VerifyManagerHostImpl()
59 {
60     APP_LOGI("create VerifyManagerHostImpl.");
61 }
62 
~VerifyManagerHostImpl()63 VerifyManagerHostImpl::~VerifyManagerHostImpl()
64 {
65     APP_LOGI("destroy VerifyManagerHostImpl.");
66 }
67 
Verify(const std::vector<std::string> & abcPaths,const std::vector<std::string> & abcNames,bool flag)68 ErrCode VerifyManagerHostImpl::Verify(const std::vector<std::string> &abcPaths,
69     const std::vector<std::string> &abcNames, bool flag)
70 {
71     ErrCode ret = InnerVerify(abcPaths, abcNames, flag);
72     RemoveTempFiles(abcPaths);
73     return ret;
74 }
75 
InnerVerify(const std::vector<std::string> & abcPaths,const std::vector<std::string> & abcNames,bool flag)76 ErrCode VerifyManagerHostImpl::InnerVerify(const std::vector<std::string> &abcPaths,
77     const std::vector<std::string> &abcNames, bool flag)
78 {
79     if (!BundlePermissionMgr::VerifyCallingPermissionForAll(Constants::PERMISSION_RUN_DYN_CODE)) {
80         APP_LOGE("verify install permission failed.");
81         return ERR_BUNDLE_MANAGER_VERIFY_PERMISSION_DENIED;
82     }
83 
84     if (!CheckFileParam(abcPaths, abcNames)) {
85         APP_LOGE("CheckFile failed.");
86         return ERR_BUNDLE_MANAGER_VERIFY_PARAM_ERROR;
87     }
88 
89     auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
90     if (dataMgr == nullptr) {
91         APP_LOGE("verify failed, dataMgr is null");
92         return ERR_BUNDLE_MANAGER_VERIFY_VERIFY_ABC_FAILED;
93     }
94 
95     int32_t callingUid = IPCSkeleton::GetCallingUid();
96     InnerBundleInfo innerBundleInfo;
97     if (dataMgr->GetInnerBundleInfoByUid(callingUid, innerBundleInfo) != ERR_OK) {
98         APP_LOGE("verify failed, callingUid is %{public}d", callingUid);
99         return ERR_BUNDLE_MANAGER_VERIFY_VERIFY_ABC_FAILED;
100     }
101 
102     std::string rootDir;
103     rootDir.append(Constants::BUNDLE_CODE_DIR).append(Constants::PATH_SEPARATOR)
104         .append(innerBundleInfo.GetBundleName()).append(Constants::PATH_SEPARATOR)
105         .append(ABCS_DIR).append(Constants::PATH_SEPARATOR);
106     if (!MoveAbc(abcPaths, abcNames, rootDir)) {
107         APP_LOGE("move abc failed.");
108         return ERR_BUNDLE_MANAGER_VERIFY_VERIFY_ABC_FAILED;
109     }
110 
111     if (!VerifyAbc(rootDir, abcNames)) {
112         APP_LOGE("verify abc failed.");
113         Rollback(rootDir, abcNames);
114         return ERR_BUNDLE_MANAGER_VERIFY_VERIFY_ABC_FAILED;
115     }
116 
117     APP_LOGI("verify abc success.");
118     return ERR_OK;
119 }
120 
CheckFileParam(const std::vector<std::string> & abcPaths,const std::vector<std::string> & abcNames)121 bool VerifyManagerHostImpl::CheckFileParam(
122     const std::vector<std::string> &abcPaths, const std::vector<std::string> &abcNames)
123 {
124     if (abcPaths.empty() || abcNames.empty()) {
125         APP_LOGE("CheckFile abcPath failed due to abcPaths or abcNames is empty");
126         return false;
127     }
128 
129     for (const auto &abcPath : abcPaths) {
130         if (!IsValidPath(abcPath)) {
131             APP_LOGE("CheckFile abcPath(%{public}s) failed due to invalid path", abcPath.c_str());
132             return false;
133         }
134         if (!BundleUtil::CheckFileType(abcPath, Constants::ABC_FILE_SUFFIX)) {
135             APP_LOGE("CheckFile abcPath(%{public}s) failed due to not abc suffix.", abcPath.c_str());
136             return false;
137         }
138         if (!BundleUtil::StartWith(abcPath, Constants::HAP_COPY_PATH)) {
139             APP_LOGE("CheckFile abcPath(%{public}s) failed due to prefix error.", abcPath.c_str());
140             return false;
141         }
142     }
143 
144     for (const auto abcName : abcNames) {
145         if (!IsValidPath(abcName)) {
146             APP_LOGE("CheckFile abcName(%{public}s) failed due to invalid path", abcName.c_str());
147             return false;
148         }
149         if (!BundleUtil::CheckFileType(abcName, Constants::ABC_FILE_SUFFIX)) {
150             APP_LOGE("CheckFile abcName(%{public}s) failed due to not abc suffix.", abcName.c_str());
151             return false;
152         }
153     }
154 
155     return true;
156 }
157 
VerifyAbc(const std::string & rootDir,const std::vector<std::string> & names)158 bool VerifyManagerHostImpl::VerifyAbc(
159     const std::string &rootDir, const std::vector<std::string> &names)
160 {
161     std::vector<std::string> paths;
162     for (const auto &name : names) {
163         paths.emplace_back(rootDir + name);
164     }
165 
166     return VerifyAbc(paths);
167 }
168 
VerifyAbc(const std::vector<std::string> & abcPaths)169 bool VerifyManagerHostImpl::VerifyAbc(const std::vector<std::string> &abcPaths)
170 {
171     for (const auto &abcPath : abcPaths) {
172         if (!BundleUtil::IsExistFile(abcPath)) {
173             APP_LOGE("abcPath is not exist: %{public}s.", abcPath.c_str());
174             return false;
175         }
176 
177         if (!VerifyUtil::VerifyAbc(abcPath)) {
178             APP_LOGE("verify abc failed.");
179             return false;
180         }
181     }
182 
183     return true;
184 }
185 
RemoveTempFiles(const std::vector<std::string> & paths)186 void VerifyManagerHostImpl::RemoveTempFiles(const std::vector<std::string> &paths)
187 {
188     APP_LOGI("RemoveTempFiles.");
189     for (const auto &path : paths) {
190         if (!BundleUtil::DeleteDir(path)) {
191             APP_LOGW("RemoveFile %{private}s failed.", path.c_str());
192         }
193     }
194 }
195 
GetFileName(const std::string & sourcePath,std::string & fileName)196 bool VerifyManagerHostImpl::GetFileName(const std::string &sourcePath, std::string &fileName)
197 {
198     size_t pos = sourcePath.find_last_of(SEPARATOR);
199     if (pos == std::string::npos) {
200         APP_LOGE("invalid sourcePath.");
201         return false;
202     }
203 
204     fileName = sourcePath.substr(pos + 1);
205     return !fileName.empty();
206 }
207 
GetFileDir(const std::string & sourcePath,std::string & fileDir)208 bool VerifyManagerHostImpl::GetFileDir(const std::string &sourcePath, std::string &fileDir)
209 {
210     size_t pos = sourcePath.find_last_of(SEPARATOR);
211     if (pos == std::string::npos) {
212         APP_LOGE("invalid sourcePath.");
213         return false;
214     }
215 
216     fileDir = sourcePath.substr(0, pos);
217     return !fileDir.empty();
218 }
219 
MkdirIfNotExist(const std::string & dir)220 ErrCode VerifyManagerHostImpl::MkdirIfNotExist(const std::string &dir)
221 {
222     bool isDirExist = false;
223     ErrCode result = InstalldClient::GetInstance()->IsExistDir(dir, isDirExist);
224     if (result != ERR_OK) {
225         APP_LOGE("Check if dir exist failed %{public}d", result);
226         return result;
227     }
228 
229     if (!isDirExist) {
230         result = InstalldClient::GetInstance()->CreateBundleDir(dir);
231         if (result != ERR_OK) {
232             APP_LOGE("Create dir failed %{public}d", result);
233             return result;
234         }
235     }
236     return result;
237 }
238 
MoveAbc(const std::vector<std::string> & abcPaths,const std::vector<std::string> & abcNames,const std::string & rootDir)239 bool VerifyManagerHostImpl::MoveAbc(const std::vector<std::string> &abcPaths,
240     const std::vector<std::string> &abcNames, const std::string &rootDir)
241 {
242     if (abcPaths.size() != abcNames.size()) {
243         APP_LOGE("The number %{public}zu of abcPaths is different from that of abcNames",
244             abcPaths.size());
245         return false;
246     }
247 
248     std::vector<std::string> hasMovePaths;
249     ErrCode result = ERR_OK;
250     for (size_t i = 0; i < abcPaths.size(); ++i) {
251         std::string targetPath = rootDir + abcNames[i];
252         std::string fileDir;
253         if (!GetFileDir(targetPath, fileDir)) {
254             APP_LOGE("GetFileDir failed %{public}s", targetPath.c_str());
255             Rollback(hasMovePaths);
256             return false;
257         }
258 
259         result = MkdirIfNotExist(fileDir);
260         if (result != ERR_OK) {
261             APP_LOGE("mkdir fileDir %{public}s faild %{public}d", fileDir.c_str(), result);
262             Rollback(hasMovePaths);
263             return false;
264         }
265 
266         result = InstalldClient::GetInstance()->MoveFile(abcPaths[i], targetPath);
267         if (result != ERR_OK) {
268             APP_LOGE("move file to real path failed %{public}d", result);
269             Rollback(hasMovePaths);
270             return false;
271         }
272 
273         hasMovePaths.emplace_back(targetPath);
274     }
275 
276     return true;
277 }
278 
Rollback(const std::string & rootDir,const std::vector<std::string> & names)279 void VerifyManagerHostImpl::Rollback(
280     const std::string &rootDir, const std::vector<std::string> &names)
281 {
282     std::vector<std::string> paths;
283     for (const auto &name : names) {
284         paths.emplace_back(rootDir + name);
285     }
286 
287     Rollback(paths);
288 }
289 
Rollback(const std::vector<std::string> & paths)290 void VerifyManagerHostImpl::Rollback(const std::vector<std::string> &paths)
291 {
292     for (const auto &abcPath : paths) {
293         std::string targetPath;
294         auto result = InstalldClient::GetInstance()->MoveFile(abcPath, targetPath);
295         if (result != ERR_OK) {
296             APP_LOGE("move file to real path failed %{public}d", result);
297         }
298     }
299 }
300 
CreateFd(const std::string & fileName,int32_t & fd,std::string & path)301 ErrCode VerifyManagerHostImpl::CreateFd(const std::string &fileName, int32_t &fd, std::string &path)
302 {
303     if (!BundlePermissionMgr::VerifyCallingPermissionForAll(Constants::PERMISSION_RUN_DYN_CODE)) {
304         APP_LOGE("verify install permission failed.");
305         return ERR_BUNDLE_MANAGER_VERIFY_PERMISSION_DENIED;
306     }
307 
308     if (!BundleUtil::CheckFileType(fileName, Constants::ABC_FILE_SUFFIX)) {
309         APP_LOGE("not abc file.");
310         return ERR_BUNDLE_MANAGER_VERIFY_PARAM_ERROR;
311     }
312 
313     if (!IsFileNameValid(fileName)) {
314         APP_LOGE("invalid fileName");
315         return ERR_BUNDLE_MANAGER_VERIFY_PARAM_ERROR;
316     }
317 
318     std::string tmpDir = BundleUtil::CreateInstallTempDir(++id_, DirType::ABC_FILE_DIR);
319     if (tmpDir.empty()) {
320         APP_LOGE("create tmp dir failed.");
321         return ERR_BUNDLE_MANAGER_VERIFY_CREATE_TARGET_DIR_FAILED;
322     }
323 
324     path = tmpDir + fileName;
325     if ((fd = BundleUtil::CreateFileDescriptor(path, 0)) < 0) {
326         APP_LOGE("create file descriptor failed.");
327         BundleUtil::DeleteDir(tmpDir);
328         return ERR_BUNDLE_MANAGER_VERIFY_CREATE_FD_FAILED;
329     }
330     return ERR_OK;
331 }
332 
DeleteAbc(const std::string & path)333 ErrCode VerifyManagerHostImpl::DeleteAbc(const std::string &path)
334 {
335     if (!BundlePermissionMgr::VerifyCallingPermissionForAll(Constants::PERMISSION_RUN_DYN_CODE)) {
336         APP_LOGE("DeleteAbc failed due to permission denied.");
337         return ERR_BUNDLE_MANAGER_VERIFY_PERMISSION_DENIED;
338     }
339     if (!IsValidPath(path)) {
340         APP_LOGE("DeleteAbc failed due to invalid path");
341         return ERR_BUNDLE_MANAGER_DELETE_ABC_PARAM_ERROR;
342     }
343     if (!BundleUtil::CheckFileType(path, Constants::ABC_FILE_SUFFIX)) {
344         APP_LOGE("DeleteAbc failed due to not abc file.");
345         return ERR_BUNDLE_MANAGER_DELETE_ABC_PARAM_ERROR;
346     }
347     auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
348     if (dataMgr == nullptr) {
349         APP_LOGE("DeleteAbc failed due to dataMgr is null");
350         return ERR_BUNDLE_MANAGER_DELETE_ABC_FAILED;
351     }
352     int32_t callingUid = IPCSkeleton::GetCallingUid();
353     InnerBundleInfo innerBundleInfo;
354     if (dataMgr->GetInnerBundleInfoByUid(callingUid, innerBundleInfo) != ERR_OK) {
355         APP_LOGE("DeleteAbc failed due to get callingUid failed");
356         return ERR_BUNDLE_MANAGER_DELETE_ABC_FAILED;
357     }
358     std::string realPath;
359     realPath.append(Constants::BUNDLE_CODE_DIR).append(Constants::PATH_SEPARATOR)
360         .append(innerBundleInfo.GetBundleName()).append(Constants::PATH_SEPARATOR)
361         .append(ABCS_DIR).append(Constants::PATH_SEPARATOR).append(path);
362     bool isExist = false;
363     auto result = InstalldClient::GetInstance()->IsExistFile(realPath, isExist);
364     if (result != ERR_OK) {
365         APP_LOGE("DeleteAbc %{public}s failed due to call IsExistFile failed %{public}d",
366             realPath.c_str(), result);
367         return ERR_BUNDLE_MANAGER_DELETE_ABC_FAILED;
368     }
369     if (!isExist) {
370         APP_LOGE("DeleteAbc failed due to path %{public}s is not exist", realPath.c_str());
371         return ERR_BUNDLE_MANAGER_DELETE_ABC_FAILED;
372     }
373     result = InstalldClient::GetInstance()->RemoveDir(realPath);
374     if (result != ERR_OK) {
375         APP_LOGE("DeleteAbc failed due to remove path %{public}s failed %{public}d",
376             realPath.c_str(), result);
377         return ERR_BUNDLE_MANAGER_DELETE_ABC_FAILED;
378     }
379     return ERR_OK;
380 }
381 } // AppExecFwk
382 } // namespace OHOS
383