• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2024 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 "bms_wrapper.h"
17 
18 #include <cstring>
19 #include "securec.h"
20 
21 #include "accesstoken_kit.h"
22 #include "app_provision_info.h"
23 #include "bundle_mgr_client.h"
24 #include "bundle_mgr_interface.h"
25 #include "hap_token_info.h"
26 #include "ipc_skeleton.h"
27 #include "iservice_registry.h"
28 
29 #include "asset_type.h"
30 #include "asset_log.h"
31 #include "system_event_wrapper.h"
32 
33 using namespace OHOS;
34 using namespace AppExecFwk;
35 using namespace Security::AccessToken;
36 
37 namespace {
38 constexpr int BUNDLE_MGR_SERVICE_SYS_ABILITY_ID = 401;
39 
40 const char * const UPGRADE_HAP_LIST[] = ASSET_UPGRADE_HAP_CONFIG;
41 
AssetMemCmp(const void * ptr1,const void * ptr2,uint32_t size1,uint32_t size2)42 bool AssetMemCmp(const void *ptr1, const void *ptr2, uint32_t size1, uint32_t size2)
43 {
44     if (size1 != size2) {
45         return false;
46     }
47     return memcmp(ptr1, ptr2, size1) == EOK;
48 }
49 
GetBundleMgr()50 sptr<IBundleMgr> GetBundleMgr()
51 {
52     auto systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
53     if (systemAbilityManager == nullptr) {
54         LOGE("[FATAL]systemAbilityManager is nullptr, please check.");
55         return nullptr;
56     }
57     auto bundleMgrRemoteObj = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
58     if (bundleMgrRemoteObj == nullptr) {
59         LOGE("[FATAL]bundleMgrRemoteObj is nullptr, please check.");
60         return nullptr;
61     }
62     return iface_cast<IBundleMgr>(bundleMgrRemoteObj);
63 }
64 
GetBundleNameAndAppIndex(sptr<IBundleMgr> bundleMgr,uint64_t uid,ProcessInfo * processInfo)65 int32_t GetBundleNameAndAppIndex(sptr<IBundleMgr> bundleMgr, uint64_t uid, ProcessInfo *processInfo)
66 {
67     int32_t appIndex = 0;
68     std::string bundleName;
69     int32_t ret = bundleMgr->GetNameAndIndexForUid(uid, bundleName, appIndex);
70     if (ret != RET_SUCCESS) {
71         LOGE("[FATAL]GetNameAndIndexForUid get bundleName and appIndex failed. ret:%{public}d", ret);
72         return ASSET_BMS_ERROR;
73     }
74 
75     processInfo->hapInfo.appIndex = appIndex;
76     if (memcpy_s(processInfo->processName.data, processInfo->processName.size, bundleName.c_str(), bundleName.size())
77         != EOK) {
78         LOGE("[FATAL]The processName buffer is too small. Expect size: %{public}zu, actual size: %{public}u",
79             bundleName.size(), processInfo->processName.size);
80         return ASSET_OUT_OF_MEMORY;
81     }
82     processInfo->processName.size = bundleName.size();
83 
84     return ASSET_SUCCESS;
85 }
86 
GetBundleInfo(AppExecFwk::BundleMgrClient & bmsClient,uint32_t userId,ProcessInfo * processInfo)87 int32_t GetBundleInfo(AppExecFwk::BundleMgrClient &bmsClient, uint32_t userId, ProcessInfo *processInfo)
88 {
89     AppExecFwk::BundleInfo bundleInfo;
90     std::string bundleName(reinterpret_cast<const char*>(processInfo->processName.data), processInfo->processName.size);
91     if (!bmsClient.GetBundleInfo(bundleName, BundleFlag::GET_BUNDLE_WITH_HASH_VALUE, bundleInfo, userId)) {
92         LOGE("[FATAL]Get bundle info failed!");
93         return ASSET_BMS_ERROR;
94     }
95 
96     if (memcpy_s(processInfo->hapInfo.appId.data, processInfo->hapInfo.appId.size, bundleInfo.appId.c_str(),
97         bundleInfo.appId.size()) != EOK) {
98         LOGE("[FATAL]The app id buffer is too small. Expect size: %{public}zu, actual size: %{public}u",
99             bundleInfo.appId.size(), processInfo->hapInfo.appId.size);
100         return ASSET_OUT_OF_MEMORY;
101     }
102     processInfo->hapInfo.appId.size = bundleInfo.appId.size();
103 
104     if (processInfo->hapInfo.groupId.data == nullptr || processInfo->hapInfo.groupId.size == 0) {
105         return ASSET_SUCCESS;
106     }
107 
108     for (const std::string &groupId : bundleInfo.applicationInfo.assetAccessGroups) {
109         if (groupId.size() <= processInfo->hapInfo.groupId.size &&
110             memcmp(processInfo->hapInfo.groupId.data, groupId.data(), processInfo->hapInfo.groupId.size) == 0) {
111             LOGI("[INFO]Found matching group id.");
112             return ASSET_SUCCESS;
113         }
114     }
115     LOGE("[FATAL]No matching group id found!");
116     return ASSET_INVALID_ARGUMENT;
117 }
118 
GetAppProvisionInfo(sptr<IBundleMgr> bundleMgr,uint32_t userId,ProcessInfo * processInfo)119 int32_t GetAppProvisionInfo(sptr<IBundleMgr> bundleMgr, uint32_t userId, ProcessInfo *processInfo)
120 {
121     if (processInfo->hapInfo.developerId.data == nullptr || processInfo->hapInfo.developerId.size == 0) {
122         return ASSET_SUCCESS;
123     }
124 
125     AppExecFwk::AppProvisionInfo appProvisionInfo;
126     std::string bundleName(reinterpret_cast<const char*>(processInfo->processName.data), processInfo->processName.size);
127     int32_t ret = bundleMgr->GetAppProvisionInfo(bundleName, userId, appProvisionInfo);
128     if (ret != RET_SUCCESS) {
129         LOGE("[FATAL]Get app provision info failed!");
130         return ASSET_BMS_ERROR;
131     }
132 
133     std::string mainDeveloperId;
134     size_t pos = appProvisionInfo.developerId.find('.');
135     if (pos != std::string::npos) {
136         mainDeveloperId = appProvisionInfo.developerId.substr(pos + 1);
137     } else {
138         mainDeveloperId = appProvisionInfo.developerId;
139     }
140     if (memcpy_s(processInfo->hapInfo.developerId.data, processInfo->hapInfo.developerId.size, mainDeveloperId.c_str(),
141         mainDeveloperId.size()) != EOK) {
142         LOGE("[FATAL]The developer id buffer is too small. Expect size: %{public}zu, actual size: %{public}u",
143             mainDeveloperId.size(), processInfo->hapInfo.developerId.size);
144         return ASSET_OUT_OF_MEMORY;
145     }
146     processInfo->hapInfo.developerId.size = mainDeveloperId.size();
147 
148     return ASSET_SUCCESS;
149 }
150 
GetHapProcessInfo(uint32_t userId,uint64_t uid,ProcessInfo * processInfo)151 int32_t GetHapProcessInfo(uint32_t userId, uint64_t uid, ProcessInfo *processInfo)
152 {
153     auto bundleMgr = GetBundleMgr();
154     if (bundleMgr == nullptr) {
155         LOGE("[FATAL]bundleMgr is nullptr, please check.");
156         return ASSET_BMS_ERROR;
157     }
158     AppExecFwk::BundleMgrClient bmsClient;
159 
160     int32_t ret = GetBundleNameAndAppIndex(bundleMgr, uid, processInfo);
161     if (ret != ASSET_SUCCESS) {
162         return ret;
163     }
164 
165     ret = GetBundleInfo(bmsClient, userId, processInfo);
166     if (ret != ASSET_SUCCESS) {
167         return ret;
168     }
169 
170     return GetAppProvisionInfo(bundleMgr, userId, processInfo);
171 }
172 
GetNativeProcessInfo(uint32_t tokenId,uint64_t uid,ProcessInfo * processInfo)173 int32_t GetNativeProcessInfo(uint32_t tokenId, uint64_t uid, ProcessInfo *processInfo)
174 {
175     NativeTokenInfo nativeTokenInfo;
176     int32_t ret = AccessTokenKit::GetNativeTokenInfo(tokenId, nativeTokenInfo);
177     if (ret != RET_SUCCESS) {
178         LOGE("[FATAL]Get native token info failed, ret = %{public}d", ret);
179         return ASSET_ACCESS_TOKEN_ERROR;
180     }
181 
182     if (memcpy_s(processInfo->processName.data, processInfo->processName.size, nativeTokenInfo.processName.c_str(),
183         nativeTokenInfo.processName.size()) != EOK) {
184         LOGE("[FATAL]The processName buffer is too small. Expect size: %{public}zu, actual size: %{public}u",
185             nativeTokenInfo.processName.size(), processInfo->processName.size);
186         return ASSET_OUT_OF_MEMORY;
187     }
188     processInfo->processName.size = nativeTokenInfo.processName.size();
189     processInfo->nativeInfo.uid = uid;
190 
191     return ASSET_SUCCESS;
192 }
193 
MarkGroupAsModified(const std::string & groupId,MutAssetBlobArray * groupIds)194 void MarkGroupAsModified(const std::string &groupId, MutAssetBlobArray *groupIds)
195 {
196     for (uint32_t i = 0; i < groupIds->size; i++) {
197         if (strcmp(groupId.c_str(), groupIds->blob[i].blob) == 0) {
198             groupIds->blob[i].modify = true;
199             break;
200         }
201     }
202 }
203 
ProcessBundleInfos(const std::vector<AppExecFwk::BundleInfo> & bundleInfos,int32_t userId,MutAssetBlobArray * groupIds)204 void ProcessBundleInfos(const std::vector<AppExecFwk::BundleInfo> &bundleInfos,
205     int32_t userId, MutAssetBlobArray *groupIds)
206 {
207     std::unordered_set<std::string> targetGroupIds;
208     for (uint32_t i = 0; i < groupIds->size; i++) {
209         targetGroupIds.insert(groupIds->blob[i].blob);
210     }
211 
212     for (const AppExecFwk::BundleInfo &bundleInfo : bundleInfos) {
213         for (const std::string &groupId : bundleInfo.applicationInfo.assetAccessGroups) {
214             if (targetGroupIds.find(groupId) != targetGroupIds.end()) {
215                 LOGI("[INFO]Found matching group id. Do not remove data in this group");
216                 MarkGroupAsModified(groupId, groupIds);
217             }
218         }
219     }
220 }
221 } // namespace
222 
GetCallingProcessInfo(uint32_t userId,uint64_t uid,ProcessInfo * processInfo)223 int32_t GetCallingProcessInfo(uint32_t userId, uint64_t uid, ProcessInfo *processInfo)
224 {
225     processInfo->userId = userId;
226     auto tokenId = IPCSkeleton::GetCallingTokenID();
227     ATokenTypeEnum tokenType = AccessTokenKit::GetTokenTypeFlag(tokenId);
228     int32_t res = ASSET_SUCCESS;
229     switch (tokenType) {
230         case ATokenTypeEnum::TOKEN_HAP:
231             if (processInfo->hapInfo.groupId.data != nullptr) {
232                 processInfo->ownerType = HAP_GROUP;
233             } else {
234                 processInfo->ownerType = HAP;
235             }
236             res = GetHapProcessInfo(userId, uid, processInfo);
237             break;
238         case ATokenTypeEnum::TOKEN_NATIVE:
239         case ATokenTypeEnum::TOKEN_SHELL:
240             processInfo->ownerType = NATIVE;
241             res = GetNativeProcessInfo(tokenId, uid, processInfo);
242             break;
243         default:
244             LOGE("[FATAL]Invalid calling type: %{public}d", tokenType);
245             res = ASSET_INVALID_ARGUMENT;
246     }
247     return res;
248 }
249 
GetCloneAppIndexes(int32_t userId,int32_t * appIndexes,uint32_t * indexSize,const char * appName)250 int32_t GetCloneAppIndexes(int32_t userId, int32_t *appIndexes, uint32_t *indexSize, const char *appName)
251 {
252     auto bundleMgr = GetBundleMgr();
253     if (bundleMgr == nullptr) {
254         LOGE("[FATAL]bundleMgr is nullptr, please check.");
255         return ASSET_BMS_ERROR;
256     }
257     std::vector<int32_t> indexes;
258     int32_t ret = bundleMgr->GetCloneAppIndexes(appName, indexes, userId);
259     if (ret != ASSET_SUCCESS) {
260         LOGE("Get clone app indexes failed.");
261         return ASSET_BMS_ERROR;
262     }
263     if (*indexSize < indexes.size()) {
264         LOGE("Too short index size.");
265         return ASSET_INVALID_ARGUMENT;
266     }
267 
268     for (size_t i = 0; i < indexes.size(); i++) {
269         *(appIndexes + i) = indexes[i];
270     }
271     *indexSize = indexes.size();
272     return ASSET_SUCCESS;
273 }
274 
IsHapInAllowList(int32_t userId,const char * appName,bool * is_in_list)275 int32_t IsHapInAllowList(int32_t userId, const char *appName, bool *is_in_list)
276 {
277     if (appName == nullptr) {
278         LOGE("[FATAL]App name is null.");
279         return ASSET_INVALID_ARGUMENT;
280     }
281     AppExecFwk::BundleInfo bundleInfo;
282     AppExecFwk::BundleMgrClient bmsClient;
283     if (!bmsClient.GetBundleInfo(appName, BundleFlag::GET_BUNDLE_WITH_HASH_VALUE, bundleInfo, userId)) {
284         LOGE("[FATAL]Get bundle info failed!");
285         return ASSET_BMS_ERROR;
286     }
287     for (uint32_t i = 0; i < ARRAY_SIZE(UPGRADE_HAP_LIST); ++i) {
288         if (AssetMemCmp(UPGRADE_HAP_LIST[i],
289             bundleInfo.appId.c_str(),
290             strlen(UPGRADE_HAP_LIST[i]),
291             bundleInfo.appId.size())) {
292             *is_in_list = true;
293             return ASSET_SUCCESS;
294         }
295     }
296     *is_in_list = false;
297     return ASSET_SUCCESS;
298 }
299 
GetUninstallGroups(int32_t userId,ConstAssetBlob * developerId,MutAssetBlobArray * groupIds)300 int32_t GetUninstallGroups(int32_t userId, ConstAssetBlob *developerId, MutAssetBlobArray *groupIds)
301 {
302     auto bundleMgr = GetBundleMgr();
303     if (bundleMgr == nullptr) {
304         LOGE("[FATAL]bundleMgr is nullptr, please check.");
305         return ASSET_BMS_ERROR;
306     }
307     std::string useDeveloperId(reinterpret_cast<const char*>(developerId->data), developerId->size);
308     std::vector<AppExecFwk::BundleInfo> bundleInfos;
309     int32_t ret = bundleMgr->GetAllBundleInfoByDeveloperId(useDeveloperId, bundleInfos, userId);
310     if (ret != RET_SUCCESS && ret != ERR_BUNDLE_MANAGER_INVALID_DEVELOPERID) {
311         LOGE("[FATAL]GetAllBundleInfoByDeveloperId failed. ret:%{public}d", ret);
312         return ASSET_BMS_ERROR;
313     }
314 
315     ProcessBundleInfos(bundleInfos, userId, groupIds);
316     return ASSET_SUCCESS;
317 }
318