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