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 "ipc_invoker.h"
17 
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <sys/ioctl.h>
23 #include <sys/mman.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26 
27 #include "ipc_process_skeleton.h"
28 #include "ipc_thread_pool.h"
29 #include "ipc_types.h"
30 #include "rpc_errno.h"
31 #include "rpc_log.h"
32 #include "rpc_os_adapter.h"
33 #include "rpc_types.h"
34 #include "securec.h"
35 #include "sys_binder.h"
36 
37 #define READ_BUFFER_SIZE 32
38 
39 #define ALIGN_SZ 4
40 #define IPC_IO_ALIGN(sz) (((sz) + ALIGN_SZ - 1) & (~(ALIGN_SZ - 1)))
41 
42 typedef struct {
43     int32_t fd;
44     size_t mmapSize;
45     void *mmapAddr;
46 } BinderConnector;
47 
48 struct FreeData {
49     uint32_t cmd;
50     binder_uintptr_t buffer;
51 }__attribute__((packed));
52 
53 struct TransactData {
54     uint32_t cmd;
55     struct binder_transaction_data btd;
56 }__attribute__((packed));
57 
58 static RemoteInvoker g_ipcInvoker;
59 static BinderConnector *g_connector = NULL;
60 static pthread_mutex_t g_connectorMutex = PTHREAD_MUTEX_INITIALIZER;
61 
OpenDriver(void)62 static BinderConnector *OpenDriver(void)
63 {
64     BinderConnector *connector = (BinderConnector *)calloc(1, sizeof(BinderConnector));
65     if (connector == NULL) {
66         RPC_LOG_ERROR("ipc open driver malloc failed.");
67         return NULL;
68     }
69     connector->fd = open(BINDER_DRIVER, O_RDWR);
70     if (connector->fd < 0) {
71         RPC_LOG_ERROR("Open liteipc driver failed error %d.", errno);
72         goto OPEN_ERR;
73     }
74     connector->mmapAddr = mmap(NULL, MMAP_MAX_SIZE, PROT_READ, MAP_PRIVATE, connector->fd, 0);
75     if (connector->mmapAddr == MAP_FAILED) {
76         RPC_LOG_ERROR("Mmap failed.");
77         goto MMAP_ERR;
78     }
79     connector->mmapSize = MMAP_MAX_SIZE;
80     return connector;
81 
82 MMAP_ERR:
83     close(connector->fd);
84 OPEN_ERR:
85     free(connector);
86     return NULL;
87 }
88 
DeleteBinderConnector(void)89 static void DeleteBinderConnector(void)
90 {
91     if (g_connector == NULL) {
92         return;
93     }
94     pthread_mutex_lock(&g_connectorMutex);
95     munmap(g_connector->mmapAddr, g_connector->mmapSize);
96     close(g_connector->fd);
97     free(g_connector);
98     g_connector = NULL;
99     pthread_mutex_unlock(&g_connectorMutex);
100 }
101 
BinderWrite(void * data,size_t len)102 static int32_t BinderWrite(void *data, size_t len)
103 {
104     struct binder_write_read bwr;
105     int32_t res;
106 
107     bwr.write_size = len;
108     bwr.write_consumed = 0;
109     bwr.write_buffer = (uintptr_t)data;
110     bwr.read_size = 0;
111     bwr.read_consumed = 0;
112     bwr.read_buffer = 0;
113     res = ioctl(g_connector->fd, BINDER_WRITE_READ, &bwr);
114     if (res < 0) {
115         RPC_LOG_ERROR("binder write ioctl failed errno = %d.", errno);
116         return IPC_INVOKER_IOCTL_FAILED;
117     }
118     return ERR_NONE;
119 }
120 
AcquireHandle(int32_t handle)121 static int32_t AcquireHandle(int32_t handle)
122 {
123     uint32_t cmd[2];
124     cmd[0] = BC_ACQUIRE;
125     cmd[1] = handle;
126     int32_t ret = BinderWrite(&cmd, sizeof(cmd));
127     return ret;
128 }
129 
ReleaseHandle(int32_t handle)130 static int32_t ReleaseHandle(int32_t handle)
131 {
132     RPC_LOG_ERROR("SA dead delete it, handle = %d.", handle);
133     uint32_t cmd[2];
134     cmd[0] = BC_RELEASE;
135     cmd[1] = handle;
136     int32_t ret = BinderWrite(&cmd, sizeof(cmd));
137     return ret;
138 }
139 
ToTransData(uint32_t handle,uint32_t code,uint32_t option,const IpcIo * data,struct TransactData * buf)140 static void ToTransData(uint32_t handle, uint32_t code, uint32_t option,
141     const IpcIo *data, struct TransactData *buf)
142 {
143     buf->btd.target.handle = handle;
144     buf->btd.code = code;
145     buf->btd.flags = option;
146     buf->btd.cookie = 0;
147     buf->btd.sender_pid = RpcGetPid();
148     buf->btd.sender_euid = RpcGetUid();
149     buf->btd.data_size = (data == NULL) ? 0 : (data->bufferCur - data->bufferBase);
150     buf->btd.data.ptr.buffer = (data == NULL) ? 0 : (binder_uintptr_t)data->bufferBase;
151     buf->btd.offsets_size = (data == NULL) ? 0 : ((char*)data->offsetsCur - (char*)data->offsetsBase);
152     buf->btd.offsets_size = IPC_IO_ALIGN(buf->btd.offsets_size);
153     buf->btd.data.ptr.offsets = (data == NULL) ? 0 : (binder_uintptr_t)data->offsetsBase;
154 }
155 
ToIpcData(const struct binder_transaction_data * tr,IpcIo * data)156 static void ToIpcData(const struct binder_transaction_data *tr, IpcIo *data)
157 {
158     data->bufferBase = data->bufferCur = (char *)tr->data.ptr.buffer;
159     data->bufferLeft = (size_t)tr->data_size;
160     data->offsetsBase = data->offsetsCur = (size_t *)tr->data.ptr.offsets;
161     data->offsetsLeft = (tr->offsets_size) / sizeof(binder_size_t);
162     data->flag = IPC_IO_INITIALIZED;
163 }
164 
BinderRefDone(const struct binder_ptr_cookie * ptrCookie,uint32_t cmd)165 static void BinderRefDone(const struct binder_ptr_cookie *ptrCookie, uint32_t cmd)
166 {
167     struct {
168         uint32_t cmd;
169         struct binder_ptr_cookie payload;
170     } __attribute__((packed)) data;
171 
172     if (cmd == BR_ACQUIRE) {
173         data.cmd = BC_ACQUIRE_DONE;
174     } else {
175         data.cmd = BC_INCREFS_DONE;
176     }
177     data.payload.ptr = ptrCookie->ptr;
178     data.payload.cookie = ptrCookie->cookie;
179     BinderWrite(&data, sizeof(data));
180 }
181 
IpcFreeBuffer(void * ptr)182 static int32_t IpcFreeBuffer(void *ptr)
183 {
184     if (ptr == NULL) {
185         return ERR_NONE;
186     }
187 
188     struct FreeData data = {0};
189     data.cmd = BC_FREE_BUFFER;
190     data.buffer = (binder_uintptr_t)ptr;
191     int32_t ret = BinderWrite(&data, sizeof(data));
192     return ret;
193 }
194 
SendReply(IpcIo * reply,const int32_t * status)195 static int32_t SendReply(IpcIo *reply, const int32_t *status)
196 {
197     struct TransactData buf;
198     buf.cmd = BC_REPLY;
199     int32_t ret;
200     if (reply->bufferCur > reply->bufferBase) {
201         ToTransData(0, 0, 0, reply, &buf);
202     } else if (status != NULL) {
203         buf.btd.flags = TF_OP_STATUS_CODE;
204         buf.btd.data_size = sizeof(int32_t);
205         buf.btd.offsets_size = 0;
206         buf.btd.data.ptr.buffer = (uintptr_t)status;
207         buf.btd.data.ptr.offsets = 0;
208     }
209     ret = BinderWrite(&buf, sizeof(buf));
210     return ret;
211 }
212 
HandleTransaction(const struct binder_transaction_data * tr)213 static void HandleTransaction(const struct binder_transaction_data *tr)
214 {
215     ThreadContext *threadContext = GetCurrentThreadContext();
216     const pid_t oldPid = threadContext->callerPid;
217     const pid_t oldUid = threadContext->callerUid;
218     threadContext->callerPid = tr->sender_pid;
219     threadContext->callerUid = (pid_t)tr->sender_euid;
220     IpcObjectStub *objectStub;
221     if (tr->target.ptr != 0) {
222         objectStub = (IpcObjectStub *)tr->cookie;
223     } else {
224         objectStub = (IpcObjectStub *)(GetRegistryObject()->cookie);
225     }
226     threadContext->objectStub = objectStub;
227     IpcIo data;
228     ToIpcData(tr, &data);
229     MessageOption option = {
230         .flags = tr->flags,
231         .args = objectStub->args
232     };
233     IpcIo reply;
234     uint8 tempData[MAX_IO_SIZE];
235     IpcIoInit(&reply, tempData, MAX_IO_SIZE, MAX_OBJ_NUM);
236     int32_t error = OnRemoteRequestInner(tr->code, &data, &reply, option, objectStub);
237     if (tr->flags & TF_ONE_WAY) {
238         IpcFreeBuffer((void *)(tr->data.ptr.buffer));
239     } else {
240         IpcFreeBuffer((void *)(tr->data.ptr.buffer));
241         SendReply(&reply, &error);
242     }
243     threadContext->callerPid = oldPid;
244     threadContext->callerUid = oldUid;
245 }
246 
HandleReply(IpcIo * reply,const struct binder_transaction_data * tr,uintptr_t * buffer)247 static void HandleReply(IpcIo *reply, const struct binder_transaction_data *tr, uintptr_t *buffer)
248 {
249     if (reply == NULL || buffer == NULL) {
250         RPC_LOG_ERROR("no need reply, free the buffer.");
251         IpcFreeBuffer((void *)(tr->data.ptr.buffer));
252         return;
253     }
254     ToIpcData(tr, reply);
255     *buffer = (uintptr_t)tr->data.ptr.buffer;
256 }
257 
HandleDeadBinderDone(void * cookie)258 static void HandleDeadBinderDone(void *cookie)
259 {
260     struct {
261         uint32_t cmd;
262         binder_uintptr_t cookie;
263     } __attribute__((packed)) data;
264     data.cmd = BC_DEAD_BINDER_DONE;
265     data.cookie = (binder_uintptr_t)cookie;
266     BinderWrite(&data, sizeof(data));
267 }
268 
HandleDeadBinder(uintptr_t ptr)269 static void HandleDeadBinder(uintptr_t ptr)
270 {
271     DeathCallback *death = (DeathCallback *)(uintptr_t) *(binder_uintptr_t *)ptr;
272     if (death != NULL) {
273         RPC_LOG_INFO("dead binder now call SendObituary.");
274         SendObituary(death);
275         HandleDeadBinderDone(death);
276     }
277 }
278 
BinderParse(IpcIo * reply,uintptr_t ptr,size_t size,uintptr_t * buffer)279 static int32_t BinderParse(IpcIo *reply, uintptr_t ptr, size_t size, uintptr_t *buffer)
280 {
281     int32_t ret = 1;
282     uintptr_t end = ptr + (uintptr_t) size;
283     while (ptr < end) {
284         uint32_t cmd = *(uint32_t *) ptr;
285         ptr += sizeof(uint32_t);
286         switch (cmd) {
287             case BR_NOOP:
288             case BR_TRANSACTION_COMPLETE:
289                 break;
290             case BR_INCREFS:
291             case BR_ACQUIRE: {
292                 struct binder_ptr_cookie *ptrCookie = (struct binder_ptr_cookie *) ptr;
293                 if ((end - ptr) < sizeof(*ptrCookie)) {
294                     return IPC_INVOKER_INVALID_DATA;
295                 }
296                 BinderRefDone(ptrCookie, cmd);
297                 ptr += sizeof(*ptrCookie);
298                 break;
299             }
300             case BR_RELEASE:
301             case BR_DECREFS:
302                 ptr += sizeof(struct binder_ptr_cookie);
303                 break;
304             case BR_SPAWN_LOOPER: {
305                 SpawnThread(SPAWN_PASSIVE, IF_PROT_DEFAULT);
306                 break;
307             }
308             case BR_TRANSACTION: {
309                 struct binder_transaction_data *tr = (struct binder_transaction_data *) ptr;
310                 if ((end - ptr) < sizeof(*tr)) {
311                     return IPC_INVOKER_INVALID_DATA;
312                 }
313                 HandleTransaction(tr);
314                 ptr += sizeof(*tr);
315                 break;
316             }
317             case BR_REPLY: {
318                 struct binder_transaction_data *tr = (struct binder_transaction_data *) ptr;
319                 if ((end - ptr) < sizeof(*tr)) {
320                     return IPC_INVOKER_INVALID_DATA;
321                 }
322                 HandleReply(reply, tr, buffer);
323                 ptr += sizeof(*tr);
324                 ret = 0;
325                 break;
326             }
327             case BR_DEAD_BINDER: {
328                 HandleDeadBinder(ptr);
329                 ptr += sizeof(binder_uintptr_t);
330                 break;
331             }
332             case BR_CLEAR_DEATH_NOTIFICATION_DONE: {
333                 ptr += sizeof(binder_uintptr_t);
334                 break;
335             }
336             case BR_FAILED_REPLY:
337                 ret = IPC_INVOKER_FAILED_REPLY;
338                 break;
339             case BR_DEAD_REPLY:
340                 ret = ERR_DEAD_OBJECT;
341                 break;
342             default:
343                 ret = IPC_INVOKER_UNKNOWN_CODE;
344         }
345     }
346     return ret;
347 }
348 
IpcJoinThread(bool initiative)349 static void IpcJoinThread(bool initiative)
350 {
351     struct binder_write_read bwr;
352     uint32_t readbuf[READ_BUFFER_SIZE];
353     int32_t ret;
354 
355     bwr.write_size = 0;
356     bwr.write_consumed = 0;
357     bwr.write_buffer = 0;
358 
359     if (initiative) {
360         readbuf[0] = BC_ENTER_LOOPER;
361     } else {
362         readbuf[0] = BC_REGISTER_LOOPER;
363     }
364     BinderWrite(readbuf, sizeof(uint32_t));
365     for (; ;) {
366         bwr.read_size = sizeof(readbuf);
367         bwr.read_consumed = 0;
368         bwr.read_buffer = (uintptr_t)readbuf;
369         ret = ioctl(g_connector->fd, BINDER_WRITE_READ, &bwr);
370         if (ret < 0) {
371             RPC_LOG_ERROR("ioctl failed errno = %d.", errno);
372             break;
373         }
374         ret = BinderParse(0, (uintptr_t)readbuf, bwr.read_consumed, NULL);
375         if (ret == 0) {
376             RPC_LOG_ERROR("unexpected reply");
377             break;
378         }
379         if (ret < 0) {
380             RPC_LOG_ERROR("io error ret = %d errno = %d.", ret, errno);
381             break;
382         }
383     }
384 }
385 
IpcSetMaxWorkThread(int32_t maxThreadNum)386 static int32_t IpcSetMaxWorkThread(int32_t maxThreadNum)
387 {
388     if (g_connector == NULL) {
389         RPC_LOG_ERROR("ipc driver not init");
390         return ERR_FAILED;
391     }
392     int32_t ret = ioctl(g_connector->fd, BINDER_SET_MAX_THREADS, &maxThreadNum);
393     return ret;
394 }
395 
IpcSetRegistryObject(SvcIdentity target,SvcIdentity * samgr)396 static int32_t IpcSetRegistryObject(SvcIdentity target, SvcIdentity *samgr)
397 {
398     if (g_connector == NULL) {
399         RPC_LOG_ERROR("ipc driver not init");
400         return ERR_FAILED;
401     }
402     int32_t ret = ioctl(g_connector->fd, BINDER_SET_CONTEXT_MGR, 0);
403     if (ret == ERR_NONE) {
404         samgr->handle = -1;
405         samgr->cookie = target.cookie;
406         RPC_LOG_INFO("set samgr success!!");
407         return ERR_NONE;
408     }
409     RPC_LOG_ERROR("set samgr failed");
410     return ERR_FAILED;
411 }
412 
InternalRequest(SvcIdentity sid,uint32_t code,IpcIo * data,IpcIo * reply,uint32_t flags)413 static int32_t InternalRequest(SvcIdentity sid, uint32_t code, IpcIo *data, IpcIo *reply, uint32_t flags)
414 {
415     RPC_LOG_INFO("Internal ipc request called");
416     IpcObjectStub *objectStub = (IpcObjectStub *)(sid.cookie);
417     if (objectStub == NULL) {
418         RPC_LOG_INFO("ipc object stub is null");
419         return ERR_INVALID_PARAM;
420     }
421     if (data != NULL && data->flag == IPC_IO_INITIALIZED) {
422         data->bufferLeft = data->bufferCur - data->bufferBase;
423         data->offsetsLeft = ((char*)data->offsetsCur - (char*)data->offsetsBase) / sizeof(size_t);
424         data->bufferCur = data->bufferBase;
425         data->offsetsCur = data->offsetsBase;
426     }
427     if (flags == TF_OP_SYNC && reply != NULL) {
428         uint8 tempData[MAX_IO_SIZE];
429         IpcIoInit(reply, tempData, MAX_IO_SIZE, MAX_OBJ_NUM);
430     }
431     MessageOption option = {
432         .flags = flags,
433         .args = objectStub->args
434     };
435     int32_t error = OnRemoteRequestInner(code, data, reply, option, objectStub);
436     if (flags == TF_OP_SYNC && reply != NULL) {
437         reply->bufferLeft = reply->bufferCur - reply->bufferBase;
438         reply->offsetsLeft = ((char*)reply->offsetsCur - (char*)reply->offsetsBase) / sizeof(size_t);
439         reply->bufferCur = reply->bufferBase;
440         reply->offsetsCur = reply->offsetsBase;
441     }
442     return error;
443 }
444 
IpcSendRequest(SvcIdentity target,uint32_t code,IpcIo * data,IpcIo * reply,MessageOption option,uintptr_t * buffer)445 static int32_t IpcSendRequest(SvcIdentity target, uint32_t code, IpcIo *data, IpcIo *reply,
446     MessageOption option, uintptr_t *buffer)
447 {
448     if (g_connector == NULL) {
449         return ERR_FAILED;
450     }
451     if (target.handle < 0) {
452         if (buffer != NULL) {
453             *buffer = 0;
454         }
455         return InternalRequest(target, code, data, reply, option.flags);
456     }
457     int32_t ret;
458     struct TransactData buf;
459     buf.cmd = BC_TRANSACTION;
460     ToTransData(target.handle, code, option.flags, data, &buf);
461     struct binder_write_read bwr = {.write_size = sizeof(buf), .write_consumed = 0, .write_buffer = (uintptr_t)&buf};
462     uint32_t readbuf[READ_BUFFER_SIZE] = {0};
463     if (option.flags != TF_OP_ASYNC) {
464         while (1) {
465             bwr.read_size = sizeof(readbuf);
466             bwr.read_consumed = 0;
467             bwr.read_buffer = (uintptr_t)readbuf;
468             if (ioctl(g_connector->fd, BINDER_WRITE_READ, &bwr) < ERR_NONE) {
469                 RPC_LOG_ERROR("ipc send request ioctl failed.");
470                 return IPC_INVOKER_IOCTL_FAILED;
471             }
472             ret = BinderParse(reply, (uintptr_t)readbuf, bwr.read_consumed, buffer);
473             if (ret == 0) {
474                 break;
475             }
476             if (ret < 0) {
477                 RPC_LOG_ERROR("ipc send request failed res = %d.", ret);
478                 break;
479             }
480         }
481     } else {
482         if (buffer != NULL) {
483             *buffer = 0;
484         }
485         bwr.read_size = sizeof(readbuf);
486         bwr.read_consumed = 0;
487         bwr.read_buffer = (uintptr_t)readbuf;
488         if (ioctl(g_connector->fd, BINDER_WRITE_READ, &bwr) < ERR_NONE) {
489             RPC_LOG_ERROR("ipc send request ioctl failed.");
490             return IPC_INVOKER_IOCTL_FAILED;
491         }
492         ret = BinderParse(reply, (uintptr_t)readbuf, bwr.read_consumed, NULL);
493         ret = (ret == 1) ? 0 : ret;
494     }
495     return ret;
496 }
497 
IpcAddDeathRecipient(int32_t handle,void * cookie)498 static int32_t IpcAddDeathRecipient(int32_t handle, void *cookie)
499 {
500     struct {
501         uint32_t cmd;
502         struct binder_handle_cookie payload;
503     } __attribute__((packed)) data;
504     data.cmd = BC_REQUEST_DEATH_NOTIFICATION;
505     data.payload.handle = handle;
506     data.payload.cookie = (binder_uintptr_t)cookie;
507     return BinderWrite(&data, sizeof(data));
508 }
509 
IpcRemoveDeathRecipient(int32_t handle,void * cookie)510 static int32_t IpcRemoveDeathRecipient(int32_t handle, void *cookie)
511 {
512     struct {
513         uint32_t cmd;
514         struct binder_handle_cookie payload;
515     } __attribute__((packed)) data;
516 
517     data.cmd = BC_CLEAR_DEATH_NOTIFICATION;
518     data.payload.handle = handle;
519     data.payload.cookie = (binder_uintptr_t)cookie;
520     return BinderWrite(&data, sizeof(data));
521 }
522 
IpcExitCurrentThread(void)523 static void IpcExitCurrentThread(void)
524 {
525     ioctl(g_connector->fd, BINDER_THREAD_EXIT, 0);
526 }
527 
InvokerResetIpc(void)528 static void InvokerResetIpc(void) {}
529 
InitBinderConnector(void)530 static BinderConnector *InitBinderConnector(void)
531 {
532     if (g_connector == NULL) {
533         if (pthread_mutex_lock(&g_connectorMutex) != 0) {
534             RPC_LOG_ERROR("init binder connector lock failed.");
535             return NULL;
536         }
537         if (g_connector == NULL) {
538             BinderConnector *temp = OpenDriver();
539             if (temp == NULL) {
540                 pthread_mutex_unlock(&g_connectorMutex);
541                 RPC_LOG_ERROR("create binder connector  failed.");
542                 return NULL;
543             }
544             g_connector = temp;
545             g_ipcInvoker.connector = g_connector;
546             g_ipcInvoker.AcquireHandle = AcquireHandle;
547             g_ipcInvoker.ReleaseHandle = ReleaseHandle;
548             g_ipcInvoker.SendRequest = IpcSendRequest;
549             g_ipcInvoker.FreeBuffer = IpcFreeBuffer;
550             g_ipcInvoker.SetMaxWorkThread = IpcSetMaxWorkThread;
551             g_ipcInvoker.JoinThread = IpcJoinThread;
552             g_ipcInvoker.SetRegistryObject = IpcSetRegistryObject;
553             g_ipcInvoker.AddDeathRecipient = IpcAddDeathRecipient;
554             g_ipcInvoker.RemoveDeathRecipient = IpcRemoveDeathRecipient;
555             g_ipcInvoker.ExitCurrentThread = IpcExitCurrentThread;
556             g_ipcInvoker.InvokerResetIpc = InvokerResetIpc;
557         }
558         pthread_mutex_unlock(&g_connectorMutex);
559     }
560     return g_connector;
561 }
562 
GetIpcInvoker(void)563 RemoteInvoker *GetIpcInvoker(void)
564 {
565     if (InitBinderConnector() == NULL) {
566         RPC_LOG_ERROR("init binder invoker failed.");
567         return NULL;
568     }
569     return &g_ipcInvoker;
570 }
571 
DeinitIpcInvoker(RemoteInvoker * invoker)572 void DeinitIpcInvoker(RemoteInvoker *invoker)
573 {
574     if (invoker != &g_ipcInvoker) {
575         return;
576     }
577     DeleteBinderConnector();
578 }