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