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 "bundle_overlay_install_checker.h"
17
18 #include "bundle_overlay_manager.h"
19
20 namespace OHOS {
21 namespace AppExecFwk {
22 namespace {
23 const std::string SHARED_TYPE = "shared";
24 constexpr int32_t OVERLAY_MAXIMUM_PRIORITY = 100;
25 } // namespace
26
CheckOverlayInstallation(std::unordered_map<std::string,InnerBundleInfo> & newInfos,int32_t userId,int32_t & overlayType)27 ErrCode BundleOverlayInstallChecker::CheckOverlayInstallation(
28 std::unordered_map<std::string, InnerBundleInfo> &newInfos, int32_t userId, int32_t &overlayType)
29 {
30 APP_LOGD("Start to check overlay installation");
31 #ifdef BUNDLE_FRAMEWORK_OVERLAY_INSTALLATION
32 if (newInfos.empty()) {
33 return ERR_BUNDLEMANAGER_OVERLAY_QUERY_FAILED_MISSING_OVERLAY_BUNDLE;
34 }
35 bool isInternalOverlayExisted = false;
36 bool isExternalOverlayExisted = false;
37 for (auto &info : newInfos) {
38 info.second.SetUserId(userId);
39 if (info.second.GetOverlayType() == NON_OVERLAY_TYPE) {
40 APP_LOGW("the hap is not overlay hap");
41 continue;
42 }
43 if (isInternalOverlayExisted && isExternalOverlayExisted) {
44 return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_INTERNAL_EXTERNAL_OVERLAY_EXISTED_SIMULTANEOUSLY;
45 }
46 ErrCode result = ERR_OK;
47 if (info.second.GetOverlayType() == OVERLAY_INTERNAL_BUNDLE) {
48 isInternalOverlayExisted = true;
49 result = CheckInternalBundle(newInfos, info.second);
50 }
51 if (info.second.GetOverlayType() == OVERLAY_EXTERNAL_BUNDLE) {
52 isExternalOverlayExisted = true;
53 result = CheckExternalBundle(info.second, userId);
54 }
55 if (result != ERR_OK) {
56 APP_LOGE("check overlay installation failed due to errcode %{public}d", result);
57 return result;
58 }
59 }
60 overlayType = (newInfos.begin()->second).GetOverlayType();
61 APP_LOGD("check overlay installation successfully and overlay type is %{public}d", overlayType);
62 #else
63 APP_LOGD("overlay is not supported");
64 #endif
65 return ERR_OK;
66 }
67
CheckInternalBundle(const std::unordered_map<std::string,InnerBundleInfo> & newInfos,const InnerBundleInfo & innerBundleInfo) const68 ErrCode BundleOverlayInstallChecker::CheckInternalBundle(
69 const std::unordered_map<std::string, InnerBundleInfo> &newInfos,
70 const InnerBundleInfo &innerBundleInfo) const
71 {
72 APP_LOGD("start");
73 // 1. check hap type
74 ErrCode result = CheckHapType(innerBundleInfo);
75 if (result != ERR_OK) {
76 APP_LOGE("check hap type failed");
77 return result;
78 }
79 // 2. check bundle type
80 if ((result = CheckBundleType(innerBundleInfo)) != ERR_OK) {
81 APP_LOGE("check bundle type failed");
82 return result;
83 }
84 // 3. check module target priority range
85 const std::map<std::string, InnerModuleInfo> &innerModuleInfos = innerBundleInfo.GetInnerModuleInfos();
86 if (innerModuleInfos.empty()) {
87 APP_LOGE("no module in the overlay hap");
88 return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_INTERNAL_ERROR;
89 }
90 std::string moduleName = innerBundleInfo.GetCurrentModulePackage();
91 if ((result = CheckTargetPriority(innerModuleInfos.at(moduleName).targetPriority)) != ERR_OK) {
92 APP_LOGE("target priority of module is invalid");
93 return result;
94 }
95 // 4. check TargetModule with moduleName
96 std::string targetModuleName = innerModuleInfos.at(moduleName).targetModuleName;
97 if (targetModuleName == moduleName) {
98 APP_LOGE("target moduleName cannot be same with moudleName");
99 return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_INVALID_MODULE_NAME;
100 }
101 // 5. check target module is non-overlay hap
102 if ((result = CheckTargetModule(innerBundleInfo.GetBundleName(), targetModuleName)) != ERR_OK) {
103 return result;
104 }
105 // 6. check version code, overlay hap has same version code with non-overlay hap
106 if ((result = CheckVersionCode(newInfos, innerBundleInfo)) != ERR_OK) {
107 return result;
108 }
109 APP_LOGD("check internal overlay installation successfully");
110 return ERR_OK;
111 }
112
CheckExternalBundle(const InnerBundleInfo & innerBundleInfo,int32_t userId) const113 ErrCode BundleOverlayInstallChecker::CheckExternalBundle(const InnerBundleInfo &innerBundleInfo, int32_t userId) const
114 {
115 APP_LOGD("start");
116 // 1. check bundle type
117 ErrCode result = CheckBundleType(innerBundleInfo);
118 if (result != ERR_OK) {
119 APP_LOGE("check bundle type failed");
120 return result;
121 }
122
123 result = CheckHapType(innerBundleInfo);
124 if (result != ERR_OK) {
125 APP_LOGE("check hap type failed");
126 return result;
127 }
128
129 // 2. check priority
130 // 2.1 check bundle priority range
131 // 2.2 check module priority range
132 int32_t priority = innerBundleInfo.GetTargetPriority();
133 if ((result = CheckTargetPriority(priority)) != ERR_OK) {
134 APP_LOGE("check bundle priority failed due to %{public}d", result);
135 return result;
136 }
137
138 const std::map<std::string, InnerModuleInfo> &innerModuleInfos = innerBundleInfo.GetInnerModuleInfos();
139 if (innerModuleInfos.empty()) {
140 APP_LOGE("no module in the overlay hap");
141 return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_INTERNAL_ERROR;
142 }
143 std::string moduleName = innerBundleInfo.GetCurrentModulePackage();
144 priority = innerModuleInfos.at(moduleName).targetPriority;
145 if ((result = CheckTargetPriority(priority)) != ERR_OK) {
146 APP_LOGE("target priority of module is invalid");
147 return result;
148 }
149
150 // 3. bundleName cannot be same with targetBundleName
151 if (innerBundleInfo.GetBundleName() == innerBundleInfo.GetTargetBundleName()) {
152 APP_LOGE("bundleName %{public}s is same with targetBundleName %{public}s",
153 innerBundleInfo.GetBundleName().c_str(), innerBundleInfo.GetTargetBundleName().c_str());
154 return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_BUNDLE_NAME_SAME_WITH_TARGET_BUNDLE_NAME;
155 }
156
157 // 4. overlay hap should be preInstall application
158 if (!innerBundleInfo.IsPreInstallApp()) {
159 APP_LOGE("no preInstall application for external overlay installation");
160 return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_NO_SYSTEM_APPLICATION_FOR_EXTERNAL_OVERLAY;
161 }
162
163 // 5. check target bundle
164 std::string targetModuleName = innerModuleInfos.at(moduleName).targetModuleName;
165 std::string fingerprint = innerBundleInfo.GetCertificateFingerprint();
166 if ((result =
167 CheckTargetBundle(innerBundleInfo.GetTargetBundleName(), targetModuleName, fingerprint, userId)) != ERR_OK) {
168 APP_LOGE("check target bundle failed");
169 return result;
170 }
171 APP_LOGD("check external overlay installation successfully");
172 return ERR_OK;
173 }
174
CheckHapType(const InnerBundleInfo & info) const175 ErrCode BundleOverlayInstallChecker::CheckHapType(const InnerBundleInfo &info) const
176 {
177 std::string currentPackageName = info.GetCurrentModulePackage();
178 APP_LOGD("current package is %{public}s", currentPackageName.c_str());
179 if (info.GetModuleTypeByPackage(currentPackageName) != SHARED_TYPE) {
180 APP_LOGE("overlay hap only support shared entry hap in internal overlay installation");
181 return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_ERROR_HAP_TYPE;
182 }
183 return ERR_OK;
184 }
185
CheckBundleType(const InnerBundleInfo & info) const186 ErrCode BundleOverlayInstallChecker::CheckBundleType(const InnerBundleInfo &info) const
187 {
188 if (info.GetEntryInstallationFree()) {
189 APP_LOGE("overlay hap cannot be service type");
190 return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_ERROR_BUNDLE_TYPE;
191 }
192 return ERR_OK;
193 }
194
CheckTargetPriority(int32_t priority) const195 ErrCode BundleOverlayInstallChecker::CheckTargetPriority(int32_t priority) const
196 {
197 APP_LOGD("start");
198 if ((priority < ServiceConstants::OVERLAY_MINIMUM_PRIORITY) || (priority > OVERLAY_MAXIMUM_PRIORITY)) {
199 APP_LOGE("overlay hap has invalid module priority %{public}d", priority);
200 return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_INVALID_PRIORITY;
201 }
202 return ERR_OK;
203 }
204
CheckVersionCode(const std::unordered_map<std::string,InnerBundleInfo> & newInfos,const InnerBundleInfo & info) const205 ErrCode BundleOverlayInstallChecker::CheckVersionCode(
206 const std::unordered_map<std::string, InnerBundleInfo> &newInfos,
207 const InnerBundleInfo &info) const
208 {
209 APP_LOGD("start to check version code");
210 for (const auto &innerBundleInfo : newInfos) {
211 if (!innerBundleInfo.second.isOverlayModule(innerBundleInfo.second.GetCurrentModulePackage())) {
212 return ERR_OK;
213 }
214 }
215
216 std::string bundleName = info.GetBundleName();
217 InnerBundleInfo oldInfo;
218 ErrCode result = ERR_OK;
219 auto isExisted = BundleOverlayManager::GetInstance()->GetInnerBundleInfo(bundleName, oldInfo);
220 auto isNonOverlayHapExisted = BundleOverlayManager::GetInstance()->IsExistedNonOverlayHap(bundleName);
221 if (isExisted) {
222 if (isNonOverlayHapExisted && (info.GetVersionCode() != oldInfo.GetVersionCode())) {
223 APP_LOGE("overlay hap needs has same version code with current bundle");
224 result = ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_INCONSISTENT_VERSION_CODE;
225 }
226 }
227 return result;
228 }
229
CheckTargetBundle(const std::string & targetBundleName,const std::string & targetModuleName,const std::string & fingerprint,int32_t userId) const230 ErrCode BundleOverlayInstallChecker::CheckTargetBundle(const std::string &targetBundleName,
231 const std::string &targetModuleName, const std::string &fingerprint, int32_t userId) const
232 {
233 APP_LOGD("start");
234 if (targetBundleName.empty()) {
235 APP_LOGE("invalid target bundle name");
236 return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_INVALID_BUNDLE_NAME;
237 }
238 InnerBundleInfo oldInfo;
239 if (!BundleOverlayManager::GetInstance()->GetInnerBundleInfo(targetBundleName, oldInfo)) {
240 APP_LOGW("target bundle is not installed");
241 return ERR_OK;
242 }
243 // 1. check target bundle is not external overlay bundle
244 if (oldInfo.GetOverlayType() == OVERLAY_EXTERNAL_BUNDLE) {
245 APP_LOGE("target bundle is cannot be external overlay bundle");
246 return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_TARGET_BUNDLE_IS_OVERLAY_BUNDLE;
247 }
248 // 2. check target bundle is system application
249 if (!oldInfo.IsPreInstallApp()) {
250 APP_LOGE("target bundle is not preInstall application");
251 return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_NO_SYSTEM_APPLICATION_FOR_EXTERNAL_OVERLAY;
252 }
253
254 // 3. check fingerprint of current bundle with target bundle
255 if (oldInfo.GetCertificateFingerprint() != fingerprint) {
256 APP_LOGE("target bundle has different fingerprint with current bundle");
257 return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_DIFFERENT_SIGNATURE_CERTIFICATE;
258 }
259
260 // 4. check target module is non-overlay hap
261 auto result = CheckTargetModule(targetBundleName, targetModuleName);
262 if (result != ERR_OK) {
263 return result;
264 }
265
266 // 5. check target bundle is not fa module
267 if (!oldInfo.GetIsNewVersion()) {
268 APP_LOGE("target bundle is not stage model");
269 return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_TARGET_BUNDLE_IS_NOT_STAGE_MODULE;
270 }
271 // 6. check target bundle is not service
272 if (CheckBundleType(oldInfo) != ERR_OK) {
273 APP_LOGE("target bundle is service");
274 return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_TARGET_BUNDLE_IS_SERVICE;
275 }
276 return ERR_OK;
277 }
278
CheckTargetModule(const std::string & bundleName,const std::string & targetModuleName) const279 ErrCode BundleOverlayInstallChecker::CheckTargetModule(const std::string &bundleName,
280 const std::string &targetModuleName) const
281 {
282 InnerBundleInfo oldInfo;
283 if (BundleOverlayManager::GetInstance()->GetInnerBundleInfo(bundleName, oldInfo)) {
284 if (oldInfo.FindModule(targetModuleName) && oldInfo.isOverlayModule(targetModuleName)) {
285 APP_LOGE("check target module failed");
286 return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_TARGET_MODULE_IS_OVERLAY_MODULE;
287 }
288 }
289 return ERR_OK;
290 }
291
CheckOverlayUpdate(const InnerBundleInfo & oldInfo,const InnerBundleInfo & newInfo,int32_t userId) const292 ErrCode BundleOverlayInstallChecker::CheckOverlayUpdate(const InnerBundleInfo &oldInfo, const InnerBundleInfo &newInfo,
293 int32_t userId) const
294 {
295 #ifdef BUNDLE_FRAMEWORK_OVERLAY_INSTALLATION
296 if (((newInfo.GetOverlayType() == OVERLAY_EXTERNAL_BUNDLE) &&
297 (oldInfo.GetOverlayType() != OVERLAY_EXTERNAL_BUNDLE)) ||
298 ((oldInfo.GetOverlayType() == OVERLAY_EXTERNAL_BUNDLE) &&
299 (newInfo.GetOverlayType() != OVERLAY_EXTERNAL_BUNDLE))) {
300 APP_LOGE("external overlay cannot update non-external overlay application");
301 return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_OVERLAY_TYPE_NOT_SAME;
302 }
303
304 std::string newModuleName = newInfo.GetCurrentModulePackage();
305 if (!oldInfo.FindModule(newModuleName)) {
306 return ERR_OK;
307 }
308 if ((newInfo.GetOverlayType() != NON_OVERLAY_TYPE) && (!oldInfo.isOverlayModule(newModuleName))) {
309 APP_LOGE("old module is non-overlay hap and new module is overlay hap");
310 return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_OVERLAY_TYPE_NOT_SAME;
311 }
312
313 if ((newInfo.GetOverlayType() == NON_OVERLAY_TYPE) && (oldInfo.isOverlayModule(newModuleName))) {
314 APP_LOGE("old module is overlay hap and new module is non-overlay hap");
315 return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_OVERLAY_TYPE_NOT_SAME;
316 }
317 #else
318 APP_LOGD("overlay is not supported");
319 #endif
320 return ERR_OK;
321 }
322 } // AppExecFwk
323 } // OHOS