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