1 /*
2  * Copyright (c) 2021-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 <ipc_skeleton.h>
17 #include <iservice_registry.h>
18 #include <regex>
19 #include <string_ex.h>
20 #include <unistd.h>
21 #include <vector>
22 
23 #include "hdf_dump.h"
24 #include "hdf_log.h"
25 #include "hdf_object_manager.h"
26 #include "hdf_sbuf_ipc.h"
27 #include "hdf_remote_adapter.h"
28 #include "hdf_xcollie.h"
29 
30 #define HDF_LOG_TAG hdf_remote_adapter
31 
32 static constexpr int32_t THREAD_POOL_BASE_THREAD_COUNT = 5;
33 static int32_t g_remoteThreadMax = THREAD_POOL_BASE_THREAD_COUNT;
34 
HdfRemoteServiceStub(struct HdfRemoteService * service)35 HdfRemoteServiceStub::HdfRemoteServiceStub(struct HdfRemoteService *service)
36     : IPCObjectStub(std::u16string(u"")), service_(service)
37 {
38 }
39 
OnRemoteRequest(uint32_t code,OHOS::MessageParcel & data,OHOS::MessageParcel & reply,OHOS::MessageOption & option)40 int HdfRemoteServiceStub::OnRemoteRequest(uint32_t code,
41     OHOS::MessageParcel &data, OHOS::MessageParcel &reply, OHOS::MessageOption &option)
42 {
43     HDF_LOGD("OnRemoteRequest enter");
44     (void)option;
45 
46     int ret = HDF_FAILURE;
47     struct HdfSBuf *dataSbuf = ParcelToSbuf(&data);
48     struct HdfSBuf *replySbuf = ParcelToSbuf(&reply);
49 
50     std::shared_lock lock(mutex_);
51     if (service_ == nullptr) {
52         HDF_LOGE("service_ is nullptr");
53         HdfSbufRecycle(dataSbuf);
54         HdfSbufRecycle(replySbuf);
55         return HDF_ERR_INVALID_OBJECT;
56     }
57     struct HdfRemoteDispatcher *dispatcher = service_->dispatcher;
58     if (dispatcher != nullptr && dispatcher->Dispatch != nullptr) {
59         ret = dispatcher->Dispatch(reinterpret_cast<HdfRemoteService *>(service_->target), code, dataSbuf, replySbuf);
60     } else {
61         HDF_LOGE("dispatcher or dispatcher->Dispatch is null, flags is: %{public}d", option.GetFlags());
62     }
63 
64     HdfSbufRecycle(dataSbuf);
65     HdfSbufRecycle(replySbuf);
66     return ret;
67 }
68 
HdfRemoteStubClearHolder()69 void HdfRemoteServiceStub::HdfRemoteStubClearHolder()
70 {
71     std::unique_lock lock(mutex_);
72     service_ = nullptr;
73 }
74 
~HdfRemoteServiceStub()75 HdfRemoteServiceStub::~HdfRemoteServiceStub()
76 {
77     HDF_LOGD("~HdfRemoteServiceStub");
78 }
79 
~HdfRemoteServiceHolder()80 HdfRemoteServiceHolder::~HdfRemoteServiceHolder()
81 {
82     HDF_LOGD("~HdfRemoteServiceHolder");
83 }
84 
Dump(int32_t fd,const std::vector<std::u16string> & args)85 int32_t HdfRemoteServiceStub::Dump(int32_t fd, const std::vector<std::u16string> &args)
86 {
87     return HdfDump(fd, args);
88 }
89 
HdfDeathNotifier(struct HdfRemoteService * service,struct HdfDeathRecipient * recipient)90 HdfDeathNotifier::HdfDeathNotifier(struct HdfRemoteService *service, struct HdfDeathRecipient *recipient)
91     : recipient_(recipient), service_(service)
92 {
93 }
94 
~HdfDeathNotifier()95 HdfDeathNotifier::~HdfDeathNotifier()
96 {
97 }
98 
OnRemoteDied(const OHOS::wptr<OHOS::IRemoteObject> & object)99 void HdfDeathNotifier::OnRemoteDied(const OHOS::wptr<OHOS::IRemoteObject> &object) /* who = 0 */
100 {
101     if (recipient_ != nullptr) {
102         recipient_->OnRemoteDied(recipient_, service_);
103     }
104 }
105 
HdfRemoteAdapterOptionalDispatch(struct HdfRemoteService * service,int code,HdfSBuf * data,HdfSBuf * reply,bool sync)106 static int HdfRemoteAdapterOptionalDispatch(struct HdfRemoteService *service, int code,
107     HdfSBuf *data, HdfSBuf *reply, bool sync)
108 {
109     if (service == nullptr) {
110         return HDF_ERR_INVALID_PARAM;
111     }
112 
113     OHOS::MessageParcel *dataParcel = nullptr;
114     OHOS::MessageParcel *replyParcel = nullptr;
115 
116     if (reply == nullptr) {
117         static OHOS::MessageParcel dummyReply;
118         dummyReply.FlushBuffer();
119         replyParcel = &dummyReply;
120     } else if (SbufToParcel(reply, &replyParcel)) {
121         HDF_LOGE("%{public}s:invalid reply sbuf object to dispatch", __func__);
122         return HDF_ERR_INVALID_PARAM;
123     }
124 
125     if (SbufToParcel(data, &dataParcel)) {
126         HDF_LOGE("%{public}s:invalid data sbuf object to dispatch", __func__);
127         return HDF_ERR_INVALID_PARAM;
128     }
129     int flag = sync ? OHOS::MessageOption::TF_SYNC : OHOS::MessageOption::TF_ASYNC;
130     OHOS::MessageOption option(flag);
131     struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
132     if (dataParcel != nullptr) {
133         OHOS::sptr<OHOS::IRemoteObject> remote = holder->remote_;
134         if (remote != nullptr) {
135             return remote->SendRequest(code, *dataParcel, *replyParcel, option);
136         }
137     }
138     return HDF_FAILURE;
139 }
140 
HdfRemoteAdapterDispatch(struct HdfRemoteService * service,int code,HdfSBuf * data,HdfSBuf * reply)141 static int HdfRemoteAdapterDispatch(struct HdfRemoteService *service,
142     int code, HdfSBuf *data, HdfSBuf *reply)
143 {
144     return HdfRemoteAdapterOptionalDispatch(service, code, data, reply, true);
145 }
146 
HdfRemoteAdapterDispatchAsync(struct HdfRemoteService * service,int code,HdfSBuf * data,HdfSBuf * reply)147 static int HdfRemoteAdapterDispatchAsync(struct HdfRemoteService *service,
148     int code, HdfSBuf *data, HdfSBuf *reply)
149 {
150     return HdfRemoteAdapterOptionalDispatch(service, code, data, reply, false);
151 }
152 
HdfRemoteServiceHolder()153 HdfRemoteServiceHolder::HdfRemoteServiceHolder() : remote_(nullptr), deathRecipient_(nullptr)
154 {
155     service_.object.objectId = HDF_OBJECT_ID_REMOTE_SERVICE;
156     service_.dispatcher = nullptr;
157     service_.target = nullptr;
158     service_.index = 0;
159 }
160 
SetInterfaceDescriptor(const char * desc)161 bool HdfRemoteServiceHolder::SetInterfaceDescriptor(const char *desc)
162 {
163     if (desc == nullptr) {
164         return false;
165     }
166     std::u16string newDesc = OHOS::Str8ToStr16(std::string(desc));
167     if (newDesc.empty()) {
168         HDF_LOGE("failed to set interface des, error on cover str8 to str16, %{public}s", desc);
169         return false;
170     }
171 
172     descriptor_.assign(newDesc);
173     return true;
174 }
175 
HdfRemoteAdapterAddDeathRecipient(struct HdfRemoteService * service,struct HdfDeathRecipient * recipient)176 void HdfRemoteAdapterAddDeathRecipient(
177     struct HdfRemoteService *service, struct HdfDeathRecipient *recipient)
178 {
179     struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
180     if (holder == nullptr) {
181         return;
182     }
183     OHOS::sptr<OHOS::IRemoteObject> remote = holder->remote_;
184     if (remote == nullptr) {
185         return;
186     }
187     if (holder->deathRecipient_ != nullptr) {
188         remote->RemoveDeathRecipient(holder->deathRecipient_);
189     }
190     holder->deathRecipient_ = new HdfDeathNotifier(service, recipient);
191     remote->AddDeathRecipient(holder->deathRecipient_);
192 }
193 
HdfRemoteAdapterRemoveDeathRecipient(struct HdfRemoteService * service,const struct HdfDeathRecipient * recipient)194 void HdfRemoteAdapterRemoveDeathRecipient(
195     struct HdfRemoteService *service, const struct HdfDeathRecipient *recipient)
196 {
197     struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
198     (void)recipient;
199     if (holder == nullptr) {
200         return;
201     }
202     OHOS::sptr<OHOS::IRemoteObject> remote = holder->remote_;
203     if (remote == nullptr) {
204         return;
205     }
206     if (holder->deathRecipient_ != nullptr) {
207         remote->RemoveDeathRecipient(holder->deathRecipient_);
208         holder->deathRecipient_ = nullptr;
209     }
210 }
211 
HdfRemoteAdapterBind(OHOS::sptr<OHOS::IRemoteObject> binder)212 struct HdfRemoteService *HdfRemoteAdapterBind(OHOS::sptr<OHOS::IRemoteObject> binder)
213 {
214     struct HdfRemoteService *remoteService = nullptr;
215     static HdfRemoteDispatcher dispatcher = {
216         .Dispatch = HdfRemoteAdapterDispatch,
217         .DispatchAsync = HdfRemoteAdapterDispatchAsync,
218     };
219 
220     struct HdfRemoteServiceHolder *holder = new HdfRemoteServiceHolder();
221     if (holder != nullptr) {
222         holder->remote_ = binder;
223         remoteService = &holder->service_;
224         remoteService->dispatcher = &dispatcher;
225         remoteService->index = (uint64_t)binder.GetRefPtr();
226         return remoteService;
227     }
228     return nullptr;
229 }
230 
HdfRemoteAdapterObtain(void)231 struct HdfRemoteService *HdfRemoteAdapterObtain(void)
232 {
233     struct HdfRemoteServiceHolder *holder = new HdfRemoteServiceHolder();
234     holder->remote_ = new HdfRemoteServiceStub(&holder->service_);
235     return &holder->service_;
236 }
237 
HdfRemoteAdapterRecycle(struct HdfRemoteService * object)238 void HdfRemoteAdapterRecycle(struct HdfRemoteService *object)
239 {
240     struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(object);
241     if (holder != nullptr) {
242         auto remote = holder->remote_;
243         if (remote != nullptr && !remote->IsProxyObject()) {
244             HdfRemoteServiceStub *stub = reinterpret_cast<HdfRemoteServiceStub *>(remote.GetRefPtr());
245             if (stub != nullptr) {
246                 stub->HdfRemoteStubClearHolder();
247             }
248         }
249         holder->service_.target = nullptr;
250         holder->service_.dispatcher = nullptr;
251         holder->descriptor_.clear();
252         holder->remote_ = nullptr;
253         delete holder;
254     }
255 }
256 
HdfRemoteAdapterAddService(const char * name,struct HdfRemoteService * service)257 int HdfRemoteAdapterAddService(const char *name, struct HdfRemoteService *service)
258 {
259     if (name == nullptr || service == nullptr) {
260         return HDF_ERR_INVALID_PARAM;
261     }
262 
263     OHOS::sptr<OHOS::IServiceRegistry> sr = OHOS::ServiceRegistry::GetInstance();
264     if (sr == nullptr) {
265         HDF_LOGE("failed to get service registry");
266         return HDF_FAILURE;
267     }
268     struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
269     int ret = sr->AddService(OHOS::Str8ToStr16(name), holder->remote_);
270     if (ret == 0) {
271         (void)OHOS::IPCSkeleton::GetInstance().SetMaxWorkThreadNum(g_remoteThreadMax++);
272     }
273     return ret;
274 }
275 
HdfRemoteAdapterGetService(const char * name)276 struct HdfRemoteService *HdfRemoteAdapterGetService(const char *name)
277 {
278     if (name == nullptr) {
279         return nullptr;
280     }
281 
282     OHOS::sptr<OHOS::IServiceRegistry> sr = OHOS::ServiceRegistry::GetInstance();
283     if (sr == nullptr) {
284         HDF_LOGE("failed to get service registry");
285         return nullptr;
286     }
287     OHOS::sptr<OHOS::IRemoteObject> remote = sr->GetService(OHOS::Str8ToStr16(name));
288     if (remote != nullptr) {
289         return HdfRemoteAdapterBind(remote);
290     }
291     return nullptr;
292 }
293 
HdfRemoteAdapterAddSa(int32_t saId,struct HdfRemoteService * service)294 int HdfRemoteAdapterAddSa(int32_t saId, struct HdfRemoteService *service)
295 {
296     if (service == nullptr) {
297         return HDF_ERR_INVALID_PARAM;
298     }
299 
300     const int32_t waitTimes = 50;
301     const int32_t sleepInterval = 20000;
302     OHOS::sptr<OHOS::ISystemAbilityManager> saManager;
303     {
304         for (uint32_t cnt = 0; cnt < waitTimes; ++cnt) {
305             HDF_LOGI("waiting for samgr... %{public}d", cnt);
306             saManager = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
307             if (saManager != nullptr) {
308                 HDF_LOGI("GetSystemAbilityManager success");
309                 break;
310             }
311             HDF_LOGI("GetSystemAbilityManager failed, retry");
312             usleep(sleepInterval);
313         }
314         if (saManager == nullptr) {
315             HDF_LOGE("failed to get sa manager, waiting timeout");
316             return HDF_FAILURE;
317         }
318     }
319     {
320         struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
321 #ifdef WITH_SELINUX
322         OHOS::sptr<OHOS::IRemoteObject> remote = holder->remote_;
323         OHOS::IPCObjectStub *stub = reinterpret_cast<OHOS::IPCObjectStub *>(remote.GetRefPtr());
324         stub->SetRequestSidFlag(true);
325 #endif
326         int ret = HDF_FAILURE;
327         for (uint32_t cnt = 0; cnt < waitTimes; ++cnt) {
328             HDF_LOGI("waiting for addSa... %{public}d", cnt);
329             ret = saManager->AddSystemAbility(saId, holder->remote_);
330             if (ret == HDF_SUCCESS) {
331                 HDF_LOGI("addsa %{public}d, success", saId);
332                 break;
333             }
334             HDF_LOGI("AddSystemAbility failed, retry");
335             usleep(sleepInterval);
336         }
337         if (ret != HDF_SUCCESS) {
338             HDF_LOGE("failed to addSa, waiting timeout");
339             return ret;
340         }
341 
342         (void)OHOS::IPCSkeleton::GetInstance().SetMaxWorkThreadNum(g_remoteThreadMax++);
343     }
344     return HDF_SUCCESS;
345 }
346 
HdfRemoteAdapterGetSa(int32_t saId)347 struct HdfRemoteService *HdfRemoteAdapterGetSa(int32_t saId)
348 {
349     auto saManager = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
350     if (saManager == nullptr) {
351         HDF_LOGE("failed to get sa manager");
352         return nullptr;
353     }
354     OHOS::sptr<OHOS::IRemoteObject> remote = saManager->GetSystemAbility(saId);
355     constexpr int32_t waitTimes = 50;
356     constexpr int32_t sleepInterval = 20000;
357     int32_t timeout = waitTimes;
358     while (remote == nullptr && (timeout > 0)) {
359         HDF_LOGD("waiting for saId %{public}d", saId);
360         usleep(sleepInterval);
361         remote = saManager->GetSystemAbility(saId);
362         timeout--;
363     }
364     if (remote != nullptr) {
365         return HdfRemoteAdapterBind(remote);
366     } else {
367         HDF_LOGE("failed to get sa %{public}d", saId);
368     }
369     return nullptr;
370 }
371 
HdfRemoteAdapterSetInterfaceDesc(struct HdfRemoteService * service,const char * desc)372 bool HdfRemoteAdapterSetInterfaceDesc(struct HdfRemoteService *service, const char *desc)
373 {
374     if (service == nullptr || desc == nullptr) {
375         return false;
376     }
377     struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
378     return holder->SetInterfaceDescriptor(desc);
379 }
380 
HdfRemoteAdapterWriteInterfaceToken(struct HdfRemoteService * service,struct HdfSBuf * data)381 bool HdfRemoteAdapterWriteInterfaceToken(struct HdfRemoteService *service, struct HdfSBuf *data)
382 {
383     if (service == nullptr || data == nullptr) {
384         return false;
385     }
386     struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
387     OHOS::MessageParcel *parcel = nullptr;
388 
389     if (SbufToParcel(data, &parcel) != HDF_SUCCESS) {
390         HDF_LOGE("failed to write interface token, SbufToParcel error");
391         return false;
392     }
393 
394     if (holder->remote_ == nullptr) {
395         HDF_LOGE("failed to write interface token, holder->remote is nullptr");
396         return false;
397     }
398     if (holder->descriptor_.empty()) {
399         HDF_LOGE("failed to write interface token, empty token");
400         return false;
401     }
402     return parcel->WriteInterfaceToken(holder->descriptor_);
403 }
404 
CheckInterfaceTokenIngoreVersion(const std::string & client,const std::string & stub)405 static bool CheckInterfaceTokenIngoreVersion(const std::string &client, const std::string &stub)
406 {
407     std::vector<std::string> clientVec;
408     OHOS::SplitStr(client, ".", clientVec);
409     std::vector<std::string> stubVec;
410     OHOS::SplitStr(stub, ".", stubVec);
411     if (clientVec.size() != stubVec.size()) {
412         HDF_LOGE("%{public}s: client desc and stub desc have different size", __func__);
413         return false;
414     }
415     std::regex rVer("[V|v][0-9]+_[0-9]+");
416     for (size_t i = 0; i < stubVec.size(); i++) {
417         if (std::regex_match(stubVec[i], rVer)) {
418             continue;
419         }
420         if (clientVec[i] != stubVec[i]) {
421             HDF_LOGE("%{public}s: mismatch between client desc and stub desc", __func__);
422             return false;
423         }
424     }
425     return true;
426 }
427 
HdfRemoteAdapterCheckInterfaceToken(struct HdfRemoteService * service,struct HdfSBuf * data)428 bool HdfRemoteAdapterCheckInterfaceToken(struct HdfRemoteService *service, struct HdfSBuf *data)
429 {
430     if (service == nullptr || data == nullptr) {
431         return false;
432     }
433     struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
434     if (holder->remote_ == nullptr) {
435         return false;
436     }
437     OHOS::MessageParcel *parcel = nullptr;
438 
439     if (SbufToParcel(data, &parcel) != HDF_SUCCESS) {
440         return false;
441     }
442     auto desc = parcel->ReadInterfaceToken();
443     if (desc.empty()) {
444         HDF_LOGE("failed to check interface, empty token");
445         return false;
446     }
447     std::string client = OHOS::Str16ToStr8(desc);
448     std::string stub = OHOS::Str16ToStr8(holder->descriptor_);
449     if (!CheckInterfaceTokenIngoreVersion(client, stub)) {
450         HDF_LOGE("calling unknown interface: %{public}s", client.c_str());
451         return false;
452     }
453     return true;
454 }
455 
HdfRemoteGetCallingPid(void)456 pid_t HdfRemoteGetCallingPid(void)
457 {
458     return OHOS::IPCSkeleton::GetCallingPid();
459 }
460 
HdfRemoteGetCallingUid(void)461 pid_t HdfRemoteGetCallingUid(void)
462 {
463     return OHOS::IPCSkeleton::GetCallingUid();
464 }
465 
HdfRemoteGetCallingSid(void)466 char *HdfRemoteGetCallingSid(void)
467 {
468     return strdup(OHOS::IPCSkeleton::GetCallingSid().c_str());
469 }
470 
HdfRemoteAdapterDefaultDispatch(struct HdfRemoteService * service,int code,struct HdfSBuf * data,struct HdfSBuf * reply)471 int HdfRemoteAdapterDefaultDispatch(struct HdfRemoteService *service,
472     int code, struct HdfSBuf *data, struct HdfSBuf *reply)
473 {
474     struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
475     if (holder == nullptr) {
476         HDF_LOGE("%{public}s: failed to converts remote to holder", __func__);
477         return HDF_ERR_INVALID_PARAM;
478     }
479 
480     if (holder->remote_ == nullptr) {
481         HDF_LOGE("%{public}s: invaild holder, holder->remote is nullptr", __func__);
482         return HDF_ERR_INVALID_PARAM;
483     }
484 
485     OHOS::IPCObjectStub *stub = reinterpret_cast<OHOS::IPCObjectStub *>(holder->remote_.GetRefPtr());
486     if (stub == nullptr) {
487         HDF_LOGE("%{public}s: failed to converts holder->remote to IPCObjectStub object", __func__);
488         return HDF_ERR_INVALID_PARAM;
489     }
490 
491     OHOS::MessageParcel *dataParcel = nullptr;
492     OHOS::MessageParcel *replyParcel = nullptr;
493     OHOS::MessageOption option;
494 
495     if (SbufToParcel(data, &dataParcel) != HDF_SUCCESS) {
496         HDF_LOGE("%{public}s:invalid data sbuf object to dispatch", __func__);
497         return HDF_ERR_INVALID_PARAM;
498     }
499 
500     if (SbufToParcel(data, &replyParcel) != HDF_SUCCESS) {
501         HDF_LOGE("%{public}s:invalid reply sbuf object to dispatch", __func__);
502         return HDF_ERR_INVALID_PARAM;
503     }
504 
505     return stub->IPCObjectStub::OnRemoteRequest(code, *dataParcel, *replyParcel, option);
506 }
507