• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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