• 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 "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