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_resource_proxy.h"
17
18 #include "securec.h"
19 #include "string_ex.h"
20
21 #include "app_log_wrapper.h"
22 #include "appexecfwk_errors.h"
23 #include "hitrace_meter.h"
24 #include "ipc_types.h"
25 #include "parcel.h"
26 #include "parcel_macro.h"
27
28 namespace OHOS {
29 namespace AppExecFwk {
30 namespace {
31 constexpr size_t MAX_PARCEL_CAPACITY = 1024 * 1024 * 1024; // allow max 1GB resource size
32 constexpr size_t MAX_IPC_ALLOWED_CAPACITY = 100 * 1024 * 1024; // max ipc size 100MB
GetData(void * & buffer,size_t size,const void * data)33 bool GetData(void *&buffer, size_t size, const void *data)
34 {
35 if (data == nullptr) {
36 APP_LOGE("failed due to null data");
37 return false;
38 }
39 if ((size == 0) || size > MAX_PARCEL_CAPACITY) {
40 APP_LOGE("failed due to wrong size");
41 return false;
42 }
43 buffer = malloc(size);
44 if (buffer == nullptr) {
45 APP_LOGE("failed due to malloc buffer failed");
46 return false;
47 }
48 if (memcpy_s(buffer, size, data, size) != EOK) {
49 free(buffer);
50 APP_LOGE("failed due to memcpy_s failed");
51 return false;
52 }
53 return true;
54 }
55 }
56
BundleResourceProxy(const sptr<IRemoteObject> & object)57 BundleResourceProxy::BundleResourceProxy(const sptr<IRemoteObject>& object) : IRemoteProxy<IBundleResource>(object)
58 {}
59
GetBundleResourceInfo(const std::string & bundleName,const uint32_t flags,BundleResourceInfo & bundleResourceInfo,const int32_t appIndex)60 ErrCode BundleResourceProxy::GetBundleResourceInfo(const std::string &bundleName,
61 const uint32_t flags,
62 BundleResourceInfo &bundleResourceInfo,
63 const int32_t appIndex)
64 {
65 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
66 APP_LOGD("start, bundleName:%{public}s, flags:%{public}u", bundleName.c_str(), flags);
67 if (bundleName.empty()) {
68 APP_LOGE("bundleName is empty");
69 return ERR_BUNDLE_MANAGER_PARAM_ERROR;
70 }
71 MessageParcel data;
72 if (!data.WriteInterfaceToken(GetDescriptor())) {
73 APP_LOGE("fail to write InterfaceToken");
74 return ERR_APPEXECFWK_PARCEL_ERROR;
75 }
76 if (!data.WriteString(bundleName)) {
77 APP_LOGE("fail to to write bundleName");
78 return ERR_APPEXECFWK_PARCEL_ERROR;
79 }
80 if (!data.WriteUint32(flags)) {
81 APP_LOGE("fail to write flags");
82 return ERR_APPEXECFWK_PARCEL_ERROR;
83 }
84 if (!data.WriteInt32(appIndex)) {
85 APP_LOGE("fail to write flags");
86 return ERR_APPEXECFWK_PARCEL_ERROR;
87 }
88 return GetParcelInfo<BundleResourceInfo>(
89 BundleResourceInterfaceCode::GET_BUNDLE_RESOURCE_INFO, data, bundleResourceInfo);
90 }
91
GetLauncherAbilityResourceInfo(const std::string & bundleName,const uint32_t flags,std::vector<LauncherAbilityResourceInfo> & launcherAbilityResourceInfo,const int32_t appIndex)92 ErrCode BundleResourceProxy::GetLauncherAbilityResourceInfo(const std::string &bundleName,
93 const uint32_t flags,
94 std::vector<LauncherAbilityResourceInfo> &launcherAbilityResourceInfo,
95 const int32_t appIndex)
96 {
97 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
98 APP_LOGD("start, bundleName:%{public}s, flags:%{public}u", bundleName.c_str(), flags);
99 if (bundleName.empty()) {
100 APP_LOGE("bundleName is empty");
101 return ERR_BUNDLE_MANAGER_PARAM_ERROR;
102 }
103 MessageParcel data;
104 if (!data.WriteInterfaceToken(GetDescriptor())) {
105 APP_LOGE("fail to write InterfaceToken");
106 return ERR_APPEXECFWK_PARCEL_ERROR;
107 }
108 if (!data.WriteString(bundleName)) {
109 APP_LOGE("fail to write bundleName");
110 return ERR_APPEXECFWK_PARCEL_ERROR;
111 }
112 if (!data.WriteUint32(flags)) {
113 APP_LOGE("fail to write flags");
114 return ERR_APPEXECFWK_PARCEL_ERROR;
115 }
116 if (!data.WriteInt32(appIndex)) {
117 APP_LOGE("fail to write appIndex");
118 return ERR_APPEXECFWK_PARCEL_ERROR;
119 }
120
121 return GetVectorParcelInfo<LauncherAbilityResourceInfo>(
122 BundleResourceInterfaceCode::GET_LAUNCHER_ABILITY_RESOURCE_INFO, data, launcherAbilityResourceInfo);
123 }
124
GetAllBundleResourceInfo(const uint32_t flags,std::vector<BundleResourceInfo> & bundleResourceInfos)125 ErrCode BundleResourceProxy::GetAllBundleResourceInfo(const uint32_t flags,
126 std::vector<BundleResourceInfo> &bundleResourceInfos)
127 {
128 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
129 APP_LOGD("start, flags:%{public}u", flags);
130 MessageParcel data;
131 if (!data.WriteInterfaceToken(GetDescriptor())) {
132 APP_LOGE("fail to write InterfaceToken");
133 return ERR_APPEXECFWK_PARCEL_ERROR;
134 }
135 if (!data.WriteUint32(flags)) {
136 APP_LOGE("fail to write flags");
137 return ERR_APPEXECFWK_PARCEL_ERROR;
138 }
139
140 return GetVectorParcelInfo<BundleResourceInfo>(
141 BundleResourceInterfaceCode::GET_ALL_BUNDLE_RESOURCE_INFO, data, bundleResourceInfos);
142 }
143
GetAllLauncherAbilityResourceInfo(const uint32_t flags,std::vector<LauncherAbilityResourceInfo> & launcherAbilityResourceInfos)144 ErrCode BundleResourceProxy::GetAllLauncherAbilityResourceInfo(const uint32_t flags,
145 std::vector<LauncherAbilityResourceInfo> &launcherAbilityResourceInfos)
146 {
147 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
148 APP_LOGD("start, flags:%{public}u", flags);
149 MessageParcel data;
150 if (!data.WriteInterfaceToken(GetDescriptor())) {
151 APP_LOGE("fail to write InterfaceToken");
152 return ERR_APPEXECFWK_PARCEL_ERROR;
153 }
154 if (!data.WriteUint32(flags)) {
155 APP_LOGE("fail to write flags");
156 return ERR_APPEXECFWK_PARCEL_ERROR;
157 }
158
159 return GetVectorParcelInfo<LauncherAbilityResourceInfo>(
160 BundleResourceInterfaceCode::GET_ALL_LAUNCHER_ABILITY_RESOURCE_INFO, data, launcherAbilityResourceInfos);
161 }
162
AddResourceInfoByBundleName(const std::string & bundleName,const int32_t userId)163 ErrCode BundleResourceProxy::AddResourceInfoByBundleName(const std::string &bundleName, const int32_t userId)
164 {
165 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
166 APP_LOGD("start, bundleName:%{public}s userId:%{private}d", bundleName.c_str(), userId);
167 MessageParcel data;
168 MessageParcel reply;
169 if (!data.WriteInterfaceToken(GetDescriptor())) {
170 APP_LOGE("fail to write InterfaceToken");
171 return ERR_APPEXECFWK_PARCEL_ERROR;
172 }
173 if (!data.WriteString(bundleName)) {
174 APP_LOGE("fail to write bundleName");
175 return ERR_APPEXECFWK_PARCEL_ERROR;
176 }
177 if (!data.WriteInt32(userId)) {
178 APP_LOGE("fail to write userId");
179 return ERR_APPEXECFWK_PARCEL_ERROR;
180 }
181
182 if (!SendRequest(BundleResourceInterfaceCode::ADD_RESOURCE_INFO_BY_BUNDLE_NAME, data, reply)) {
183 return ERR_APPEXECFWK_PARCEL_ERROR;
184 }
185 ErrCode ret = reply.ReadInt32();
186 if (ret != ERR_OK) {
187 APP_LOGE("host reply err:%{public}d", ret);
188 return ret;
189 }
190 return ERR_OK;
191 }
192
AddResourceInfoByAbility(const std::string & bundleName,const std::string & moduleName,const std::string & abilityName,const int32_t userId)193 ErrCode BundleResourceProxy::AddResourceInfoByAbility(const std::string &bundleName, const std::string &moduleName,
194 const std::string &abilityName, const int32_t userId)
195 {
196 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
197 APP_LOGD("start, bundleName:%{public}s moduleName:%{public}s abilityName:%{public}s userId:%{private}d",
198 bundleName.c_str(), moduleName.c_str(), abilityName.c_str(), userId);
199 MessageParcel data;
200 MessageParcel reply;
201 if (!data.WriteInterfaceToken(GetDescriptor())) {
202 APP_LOGE("fail to write InterfaceToken");
203 return ERR_APPEXECFWK_PARCEL_ERROR;
204 }
205 if (!data.WriteString(bundleName)) {
206 APP_LOGE("fail to write bundleName");
207 return ERR_APPEXECFWK_PARCEL_ERROR;
208 }
209 if (!data.WriteString(moduleName)) {
210 APP_LOGE("fail to write moduleName");
211 return ERR_APPEXECFWK_PARCEL_ERROR;
212 }
213 if (!data.WriteString(abilityName)) {
214 APP_LOGE("fail to write abilityName");
215 return ERR_APPEXECFWK_PARCEL_ERROR;
216 }
217 if (!data.WriteInt32(userId)) {
218 APP_LOGE("fail to write userId");
219 return ERR_APPEXECFWK_PARCEL_ERROR;
220 }
221
222 if (!SendRequest(BundleResourceInterfaceCode::ADD_RESOURCE_INFO_BY_ABILITY, data, reply)) {
223 return ERR_APPEXECFWK_PARCEL_ERROR;
224 }
225 ErrCode ret = reply.ReadInt32();
226 if (ret != ERR_OK) {
227 APP_LOGE("host reply err:%{public}d", ret);
228 return ret;
229 }
230 return ERR_OK;
231 }
232
DeleteResourceInfo(const std::string & key)233 ErrCode BundleResourceProxy::DeleteResourceInfo(const std::string &key)
234 {
235 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
236 APP_LOGD("start, key:%{private}s", key.c_str());
237 MessageParcel data;
238 MessageParcel reply;
239 if (!data.WriteInterfaceToken(GetDescriptor())) {
240 APP_LOGE("fail to write InterfaceToken");
241 return ERR_APPEXECFWK_PARCEL_ERROR;
242 }
243 if (!data.WriteString(key)) {
244 APP_LOGE("fail to write key");
245 return ERR_APPEXECFWK_PARCEL_ERROR;
246 }
247
248 if (!SendRequest(BundleResourceInterfaceCode::DELETE_RESOURCE_INFO, data, reply)) {
249 return ERR_APPEXECFWK_PARCEL_ERROR;
250 }
251 ErrCode ret = reply.ReadInt32();
252 if (ret != ERR_OK) {
253 APP_LOGE("host reply err:%{public}d", ret);
254 return ret;
255 }
256 return ERR_OK;
257 }
258
259 template<typename T>
GetParcelInfo(BundleResourceInterfaceCode code,MessageParcel & data,T & parcelInfo)260 ErrCode BundleResourceProxy::GetParcelInfo(BundleResourceInterfaceCode code, MessageParcel &data, T &parcelInfo)
261 {
262 MessageParcel reply;
263 if (!SendRequest(code, data, reply)) {
264 APP_LOGE("SendTransactCmd failed");
265 return ERR_APPEXECFWK_PARCEL_ERROR;
266 }
267 ErrCode ret = reply.ReadInt32();
268 if (ret != ERR_OK) {
269 APP_LOGE("host reply err: %{public}d", ret);
270 return ret;
271 }
272 size_t dataSize = reply.ReadUint32();
273 void *buffer = nullptr;
274 if (dataSize > MAX_IPC_ALLOWED_CAPACITY) {
275 if (GetParcelInfoFromAshMem(reply, buffer) != ERR_OK) {
276 APP_LOGE("read data from ashmem fail, length %{public}zu", dataSize);
277 return ERR_APPEXECFWK_PARCEL_ERROR;
278 }
279 } else {
280 if (!GetData(buffer, dataSize, reply.ReadRawData(dataSize))) {
281 APP_LOGE("GetData failed dataSize: %{public}zu", dataSize);
282 return ERR_APPEXECFWK_PARCEL_ERROR;
283 }
284 }
285
286 MessageParcel tmpParcel;
287 if (!tmpParcel.ParseFrom(reinterpret_cast<uintptr_t>(buffer), dataSize)) {
288 APP_LOGE("ParseFrom failed");
289 return ERR_APPEXECFWK_PARCEL_ERROR;
290 }
291
292 std::unique_ptr<T> info(tmpParcel.ReadParcelable<T>());
293 if (info == nullptr) {
294 APP_LOGE("ReadParcelable failed");
295 return ERR_APPEXECFWK_PARCEL_ERROR;
296 }
297 parcelInfo = *info;
298 return ERR_OK;
299 }
300
301 template<typename T>
GetVectorParcelInfo(BundleResourceInterfaceCode code,MessageParcel & data,std::vector<T> & parcelInfos)302 ErrCode BundleResourceProxy::GetVectorParcelInfo(
303 BundleResourceInterfaceCode code, MessageParcel &data, std::vector<T> &parcelInfos)
304 {
305 MessageParcel reply;
306 if (!SendRequest(code, data, reply)) {
307 APP_LOGE("SendTransactCmd failed");
308 return ERR_APPEXECFWK_PARCEL_ERROR;
309 }
310
311 ErrCode res = reply.ReadInt32();
312 if (res != ERR_OK) {
313 APP_LOGE("failed err %{public}d", res);
314 return res;
315 }
316
317 size_t dataSize = reply.ReadUint32();
318 if (dataSize == 0) {
319 APP_LOGW("Parcel no data");
320 return ERR_OK;
321 }
322
323 void *buffer = nullptr;
324 if (dataSize > MAX_IPC_ALLOWED_CAPACITY) {
325 APP_LOGI("dataSize is too large, use ashmem");
326 if (GetParcelInfoFromAshMem(reply, buffer) != ERR_OK) {
327 APP_LOGE("read data from ashmem fail, length %{public}zu", dataSize);
328 return ERR_APPEXECFWK_PARCEL_ERROR;
329 }
330 } else {
331 if (!GetData(buffer, dataSize, reply.ReadRawData(dataSize))) {
332 APP_LOGE("GetData failed dataSize: %{public}zu", dataSize);
333 return ERR_APPEXECFWK_PARCEL_ERROR;
334 }
335 }
336
337 MessageParcel tempParcel;
338 if (!tempParcel.ParseFrom(reinterpret_cast<uintptr_t>(buffer), dataSize)) {
339 APP_LOGE("Fail to ParseFrom");
340 return ERR_APPEXECFWK_PARCEL_ERROR;
341 }
342
343 int32_t infoSize = tempParcel.ReadInt32();
344 CONTAINER_SECURITY_VERIFY(tempParcel, infoSize, &parcelInfos);
345 for (int32_t i = 0; i < infoSize; i++) {
346 std::unique_ptr<T> info(tempParcel.ReadParcelable<T>());
347 if (info == nullptr) {
348 APP_LOGE("Read Parcelable infos failed");
349 return ERR_APPEXECFWK_PARCEL_ERROR;
350 }
351 parcelInfos.emplace_back(*info);
352 }
353
354 return ERR_OK;
355 }
356
GetParcelInfoFromAshMem(MessageParcel & reply,void * & data)357 ErrCode BundleResourceProxy::GetParcelInfoFromAshMem(MessageParcel &reply, void *&data)
358 {
359 sptr<Ashmem> ashMem = reply.ReadAshmem();
360 if (ashMem == nullptr) {
361 APP_LOGE("Ashmem is nullptr");
362 return ERR_APPEXECFWK_PARCEL_ERROR;
363 }
364
365 if (!ashMem->MapReadOnlyAshmem()) {
366 APP_LOGE("MapReadOnlyAshmem failed");
367 return ERR_APPEXECFWK_PARCEL_ERROR;
368 }
369 int32_t ashMemSize = ashMem->GetAshmemSize();
370 int32_t offset = 0;
371 const void* ashDataPtr = ashMem->ReadFromAshmem(ashMemSize, offset);
372 if (ashDataPtr == nullptr) {
373 APP_LOGE("ashDataPtr is nullptr");
374 return ERR_APPEXECFWK_PARCEL_ERROR;
375 }
376 if ((ashMemSize == 0) || ashMemSize > static_cast<int32_t>(MAX_PARCEL_CAPACITY)) {
377 APP_LOGE("failed due to wrong size");
378 return ERR_APPEXECFWK_PARCEL_ERROR;
379 }
380 data = malloc(ashMemSize);
381 if (data == nullptr) {
382 APP_LOGE("failed due to malloc data failed");
383 return ERR_APPEXECFWK_PARCEL_ERROR;
384 }
385 if (memcpy_s(data, ashMemSize, ashDataPtr, ashMemSize) != EOK) {
386 free(data);
387 APP_LOGE("failed due to memcpy_s failed");
388 return ERR_APPEXECFWK_PARCEL_ERROR;
389 }
390 return ERR_OK;
391 }
392
SendRequest(BundleResourceInterfaceCode code,MessageParcel & data,MessageParcel & reply)393 bool BundleResourceProxy::SendRequest(BundleResourceInterfaceCode code,
394 MessageParcel &data, MessageParcel &reply)
395 {
396 MessageOption option(MessageOption::TF_SYNC);
397
398 sptr<IRemoteObject> remote = Remote();
399 if (remote == nullptr) {
400 APP_LOGE("fail send transact cmd %{public}hhu due to remote object", code);
401 return false;
402 }
403 int32_t result = remote->SendRequest(static_cast<uint32_t>(code), data, reply, option);
404 if (result != NO_ERROR) {
405 APP_LOGE("receive error %{public}d in transact cmd %{public}hhu", result, code);
406 return false;
407 }
408 return true;
409 }
410 } // AppExecFwk
411 } // OHOS
412