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