• 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_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 
ClearAshmem(sptr<Ashmem> & optMem)357 void BundleResourceProxy::ClearAshmem(sptr<Ashmem> &optMem)
358 {
359     if (optMem != nullptr) {
360         optMem->UnmapAshmem();
361         optMem->CloseAshmem();
362     }
363 }
364 
GetParcelInfoFromAshMem(MessageParcel & reply,void * & data)365 ErrCode BundleResourceProxy::GetParcelInfoFromAshMem(MessageParcel &reply, void *&data)
366 {
367     sptr<Ashmem> ashMem = reply.ReadAshmem();
368     if (ashMem == nullptr) {
369         APP_LOGE("Ashmem is nullptr");
370         return ERR_APPEXECFWK_PARCEL_ERROR;
371     }
372 
373     if (!ashMem->MapReadOnlyAshmem()) {
374         APP_LOGE("MapReadOnlyAshmem failed");
375         ClearAshmem(ashMem);
376         return ERR_APPEXECFWK_PARCEL_ERROR;
377     }
378     int32_t ashMemSize = ashMem->GetAshmemSize();
379     int32_t offset = 0;
380     const void* ashDataPtr = ashMem->ReadFromAshmem(ashMemSize, offset);
381     if (ashDataPtr == nullptr) {
382         APP_LOGE("ashDataPtr is nullptr");
383         ClearAshmem(ashMem);
384         return ERR_APPEXECFWK_PARCEL_ERROR;
385     }
386     if ((ashMemSize == 0) || ashMemSize > static_cast<int32_t>(MAX_PARCEL_CAPACITY)) {
387         APP_LOGE("failed due to wrong size");
388         ClearAshmem(ashMem);
389         return ERR_APPEXECFWK_PARCEL_ERROR;
390     }
391     data = malloc(ashMemSize);
392     if (data == nullptr) {
393         APP_LOGE("failed due to malloc data failed");
394         ClearAshmem(ashMem);
395         return ERR_APPEXECFWK_PARCEL_ERROR;
396     }
397     if (memcpy_s(data, ashMemSize, ashDataPtr, ashMemSize) != EOK) {
398         free(data);
399         ClearAshmem(ashMem);
400         APP_LOGE("failed due to memcpy_s failed");
401         return ERR_APPEXECFWK_PARCEL_ERROR;
402     }
403     ClearAshmem(ashMem);
404     return ERR_OK;
405 }
406 
SendRequest(BundleResourceInterfaceCode code,MessageParcel & data,MessageParcel & reply)407 bool BundleResourceProxy::SendRequest(BundleResourceInterfaceCode code,
408     MessageParcel &data, MessageParcel &reply)
409 {
410     MessageOption option(MessageOption::TF_SYNC);
411 
412     sptr<IRemoteObject> remote = Remote();
413     if (remote == nullptr) {
414         APP_LOGE("fail send transact cmd %{public}hhu due to remote object", code);
415         return false;
416     }
417     int32_t result = remote->SendRequest(static_cast<uint32_t>(code), data, reply, option);
418     if (result != NO_ERROR) {
419         APP_LOGE("receive error %{public}d in transact cmd %{public}hhu", result, code);
420         return false;
421     }
422     return true;
423 }
424 } // AppExecFwk
425 } // OHOS
426