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 #include "bundle_mgr_interface.h"
18 #include "iservice_registry.h"
19
20 #include <cstring>
21 #include "securec.h"
22
23 #include "accesstoken_kit.h"
24 #include "app_provision_info.h"
25 #include "bundle_mgr_client.h"
26 #include "bundle_mgr_interface.h"
27 #include "hap_token_info.h"
28 #include "ipc_skeleton.h"
29 #include "iservice_registry.h"
30
31 #include "asset_type.h"
32 #include "asset_log.h"
33
34 using namespace OHOS;
35 using namespace AppExecFwk;
36 using namespace Security::AccessToken;
37
38 namespace {
39 constexpr int BUNDLE_MGR_SERVICE_SYS_ABILITY_ID = 401;
40
41 const char * const UPGRADE_HAP_LIST[] = ASSET_UPGRADE_HAP_CONFIG;
42
AssetMemCmp(const void * ptr1,const void * ptr2,uint32_t size1,uint32_t size2)43 bool AssetMemCmp(const void *ptr1, const void *ptr2, uint32_t size1, uint32_t size2)
44 {
45 if (size1 != size2) {
46 return false;
47 }
48 return memcmp(ptr1, ptr2, size1) == EOK;
49 }
50
GetBundleMgr()51 sptr<IBundleMgr> GetBundleMgr()
52 {
53 auto systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
54 if (systemAbilityManager == nullptr) {
55 LOGE("[FATAL]systemAbilityManager is nullptr, please check.");
56 return nullptr;
57 }
58 auto bundleMgrRemoteObj = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
59 if (bundleMgrRemoteObj == nullptr) {
60 LOGE("[FATAL]bundleMgrRemoteObj is nullptr, please check.");
61 return nullptr;
62 }
63 return iface_cast<IBundleMgr>(bundleMgrRemoteObj);
64 }
65
GetBundleNameAndAppIndex(sptr<IBundleMgr> bundleMgr,uint64_t uid,ProcessInfo * processInfo)66 int32_t GetBundleNameAndAppIndex(sptr<IBundleMgr> bundleMgr, uint64_t uid, ProcessInfo *processInfo)
67 {
68 int32_t appIndex = 0;
69 std::string bundleName;
70 int32_t ret = bundleMgr->GetNameAndIndexForUid(uid, bundleName, appIndex);
71 if (ret != RET_SUCCESS) {
72 LOGE("[FATAL]GetNameAndIndexForUid get bundleName and appIndex failed. ret:%{public}d", ret);
73 return ASSET_BMS_ERROR;
74 }
75
76 processInfo->hapInfo.appIndex = appIndex;
77 if (memcpy_s(processInfo->processName.data, processInfo->processName.size, bundleName.c_str(), bundleName.size())
78 != EOK) {
79 LOGE("[FATAL]The processName buffer is too small. Expect size: %{public}zu, actual size: %{public}u",
80 bundleName.size(), processInfo->processName.size);
81 return ASSET_OUT_OF_MEMORY;
82 }
83 processInfo->processName.size = bundleName.size();
84
85 return ASSET_SUCCESS;
86 }
87
GetBundleInfo(AppExecFwk::BundleMgrClient & bmsClient,uint32_t userId,ProcessInfo * processInfo)88 int32_t GetBundleInfo(AppExecFwk::BundleMgrClient &bmsClient, uint32_t userId, ProcessInfo *processInfo)
89 {
90 AppExecFwk::BundleInfo bundleInfo;
91 std::string bundleName(reinterpret_cast<const char*>(processInfo->processName.data), processInfo->processName.size);
92 if (!bmsClient.GetBundleInfo(bundleName, BundleFlag::GET_BUNDLE_WITH_HASH_VALUE, bundleInfo, userId)) {
93 LOGE("[FATAL]Get bundle info failed!");
94 return ASSET_BMS_ERROR;
95 }
96
97 if (memcpy_s(processInfo->hapInfo.appId.data, processInfo->hapInfo.appId.size, bundleInfo.appId.c_str(),
98 bundleInfo.appId.size()) != EOK) {
99 LOGE("[FATAL]The app id buffer is too small. Expect size: %{public}zu, actual size: %{public}u",
100 bundleInfo.appId.size(), processInfo->hapInfo.appId.size);
101 return ASSET_OUT_OF_MEMORY;
102 }
103 processInfo->hapInfo.appId.size = bundleInfo.appId.size();
104
105 if (processInfo->hapInfo.groupId.data == nullptr || processInfo->hapInfo.groupId.size == 0) {
106 return ASSET_SUCCESS;
107 }
108
109 for (const std::string &groupId : bundleInfo.applicationInfo.assetAccessGroups) {
110 if (groupId.size() <= processInfo->hapInfo.groupId.size &&
111 memcmp(processInfo->hapInfo.groupId.data, groupId.data(), processInfo->hapInfo.groupId.size) == 0) {
112 LOGI("[INFO]Found matching group id.");
113 return ASSET_SUCCESS;
114 }
115 }
116 LOGE("[FATAL]No matching group id found!");
117 return ASSET_INVALID_ARGUMENT;
118 }
119
GetAppProvisionInfo(sptr<IBundleMgr> bundleMgr,uint32_t userId,ProcessInfo * processInfo)120 int32_t GetAppProvisionInfo(sptr<IBundleMgr> bundleMgr, uint32_t userId, ProcessInfo *processInfo)
121 {
122 if (processInfo->hapInfo.developerId.data == nullptr || processInfo->hapInfo.developerId.size == 0) {
123 return ASSET_SUCCESS;
124 }
125
126 AppExecFwk::AppProvisionInfo appProvisionInfo;
127 std::string bundleName(reinterpret_cast<const char*>(processInfo->processName.data), processInfo->processName.size);
128 int32_t ret = bundleMgr->GetAppProvisionInfo(bundleName, userId, appProvisionInfo);
129 if (ret != RET_SUCCESS) {
130 LOGE("[FATAL]Get app provision info failed!");
131 return ASSET_BMS_ERROR;
132 }
133
134 if (memcpy_s(processInfo->hapInfo.developerId.data, processInfo->hapInfo.developerId.size,
135 appProvisionInfo.developerId.c_str(), appProvisionInfo.developerId.size()) != EOK) {
136 LOGE("[FATAL]The developer id buffer is too small. Expect size: %{public}zu, actual size: %{public}u",
137 appProvisionInfo.developerId.size(), processInfo->hapInfo.developerId.size);
138 return ASSET_OUT_OF_MEMORY;
139 }
140 processInfo->hapInfo.developerId.size = appProvisionInfo.developerId.size();
141
142 return ASSET_SUCCESS;
143 }
144
ModifyAppindex(ProcessInfo * processInfo)145 void ModifyAppindex(ProcessInfo *processInfo)
146 {
147 for (uint32_t i = 0; i < ARRAY_SIZE(UPGRADE_HAP_LIST); ++i) {
148 if (AssetMemCmp(UPGRADE_HAP_LIST[i],
149 processInfo->hapInfo.appId.data,
150 strlen(UPGRADE_HAP_LIST[i]),
151 processInfo->hapInfo.appId.size)) {
152 LOGI("[INFO]app: %{public}s appIndex changed to 0", UPGRADE_HAP_LIST[i]);
153 processInfo->hapInfo.appIndex = 0;
154 return;
155 }
156 }
157 }
158
GetHapProcessInfo(uint32_t userId,uint64_t uid,ProcessInfo * processInfo)159 int32_t GetHapProcessInfo(uint32_t userId, uint64_t uid, ProcessInfo *processInfo)
160 {
161 auto bundleMgr = GetBundleMgr();
162 if (bundleMgr == nullptr) {
163 LOGE("[FATAL]bundleMgr is nullptr, please check.");
164 return ASSET_BMS_ERROR;
165 }
166 AppExecFwk::BundleMgrClient bmsClient;
167
168 int32_t ret = GetBundleNameAndAppIndex(bundleMgr, uid, processInfo);
169 if (ret != ASSET_SUCCESS) {
170 return ret;
171 }
172
173 ret = GetBundleInfo(bmsClient, userId, processInfo);
174 if (ret != ASSET_SUCCESS) {
175 return ret;
176 }
177
178 ModifyAppindex(processInfo);
179
180 return GetAppProvisionInfo(bundleMgr, userId, processInfo);
181 }
182
GetNativeProcessInfo(uint32_t tokenId,uint64_t uid,ProcessInfo * processInfo)183 int32_t GetNativeProcessInfo(uint32_t tokenId, uint64_t uid, ProcessInfo *processInfo)
184 {
185 NativeTokenInfo nativeTokenInfo;
186 int32_t ret = AccessTokenKit::GetNativeTokenInfo(tokenId, nativeTokenInfo);
187 if (ret != RET_SUCCESS) {
188 LOGE("[FATAL]Get native token info failed, ret = %{public}d", ret);
189 return ASSET_ACCESS_TOKEN_ERROR;
190 }
191
192 if (memcpy_s(processInfo->processName.data, processInfo->processName.size, nativeTokenInfo.processName.c_str(),
193 nativeTokenInfo.processName.size()) != EOK) {
194 LOGE("[FATAL]The processName buffer is too small. Expect size: %{public}zu, actual size: %{public}u",
195 nativeTokenInfo.processName.size(), processInfo->processName.size);
196 return ASSET_OUT_OF_MEMORY;
197 }
198 processInfo->processName.size = nativeTokenInfo.processName.size();
199 processInfo->nativeInfo.uid = uid;
200
201 return ASSET_SUCCESS;
202 }
203 } // namespace
204
GetCallingProcessInfo(uint32_t userId,uint64_t uid,ProcessInfo * processInfo)205 int32_t GetCallingProcessInfo(uint32_t userId, uint64_t uid, ProcessInfo *processInfo)
206 {
207 processInfo->userId = userId;
208 auto tokenId = IPCSkeleton::GetCallingTokenID();
209 ATokenTypeEnum tokenType = AccessTokenKit::GetTokenTypeFlag(tokenId);
210 int32_t res = ASSET_SUCCESS;
211 switch (tokenType) {
212 case ATokenTypeEnum::TOKEN_HAP:
213 if (processInfo->hapInfo.groupId.data != nullptr) {
214 processInfo->ownerType = HAP_GROUP;
215 } else {
216 processInfo->ownerType = HAP;
217 }
218 res = GetHapProcessInfo(userId, uid, processInfo);
219 break;
220 case ATokenTypeEnum::TOKEN_NATIVE:
221 case ATokenTypeEnum::TOKEN_SHELL:
222 processInfo->ownerType = NATIVE;
223 res = GetNativeProcessInfo(tokenId, uid, processInfo);
224 break;
225 default:
226 LOGE("[FATAL]Invalid calling type: %{public}d", tokenType);
227 res = ASSET_INVALID_ARGUMENT;
228 }
229 return res;
230 }