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