1 /*
2 * Copyright (C) 2021 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 "binder_invoker.h"
17
18 #include <chrono>
19 #include <securec.h>
20 #include "access_token_adapter.h"
21 #include "binder_debug.h"
22 #include "dbinder_error_code.h"
23 #include "hilog/log.h"
24 #include "hitrace_invoker.h"
25 #include "ipc_object_proxy.h"
26 #include "ipc_object_stub.h"
27 #include "ipc_process_skeleton.h"
28 #include "ipc_thread_skeleton.h"
29 #include "log_tags.h"
30 #include "string_ex.h"
31 #include "sys_binder.h"
32
33 namespace OHOS {
34 #ifdef CONFIG_IPC_SINGLE
35 namespace IPC_SINGLE {
36 #endif
37
38 using namespace OHOS::HiviewDFX;
39 static constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC, "BinderInvoker" };
40 enum {
41 GET_SERVICE_TRANSACTION = 0x1,
42 CHECK_SERVICE_TRANSACTION,
43 ADD_SERVICE_TRANSACTION,
44 };
45
BinderInvoker()46 BinderInvoker::BinderInvoker()
47 : isMainWorkThread(false), stopWorkThread(false), callerPid_(getpid()), callerUid_(getuid()),
48 firstTokenID_(0), status_(0)
49 {
50 callerTokenID_ = (uint32_t)RpcGetSelfTokenID();
51 input_.SetDataCapacity(IPC_DEFAULT_PARCEL_SIZE);
52 binderConnector_ = BinderConnector::GetInstance();
53 }
54
AcquireHandle(int32_t handle)55 bool BinderInvoker::AcquireHandle(int32_t handle)
56 {
57 size_t rewindPos = output_.GetWritePosition();
58 if (!output_.WriteUint32(BC_ACQUIRE)) {
59 return false;
60 }
61
62 if (!output_.WriteInt32(handle)) {
63 if (!output_.RewindWrite(rewindPos)) {
64 output_.FlushBuffer();
65 }
66 return false;
67 }
68 /* invoke remote to receive acquire handle event, don't care ping result */
69 if (handle != 0) {
70 (void)PingService(handle);
71 }
72 return true;
73 }
74
ReleaseHandle(int32_t handle)75 bool BinderInvoker::ReleaseHandle(int32_t handle)
76 {
77 size_t rewindPos = output_.GetWritePosition();
78 if (!output_.WriteUint32(BC_RELEASE)) {
79 return false;
80 }
81
82 if (!output_.WriteInt32(handle)) {
83 if (!output_.RewindWrite(rewindPos)) {
84 output_.FlushBuffer();
85 }
86 return false;
87 }
88 FlushCommands(nullptr);
89 return true;
90 }
91
SendRequest(int handle,uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)92 int BinderInvoker::SendRequest(int handle, uint32_t code, MessageParcel &data, MessageParcel &reply,
93 MessageOption &option)
94 {
95 int error = ERR_NONE;
96 uint32_t flags = (uint32_t)option.GetFlags();
97 MessageParcel &newData = const_cast<MessageParcel &>(data);
98 size_t oldWritePosition = newData.GetWritePosition();
99 HiTraceId traceId = HiTraceChain::GetId();
100 // set client send trace point if trace is enabled
101 HiTraceId childId = HitraceInvoker::TraceClientSend(handle, code, newData, flags, traceId);
102 if (!WriteTransaction(BC_TRANSACTION, flags, handle, code, data, nullptr)) {
103 newData.RewindWrite(oldWritePosition);
104 ZLOGE(LABEL, "WriteTransaction ERROR");
105 #ifndef BUILD_PUBLIC_VERSION
106 ReportDriverEvent(DbinderErrorCode::COMMON_DRIVER_ERROR, DbinderErrorCode::ERROR_TYPE,
107 DbinderErrorCode::IPC_DRIVER, DbinderErrorCode::ERROR_CODE, DbinderErrorCode::TRANSACT_DATA_FAILURE);
108 #endif
109 return IPC_INVOKER_WRITE_TRANS_ERR;
110 }
111
112 if ((flags & TF_ONE_WAY) != 0) {
113 error = WaitForCompletion(nullptr);
114 } else {
115 error = WaitForCompletion(&reply);
116 }
117 HitraceInvoker::TraceClientReceieve(handle, code, flags, traceId, childId);
118 // restore Parcel data
119 newData.RewindWrite(oldWritePosition);
120 if (error != ERR_NONE) {
121 ZLOGE(LABEL, "%{public}s: handle=%{public}d result = %{public}d", __func__, handle, error);
122 }
123 return error;
124 }
125
AddDeathRecipient(int32_t handle,void * cookie)126 bool BinderInvoker::AddDeathRecipient(int32_t handle, void *cookie)
127 {
128 size_t rewindPos = output_.GetWritePosition();
129 if (!output_.WriteInt32(BC_REQUEST_DEATH_NOTIFICATION)) {
130 ZLOGE(LABEL, "fail to write command field:%d", handle);
131 return false;
132 }
133
134 if (!output_.WriteInt32(handle)) {
135 if (!output_.RewindWrite(rewindPos)) {
136 output_.FlushBuffer();
137 }
138 return false;
139 }
140
141 if (!output_.WritePointer((uintptr_t)cookie)) {
142 /* rewind written size notification and handle. */
143 if (!output_.RewindWrite(rewindPos)) {
144 output_.FlushBuffer();
145 }
146 return false;
147 }
148
149 // pass in nullptr directly
150 int error = FlushCommands(nullptr);
151 if (error == ERR_NONE) {
152 auto *proxy = reinterpret_cast<IPCObjectProxy *>(cookie);
153 if (proxy != nullptr) {
154 proxy->IncStrongRef(this);
155 }
156 }
157 return error == ERR_NONE;
158 }
159
RemoveDeathRecipient(int32_t handle,void * cookie)160 bool BinderInvoker::RemoveDeathRecipient(int32_t handle, void *cookie)
161 {
162 size_t rewindPos = output_.GetWritePosition();
163 if (!output_.WriteInt32(BC_CLEAR_DEATH_NOTIFICATION)) {
164 return false;
165 }
166
167 if (!output_.WriteInt32(handle)) {
168 if (!output_.RewindWrite(rewindPos)) {
169 output_.FlushBuffer();
170 }
171 return false;
172 }
173
174 if (!output_.WritePointer((uintptr_t)cookie)) {
175 if (!output_.RewindWrite(rewindPos)) {
176 output_.FlushBuffer();
177 }
178 return false;
179 }
180
181 // pass in nullptr directly
182 int error = FlushCommands(nullptr);
183 if (error != ERR_NONE) {
184 ZLOGE(LABEL, "Remove Death Recipient handle =%{public}d result = %{public}d", handle, error);
185 return false;
186 }
187
188 return true;
189 }
190
GetObjectRefCount(const IRemoteObject * object)191 int BinderInvoker::GetObjectRefCount(const IRemoteObject *object)
192 {
193 if ((binderConnector_ == nullptr) || (!binderConnector_->IsDriverAlive())) {
194 return 0;
195 }
196
197 struct binder_ptr_count refs;
198 refs.ptr = reinterpret_cast<uintptr_t>(object);
199
200 int error = binderConnector_->WriteBinder(BINDER_GET_NODE_REFCOUNT, &refs);
201 if (error != ERR_NONE) {
202 ZLOGE(LABEL, "GetSRefCount error = %{public}d", error);
203 return 0;
204 }
205 return refs.count;
206 }
207
208 #ifndef CONFIG_IPC_SINGLE
TranslateProxy(uint32_t handle,uint32_t flag)209 int BinderInvoker::TranslateProxy(uint32_t handle, uint32_t flag)
210 {
211 binder_node_debug_info info {};
212 if ((binderConnector_ == nullptr) || (!binderConnector_->IsDriverAlive())) {
213 return -IPC_INVOKER_CONNECT_ERR;
214 }
215 info.has_strong_ref = handle;
216 info.has_weak_ref = flag;
217 ZLOGD(LABEL, "TranslateProxy input handle = %{public}u", info.has_strong_ref);
218 int error = binderConnector_->WriteBinder(BINDER_TRANSLATE_HANDLE, &info);
219 if (error == ERR_NONE && info.has_strong_ref > 0) {
220 ZLOGD(LABEL, "TranslateProxy get new handle = %{public}u", info.has_strong_ref);
221 return info.has_strong_ref;
222 }
223 ZLOGE(LABEL, "failed to translateProxy input handle = %{public}u", info.has_strong_ref);
224 return -IPC_INVOKER_TRANSLATE_ERR;
225 }
226
TranslateStub(binder_uintptr_t cookie,binder_uintptr_t ptr,uint32_t flag,int cmd)227 int BinderInvoker::TranslateStub(binder_uintptr_t cookie, binder_uintptr_t ptr, uint32_t flag, int cmd)
228 {
229 binder_node_debug_info info {};
230 if ((binderConnector_ == nullptr) || (!binderConnector_->IsDriverAlive())) {
231 return -IPC_INVOKER_CONNECT_ERR;
232 }
233 info.cookie = cookie;
234 info.ptr = ptr;
235 info.has_weak_ref = (uint32_t)cmd;
236 info.has_strong_ref = flag;
237 int error = binderConnector_->WriteBinder(BINDER_TRANSLATE_HANDLE, &info);
238 if (error == ERR_NONE && info.has_strong_ref > 0) {
239 ZLOGD(LABEL, "TranslateStub get new handle = %{public}u", info.has_strong_ref);
240 return info.has_strong_ref;
241 }
242 ZLOGE(LABEL, "failed to TranslateStub");
243 return -IPC_INVOKER_TRANSLATE_ERR;
244 }
245
GetSAMgrObject()246 sptr<IRemoteObject> BinderInvoker::GetSAMgrObject()
247 {
248 IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
249 if (current != nullptr) {
250 return current->GetRegistryObject();
251 }
252 return nullptr;
253 }
254
255 #endif
SetMaxWorkThread(int maxThreadNum)256 bool BinderInvoker::SetMaxWorkThread(int maxThreadNum)
257 {
258 if ((binderConnector_ == nullptr) || (!binderConnector_->IsDriverAlive())) {
259 ZLOGE(LABEL, "%{public}s driver died", __func__);
260 return false;
261 }
262
263 int error = binderConnector_->WriteBinder(BINDER_SET_MAX_THREADS, &maxThreadNum);
264 if (error != ERR_NONE) {
265 ZLOGE(LABEL, "SetMaxWorkThread error = %{public}d", error);
266 return false;
267 }
268
269 return true;
270 }
271
FlushCommands(IRemoteObject * object)272 int BinderInvoker::FlushCommands(IRemoteObject *object)
273 {
274 if ((binderConnector_ == nullptr) || (!binderConnector_->IsDriverAlive())) {
275 ZLOGE(LABEL, "driver is died");
276 return IPC_INVOKER_CONNECT_ERR;
277 }
278 int error = TransactWithDriver(false);
279 if (error != ERR_NONE) {
280 ZLOGE(LABEL, "fail to flush commands with error = %{public}d", error);
281 }
282
283 if (output_.GetDataSize() > 0) {
284 error = TransactWithDriver(false);
285 ZLOGE(LABEL, "flush commands again with return value = %{public}d", error);
286 }
287 if (error != ERR_NONE || output_.GetDataSize() > 0) {
288 ZLOGE(LABEL, "flush commands with error = %{public}d, left data size = %{public}zu", error,
289 output_.GetDataSize());
290 }
291
292 return error;
293 }
294
ExitCurrentThread()295 void BinderInvoker::ExitCurrentThread()
296 {
297 if ((binderConnector_ == nullptr) || (!binderConnector_->IsDriverAlive())) {
298 ZLOGE(LABEL, "%{public}s driver died when exit current thread", __func__);
299 return;
300 }
301 binderConnector_->ExitCurrentThread(BINDER_THREAD_EXIT);
302 }
303
StartWorkLoop()304 void BinderInvoker::StartWorkLoop()
305 {
306 int error;
307 do {
308 error = TransactWithDriver();
309 if (error < ERR_NONE && error != -ECONNREFUSED && error != -EBADF) {
310 ZLOGE(LABEL, "returned unexpected error %d, aborting", error);
311 break;
312 }
313 uint32_t cmd = input_.ReadUint32();
314 int userError = HandleCommands(cmd);
315 if ((userError == -ERR_TIMED_OUT || userError == IPC_INVOKER_INVALID_DATA_ERR) && !isMainWorkThread) {
316 break;
317 }
318 } while (error != -ECONNREFUSED && error != -EBADF && !stopWorkThread);
319 }
320
SendReply(MessageParcel & reply,uint32_t flags,int32_t result)321 int BinderInvoker::SendReply(MessageParcel &reply, uint32_t flags, int32_t result)
322 {
323 int error = WriteTransaction(BC_REPLY, flags, -1, 0, reply, &result);
324 if (error < ERR_NONE) {
325 return error;
326 }
327
328 return WaitForCompletion();
329 }
330
OnBinderDied()331 void BinderInvoker::OnBinderDied()
332 {
333 uintptr_t cookie = input_.ReadPointer();
334 auto *proxy = reinterpret_cast<IPCObjectProxy *>(cookie);
335 if (proxy != nullptr) {
336 proxy->SendObituary();
337 }
338
339 size_t rewindPos = output_.GetWritePosition();
340 if (!output_.WriteInt32(BC_DEAD_BINDER_DONE)) {
341 return;
342 }
343
344 if (!output_.WritePointer((uintptr_t)cookie)) {
345 if (!output_.RewindWrite(rewindPos)) {
346 output_.FlushBuffer();
347 }
348 }
349 }
350
OnAcquireObject(uint32_t cmd)351 void BinderInvoker::OnAcquireObject(uint32_t cmd)
352 {
353 bool ParcelResult = false;
354 uintptr_t refsPointer = input_.ReadPointer();
355 uintptr_t objectPointer = input_.ReadPointer();
356 RefBase *refs = reinterpret_cast<IRemoteObject *>(refsPointer);
357 if ((refs == nullptr) || (!objectPointer)) {
358 ZLOGE(LABEL, "OnAcquireObject FAIL!");
359 return;
360 }
361
362 size_t rewindPos = output_.GetWritePosition();
363 if (cmd == BR_ACQUIRE) {
364 refs->IncStrongRef(this);
365 ParcelResult = output_.WriteInt32(BC_ACQUIRE_DONE);
366 } else {
367 refs->IncWeakRef(this);
368 ParcelResult = output_.WriteInt32(BC_INCREFS_DONE);
369 }
370
371 if (!ParcelResult || !output_.WritePointer(refsPointer)) {
372 if (!output_.RewindWrite(rewindPos)) {
373 output_.FlushBuffer();
374 }
375 return;
376 }
377
378 if (!output_.WritePointer(objectPointer)) {
379 if (!output_.RewindWrite(rewindPos)) {
380 output_.FlushBuffer();
381 }
382 }
383 }
384
OnReleaseObject(uint32_t cmd)385 void BinderInvoker::OnReleaseObject(uint32_t cmd)
386 {
387 uintptr_t refsPointer = input_.ReadPointer();
388 uintptr_t objectPointer = input_.ReadPointer();
389 auto *refs = reinterpret_cast<IRemoteObject *>(refsPointer);
390 auto *object = reinterpret_cast<IRemoteObject *>(objectPointer);
391 if ((refs == nullptr) || (object == nullptr)) {
392 ZLOGE(LABEL, "OnReleaseObject FAIL!");
393 return;
394 }
395
396 if (cmd == BR_RELEASE) {
397 refs->DecStrongRef(this);
398 } else {
399 refs->DecWeakRef(this);
400 }
401 }
402
OnTransaction(const uint8_t * buffer)403 void BinderInvoker::OnTransaction(const uint8_t *buffer)
404 {
405 const binder_transaction_data *tr = reinterpret_cast<const binder_transaction_data *>(buffer);
406 auto binderAllocator = new (std::nothrow) BinderAllocator();
407 if (binderAllocator == nullptr) {
408 ZLOGE(LABEL, "BinderAllocator Creation failed");
409 return;
410 }
411 auto data = std::make_unique<MessageParcel>(binderAllocator);
412 data->ParseFrom(tr->data.ptr.buffer, tr->data_size);
413 if (tr->offsets_size > 0) {
414 data->InjectOffsets(tr->data.ptr.offsets, tr->offsets_size / sizeof(binder_size_t));
415 }
416 uint32_t &newflags = const_cast<uint32_t &>(tr->flags);
417 int isServerTraced = HitraceInvoker::TraceServerReceieve(tr->target.handle, tr->code, *data, newflags);
418 const pid_t oldPid = callerPid_;
419 const auto oldUid = static_cast<const uid_t>(callerUid_);
420 const uint32_t oldToken = callerTokenID_;
421 const uint32_t oldFirstToken = firstTokenID_;
422 uint32_t oldStatus = status_;
423 callerPid_ = tr->sender_pid;
424 callerUid_ = tr->sender_euid;
425 if (binderConnector_->IsAccessTokenSupported()) {
426 struct access_token tmp;
427 int error = binderConnector_->WriteBinder(BINDER_GET_ACCESS_TOKEN, &tmp);
428 if (error != ERR_NONE) {
429 callerTokenID_ = 0;
430 firstTokenID_ = 0;
431 } else {
432 callerTokenID_ = tmp.sender_tokenid;
433 firstTokenID_ = tmp.first_tokenid;
434 }
435 } else {
436 callerTokenID_ = 0;
437 firstTokenID_ = 0;
438 }
439 SetStatus(IRemoteInvoker::ACTIVE_INVOKER);
440 int error = ERR_DEAD_OBJECT;
441 sptr<IRemoteObject> targetObject;
442 if (tr->target.ptr != 0) {
443 auto *refs = reinterpret_cast<IRemoteObject *>(tr->target.ptr);
444 if ((refs != nullptr) && (tr->cookie) && (refs->AttemptIncStrongRef(this))) {
445 targetObject = reinterpret_cast<IPCObjectStub *>(tr->cookie);
446 if (targetObject != nullptr) {
447 targetObject->DecStrongRef(this);
448 }
449 }
450 } else {
451 targetObject = IPCProcessSkeleton::GetCurrent()->GetRegistryObject();
452 if (targetObject == nullptr) {
453 ZLOGE(LABEL, "Invalid samgr stub object");
454 abort();
455 }
456 }
457 MessageParcel reply;
458 MessageOption option;
459 uint32_t flagValue = static_cast<uint32_t>(tr->flags) & ~static_cast<uint32_t>(MessageOption::TF_ACCEPT_FDS);
460 if (targetObject != nullptr) {
461 option.SetFlags(static_cast<int>(flagValue));
462 auto start = std::chrono::steady_clock::now();
463 error = targetObject->SendRequest(tr->code, *data, reply, option);
464 auto finish = std::chrono::steady_clock::now();
465 int duration = static_cast<int>(std::chrono::duration_cast<std::chrono::milliseconds>(
466 finish - start).count());
467 if (duration >= IPC_CMD_PROCESS_WARN_TIME) {
468 ZLOGW(LABEL, "stub: %{public}s deal request code: %{public}u cost time: %{public}dms",
469 Str16ToStr8(targetObject->descriptor_).c_str(), tr->code, duration);
470 }
471 }
472 HitraceInvoker::TraceServerSend(tr->target.handle, tr->code, isServerTraced, newflags);
473 if (!(flagValue & TF_ONE_WAY)) {
474 SendReply(reply, 0, error);
475 }
476 callerPid_ = oldPid;
477 callerUid_ = oldUid;
478 callerTokenID_ = oldToken;
479 firstTokenID_ = oldFirstToken;
480 SetStatus(oldStatus);
481 }
482
OnAttemptAcquire()483 void BinderInvoker::OnAttemptAcquire()
484 {
485 bool success = false;
486 uintptr_t refsPtr = input_.ReadPointer();
487 uintptr_t objectPtr = input_.ReadPointer();
488 auto *refs = reinterpret_cast<IRemoteObject *>(refsPtr);
489
490 size_t rewindPos = output_.GetWritePosition();
491 if ((refs != nullptr) && (!objectPtr)) {
492 success = refs->AttemptIncStrongRef(this);
493 }
494
495 if (!output_.WriteUint32(BC_ACQUIRE_RESULT)) {
496 return;
497 }
498
499 if (!output_.WriteUint32((uint32_t)success)) {
500 if (!output_.RewindWrite(rewindPos)) {
501 output_.FlushBuffer();
502 }
503 }
504 }
505
OnRemoveRecipientDone()506 void BinderInvoker::OnRemoveRecipientDone()
507 {
508 uintptr_t cookie = input_.ReadPointer();
509 auto *proxy = reinterpret_cast<IPCObjectProxy *>(cookie);
510 if (proxy != nullptr) {
511 proxy->DecStrongRef(this);
512 }
513 }
514
HandleReply(MessageParcel * reply)515 int BinderInvoker::HandleReply(MessageParcel *reply)
516 {
517 const size_t readSize = sizeof(binder_transaction_data);
518 const uint8_t *buffer = input_.ReadBuffer(readSize);
519 if (buffer == nullptr) {
520 ZLOGE(LABEL, "HandleReply read tr failed");
521 return IPC_INVOKER_INVALID_DATA_ERR;
522 }
523 const binder_transaction_data *tr = reinterpret_cast<const binder_transaction_data *>(buffer);
524
525 if (reply == nullptr) {
526 FreeBuffer(reinterpret_cast<void *>(tr->data.ptr.buffer));
527 return IPC_INVOKER_INVALID_REPLY_ERR;
528 }
529
530 if (tr->flags & TF_STATUS_CODE) {
531 int32_t status = *reinterpret_cast<const int32_t *>(tr->data.ptr.buffer);
532 FreeBuffer(reinterpret_cast<void *>(tr->data.ptr.buffer));
533 return status;
534 }
535
536 if (tr->data_size > 0) {
537 auto allocator = new (std::nothrow) BinderAllocator();
538 if (allocator == nullptr) {
539 ZLOGE(LABEL, "create BinderAllocator object failed");
540 return IPC_INVOKER_INVALID_DATA_ERR;
541 }
542 if (!reply->SetAllocator(allocator)) {
543 delete allocator;
544 FreeBuffer(reinterpret_cast<void*>(tr->data.ptr.buffer));
545 return IPC_INVOKER_INVALID_DATA_ERR;
546 }
547 reply->ParseFrom(tr->data.ptr.buffer, tr->data_size);
548 }
549
550 if (tr->offsets_size > 0) {
551 reply->InjectOffsets(tr->data.ptr.offsets, tr->offsets_size / sizeof(binder_size_t));
552 reply->SetClearFdFlag();
553 }
554 return ERR_NONE;
555 }
556
HandleCommandsInner(uint32_t cmd)557 int BinderInvoker::HandleCommandsInner(uint32_t cmd)
558 {
559 int error = ERR_NONE;
560 switch (cmd) {
561 case BR_ERROR:
562 error = input_.ReadInt32();
563 break;
564 case BR_ACQUIRE:
565 case BR_INCREFS:
566 OnAcquireObject(cmd);
567 break;
568 case BR_RELEASE:
569 case BR_DECREFS:
570 OnReleaseObject(cmd);
571 break;
572 case BR_ATTEMPT_ACQUIRE:
573 OnAttemptAcquire();
574 break;
575 case BR_TRANSACTION: {
576 const uint8_t *buffer = input_.ReadBuffer(sizeof(binder_transaction_data));
577 if (buffer == nullptr) {
578 error = IPC_INVOKER_INVALID_DATA_ERR;
579 break;
580 }
581 OnTransaction(buffer);
582 break;
583 }
584 case BR_SPAWN_LOOPER: {
585 IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
586 if (current != nullptr) {
587 current->SpawnThread();
588 }
589 break;
590 }
591 case BR_FINISHED:
592 error = -ERR_TIMED_OUT;
593 break;
594 case BR_DEAD_BINDER:
595 OnBinderDied();
596 break;
597 case BR_CLEAR_DEATH_NOTIFICATION_DONE:
598 OnRemoveRecipientDone();
599 break;
600 case BR_OK:
601 case BR_NOOP:
602 break;
603 default:
604 error = IPC_INVOKER_ON_TRANSACT_ERR;
605 break;
606 }
607 return error;
608 }
609
HandleCommands(uint32_t cmd)610 int BinderInvoker::HandleCommands(uint32_t cmd)
611 {
612 auto start = std::chrono::steady_clock::now();
613 int error = HandleCommandsInner(cmd);
614 if (error != ERR_NONE) {
615 ZLOGE(LABEL, "HandleCommands cmd = %{public}u, error = %{public}d", cmd, error);
616 }
617 if (cmd != BR_TRANSACTION) {
618 auto finish = std::chrono::steady_clock::now();
619 int duration = static_cast<int>(std::chrono::duration_cast<std::chrono::milliseconds>(
620 finish - start).count());
621 if (duration >= IPC_CMD_PROCESS_WARN_TIME) {
622 ZLOGW(LABEL, "HandleCommands cmd: %{public}u cost time: %{public}dms", cmd, duration);
623 }
624 }
625 return error;
626 }
627
JoinThread(bool initiative)628 void BinderInvoker::JoinThread(bool initiative)
629 {
630 isMainWorkThread = initiative;
631 output_.WriteUint32(initiative ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
632 StartWorkLoop();
633 output_.WriteUint32(BC_EXIT_LOOPER);
634 // pass in nullptr directly
635 FlushCommands(nullptr);
636 ZLOGE(LABEL, "Current Thread %d is leaving", getpid());
637 }
638
JoinProcessThread(bool initiative)639 void BinderInvoker::JoinProcessThread(bool initiative) {}
640
TransactWithDriver(bool doRead)641 int BinderInvoker::TransactWithDriver(bool doRead)
642 {
643 if ((binderConnector_ == nullptr) || (!binderConnector_->IsDriverAlive())) {
644 ZLOGE(LABEL, "%{public}s: Binder Driver died", __func__);
645 return IPC_INVOKER_CONNECT_ERR;
646 }
647
648 binder_write_read bwr;
649 const bool readAvail = input_.GetReadableBytes() == 0;
650 const size_t outAvail = (!doRead || readAvail) ? output_.GetDataSize() : 0;
651
652 bwr.write_size = (binder_size_t)outAvail;
653 bwr.write_buffer = output_.GetData();
654
655 if (doRead && readAvail) {
656 bwr.read_size = input_.GetDataCapacity();
657 bwr.read_buffer = input_.GetData();
658 } else {
659 bwr.read_size = 0;
660 bwr.read_buffer = 0;
661 }
662 if ((bwr.write_size == 0) && (bwr.read_size == 0)) {
663 return ERR_NONE;
664 }
665
666 bwr.write_consumed = 0;
667 bwr.read_consumed = 0;
668 int error = binderConnector_->WriteBinder(BINDER_WRITE_READ, &bwr);
669 if (bwr.write_consumed > 0) {
670 if (bwr.write_consumed < output_.GetDataSize()) {
671 // we still have some bytes not been handled.
672 } else {
673 output_.FlushBuffer();
674 }
675 }
676 if (bwr.read_consumed > 0) {
677 input_.SetDataSize(bwr.read_consumed);
678 input_.RewindRead(0);
679 }
680 if (error != ERR_NONE) {
681 ZLOGE(LABEL, "TransactWithDriver result = %{public}d", error);
682 }
683
684 return error;
685 }
686
WriteTransaction(int cmd,uint32_t flags,int32_t handle,uint32_t code,const MessageParcel & data,const int32_t * status)687 bool BinderInvoker::WriteTransaction(int cmd, uint32_t flags, int32_t handle, uint32_t code, const MessageParcel &data,
688 const int32_t *status)
689 {
690 binder_transaction_data tr {};
691 tr.target.handle = (uint32_t)handle;
692 tr.code = code;
693 tr.flags = flags;
694 tr.flags |= TF_ACCEPT_FDS;
695 if (data.GetDataSize() > 0) {
696 // Send this parcel's data through the binder.
697 tr.data_size = data.GetDataSize();
698 tr.data.ptr.buffer = (binder_uintptr_t)data.GetData();
699 tr.offsets_size = data.GetOffsetsSize() * sizeof(binder_size_t);
700 tr.data.ptr.offsets = data.GetObjectOffsets();
701 } else if (status != nullptr) {
702 // Send this parcel's status through the binder.
703 tr.flags |= TF_STATUS_CODE;
704 tr.data_size = sizeof(int32_t);
705 tr.data.ptr.buffer = reinterpret_cast<uintptr_t>(status);
706 tr.offsets_size = 0;
707 tr.data.ptr.offsets = 0;
708 }
709
710 if (!output_.WriteInt32(cmd)) {
711 ZLOGE(LABEL, "WriteTransaction Command failure");
712 return false;
713 }
714 return output_.WriteBuffer(&tr, sizeof(binder_transaction_data));
715 }
716
WaitForCompletion(MessageParcel * reply,int32_t * acquireResult)717 int BinderInvoker::WaitForCompletion(MessageParcel *reply, int32_t *acquireResult)
718 {
719 uint32_t cmd;
720 bool continueLoop = true;
721 int error = ERR_NONE;
722 while (continueLoop) {
723 if ((error = TransactWithDriver()) < ERR_NONE) {
724 break;
725 }
726 if (input_.GetReadableBytes() == 0) {
727 continue;
728 }
729 cmd = input_.ReadUint32();
730 switch (cmd) {
731 case BR_TRANSACTION_COMPLETE: {
732 if (reply == nullptr && acquireResult == nullptr) {
733 continueLoop = false;
734 }
735 break;
736 }
737 case BR_DEAD_REPLY: // fall-through
738 case BR_FAILED_REPLY: {
739 error = (int)cmd;
740 if (acquireResult != nullptr) {
741 *acquireResult = (int32_t)cmd;
742 }
743 continueLoop = false;
744 break;
745 }
746 case BR_ACQUIRE_RESULT: {
747 int32_t result = input_.ReadInt32();
748 if (acquireResult != nullptr) {
749 *acquireResult = result ? ERR_NONE : ERR_INVALID_OPERATION;
750 continueLoop = false;
751 }
752 break;
753 }
754 case BR_REPLY: {
755 error = HandleReply(reply);
756 if (error != IPC_INVOKER_INVALID_REPLY_ERR) {
757 continueLoop = false;
758 break;
759 }
760 error = ERR_NONE;
761 break;
762 }
763 default: {
764 error = HandleCommands(cmd);
765 if (error != ERR_NONE) {
766 continueLoop = false;
767 }
768 break;
769 }
770 }
771 }
772 return error;
773 }
774
StopWorkThread()775 void BinderInvoker::StopWorkThread()
776 {
777 stopWorkThread = true;
778 }
779
PingService(int32_t handle)780 bool BinderInvoker::PingService(int32_t handle)
781 {
782 MessageParcel data, reply;
783 MessageOption option;
784 int result = SendRequest(handle, PING_TRANSACTION, data, reply, option);
785 return (result == ERR_NONE);
786 }
787
SetRegistryObject(sptr<IRemoteObject> & object)788 bool BinderInvoker::SetRegistryObject(sptr<IRemoteObject> &object)
789 {
790 if ((binderConnector_ == nullptr) || (!binderConnector_->IsDriverAlive())) {
791 return false;
792 }
793
794 if (object->IsProxyObject()) {
795 ZLOGE(LABEL, "%{public}s: set wrong object!", __func__);
796 return false;
797 }
798
799 Parcel dummy;
800 int result = binderConnector_->WriteBinder(BINDER_SET_CONTEXT_MGR, &dummy);
801 if (result != ERR_NONE) {
802 ZLOGE(LABEL, "%{public}s:set registry fail, driver error %{public}d", __func__, result);
803 return false;
804 }
805
806 return true;
807 }
808
FreeBuffer(void * data)809 void BinderInvoker::FreeBuffer(void *data)
810 {
811 size_t rewindPos = output_.GetWritePosition();
812 if (!output_.WriteUint32(BC_FREE_BUFFER)) {
813 return;
814 }
815
816 if (!output_.WritePointer((uintptr_t)data)) {
817 if (!output_.RewindWrite(rewindPos)) {
818 output_.FlushBuffer();
819 }
820 }
821 }
822
Dealloc(void * data)823 void BinderInvoker::BinderAllocator::Dealloc(void *data)
824 {
825 IRemoteInvoker *invoker = IPCThreadSkeleton::GetRemoteInvoker(IRemoteObject::IF_PROT_DEFAULT);
826 if (invoker != nullptr) {
827 invoker->FreeBuffer(data);
828 }
829 }
830
GetCallerPid() const831 pid_t BinderInvoker::GetCallerPid() const
832 {
833 return callerPid_;
834 }
835
GetCallerUid() const836 uid_t BinderInvoker::GetCallerUid() const
837 {
838 return callerUid_;
839 }
840
GetCallerTokenID() const841 uint32_t BinderInvoker::GetCallerTokenID() const
842 {
843 return callerTokenID_;
844 }
845
GetFirstTokenID() const846 uint32_t BinderInvoker::GetFirstTokenID() const
847 {
848 if (firstTokenID_ == 0) {
849 return (uint32_t)RpcGetFirstCallerTokenID();
850 }
851 return firstTokenID_;
852 }
853
GetStatus() const854 uint32_t BinderInvoker::GetStatus() const
855 {
856 return status_;
857 }
858
SetStatus(uint32_t status)859 void BinderInvoker::SetStatus(uint32_t status)
860 {
861 status_ = status;
862 }
863
GetLocalDeviceID()864 std::string BinderInvoker::GetLocalDeviceID()
865 {
866 return "";
867 }
868
GetCallerDeviceID() const869 std::string BinderInvoker::GetCallerDeviceID() const
870 {
871 return "";
872 }
873
IsLocalCalling()874 bool BinderInvoker::IsLocalCalling()
875 {
876 return true;
877 }
878
FlattenObject(Parcel & parcel,const IRemoteObject * object) const879 bool BinderInvoker::FlattenObject(Parcel &parcel, const IRemoteObject *object) const
880 {
881 if (object == nullptr) {
882 return false;
883 }
884 flat_binder_object flat;
885 if (object->IsProxyObject()) {
886 const IPCObjectProxy *proxy = reinterpret_cast<const IPCObjectProxy *>(object);
887 const int32_t handle = proxy ? (int32_t)(proxy->GetHandle()) : -1;
888 flat.hdr.type = BINDER_TYPE_HANDLE;
889 flat.binder = 0;
890 flat.handle = (uint32_t)handle;
891 flat.cookie = proxy ? static_cast<binder_uintptr_t>(proxy->GetProto()) : 0;
892 } else {
893 flat.hdr.type = BINDER_TYPE_BINDER;
894 flat.binder = reinterpret_cast<uintptr_t>(object);
895 flat.cookie = flat.binder;
896 }
897
898 flat.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
899 bool status = parcel.WriteBuffer(&flat, sizeof(flat_binder_object));
900 if (!status) {
901 ZLOGE(LABEL, "Fail to flatten object");
902 #ifndef BUILD_PUBLIC_VERSION
903 ReportDriverEvent(DbinderErrorCode::COMMON_DRIVER_ERROR, DbinderErrorCode::ERROR_TYPE,
904 DbinderErrorCode::IPC_DRIVER, DbinderErrorCode::ERROR_CODE, DbinderErrorCode::FLATTEN_OBJECT_FAILURE);
905 #endif
906 }
907 return status;
908 }
909
UnflattenObject(Parcel & parcel)910 sptr<IRemoteObject> BinderInvoker::UnflattenObject(Parcel &parcel)
911 {
912 const uint8_t *buffer = parcel.ReadBuffer(sizeof(flat_binder_object));
913 if (buffer == nullptr) {
914 ZLOGE(LABEL, "UnflattenObject null object buffer");
915 return nullptr;
916 }
917
918 IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
919 if (current == nullptr) {
920 return nullptr;
921 }
922
923 sptr<IRemoteObject> remoteObject = nullptr;
924 auto *flat = reinterpret_cast<const flat_binder_object *>(buffer);
925 switch (flat->hdr.type) {
926 case BINDER_TYPE_BINDER: {
927 remoteObject = reinterpret_cast<IRemoteObject *>(flat->cookie);
928 if (!current->IsContainsObject(remoteObject)) {
929 remoteObject = nullptr;
930 }
931 break;
932 }
933 case BINDER_TYPE_REMOTE_HANDLE:
934 case BINDER_TYPE_HANDLE: {
935 remoteObject = current->FindOrNewObject(flat->handle);
936 break;
937 }
938 default:
939 ZLOGE(LABEL, "%s: unknown binder type %u", __func__, flat->hdr.type);
940 remoteObject = nullptr;
941 break;
942 }
943
944 return remoteObject;
945 }
946
ReadFileDescriptor(Parcel & parcel)947 int BinderInvoker::ReadFileDescriptor(Parcel &parcel)
948 {
949 int fd = -1;
950 const uint8_t *buffer = parcel.ReadBuffer(sizeof(flat_binder_object));
951 if (buffer == nullptr) {
952 ZLOGE(LABEL, "UnflattenObject null object buffer");
953 return fd;
954 }
955
956 auto *flat = reinterpret_cast<const flat_binder_object *>(buffer);
957 if (flat->hdr.type == BINDER_TYPE_FD || flat->hdr.type == BINDER_TYPE_FDR) {
958 fd = flat->handle;
959 } else {
960 ZLOGE(LABEL, "%s: unknown binder type %u", __func__, flat->hdr.type);
961 }
962
963 return fd;
964 }
965
WriteFileDescriptor(Parcel & parcel,int fd,bool takeOwnership)966 bool BinderInvoker::WriteFileDescriptor(Parcel &parcel, int fd, bool takeOwnership)
967 {
968 flat_binder_object flat;
969 flat.hdr.type = BINDER_TYPE_FD;
970 flat.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
971 flat.binder = 0; // Don't pass uninitialized stack data to a remote process
972 flat.handle = (uint32_t)fd;
973 flat.cookie = takeOwnership ? 1 : 0;
974
975 return parcel.WriteBuffer(&flat, sizeof(flat_binder_object));
976 }
977
ResetCallingIdentity()978 std::string BinderInvoker::ResetCallingIdentity()
979 {
980 char buf[ACCESS_TOKEN_MAX_LEN + 1] = {0};
981 int ret = sprintf_s(buf, ACCESS_TOKEN_MAX_LEN + 1, "%010u", callerTokenID_);
982 if (ret < 0) {
983 ZLOGE(LABEL, "%s: sprintf callerTokenID_ %u failed", __func__, callerTokenID_);
984 return "";
985 }
986 std::string accessToken(buf);
987 std::string pidUid = std::to_string(((static_cast<uint64_t>(callerUid_) << PID_LEN)
988 | static_cast<uint64_t>(callerPid_)));
989 callerUid_ = (pid_t)getuid();
990 callerPid_ = getpid();
991 callerTokenID_ = (uint32_t)RpcGetSelfTokenID();
992 return accessToken + pidUid;
993 }
994
SetCallingIdentity(std::string & identity)995 bool BinderInvoker::SetCallingIdentity(std::string &identity)
996 {
997 if (identity.empty() || identity.length() <= ACCESS_TOKEN_MAX_LEN) {
998 return false;
999 }
1000
1001 uint64_t pidUid =
1002 std::stoull(identity.substr(ACCESS_TOKEN_MAX_LEN, identity.length() - ACCESS_TOKEN_MAX_LEN).c_str());
1003 callerUid_ = static_cast<int>(pidUid >> PID_LEN);
1004 callerPid_ = static_cast<int>(pidUid);
1005 callerTokenID_ = static_cast<uint32_t>(std::atoi(identity.substr(0, ACCESS_TOKEN_MAX_LEN).c_str()));
1006 return true;
1007 }
1008 #ifdef CONFIG_IPC_SINGLE
1009 } // namespace IPC_SINGLE
1010 #endif
1011 } // namespace OHOS
1012