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 "serializer.h"
17 #include "serializer_inner.h"
18
19 #include "ipc_process_skeleton.h"
20 #include "rpc_log.h"
21 #include "securec.h"
22 #include "sys_binder.h"
23
IoPushBinderObj(IpcIo * io)24 static struct flat_binder_object *IoPushBinderObj(IpcIo *io)
25 {
26 if (io->offsetsCur == NULL) {
27 RPC_LOG_ERROR("Io push object current is null.");
28 return NULL;
29 }
30 struct flat_binder_object *ptr = NULL;
31 ptr = IoPush(io, sizeof(struct flat_binder_object));
32 if ((ptr != NULL) && io->offsetsLeft) {
33 io->offsetsLeft--;
34 *(io->offsetsCur) = (char*)ptr - (char*)io->bufferBase;
35 io->offsetsCur++;
36 return ptr;
37 } else {
38 io->flag |= IPC_IO_OVERFLOW;
39 return NULL;
40 }
41 }
42
IpcIoPushObject(IpcIo * io,uint32_t token,uintptr_t cookie)43 static bool IpcIoPushObject(IpcIo *io, uint32_t token, uintptr_t cookie)
44 {
45 struct flat_binder_object *ptr = IoPushBinderObj(io);
46 if (ptr == NULL) {
47 RPC_LOG_ERROR("Io push object IPC_IO_OVERFLOW.");
48 return false;
49 }
50 ptr->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
51 ptr->type = BINDER_TYPE_BINDER;
52 ptr->binder = (uintptr_t)cookie;
53 ptr->cookie = cookie;
54 return true;
55 }
56
IpcIoPushRef(IpcIo * io,uint32_t handle,uintptr_t cookie)57 static bool IpcIoPushRef(IpcIo *io, uint32_t handle, uintptr_t cookie)
58 {
59 struct flat_binder_object *ptr = IoPushBinderObj(io);
60 if (ptr == NULL) {
61 RPC_LOG_ERROR("Io push ref IPC_IO_OVERFLOW.");
62 return false;
63 }
64 ptr->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
65 ptr->type = BINDER_TYPE_HANDLE;
66 ptr->handle = handle;
67 ptr->cookie = cookie;
68 return true;
69 }
70
IpcIoPopRef(IpcIo * io)71 static struct flat_binder_object *IpcIoPopRef(IpcIo *io)
72 {
73 if (io->offsetsCur == NULL) {
74 RPC_LOG_ERROR("Io push object current is null.");
75 return NULL;
76 }
77 if (io->offsetsLeft == 0) {
78 io->flag |= IPC_IO_OVERFLOW;
79 return NULL;
80 }
81 struct flat_binder_object *obj = (struct flat_binder_object *)IoPop(io, sizeof(struct flat_binder_object));
82 if (obj != NULL) {
83 io->offsetsCur++;
84 io->offsetsLeft--;
85 return obj;
86 }
87 return NULL;
88 }
89
WriteRemoteObject(IpcIo * io,const SvcIdentity * svc)90 bool WriteRemoteObject(IpcIo *io, const SvcIdentity *svc)
91 {
92 if (io == NULL || svc == NULL) {
93 RPC_LOG_ERROR("push io or svc is NULL ...");
94 return false;
95 }
96 bool res;
97 if (svc->handle <= 0) {
98 res = IpcIoPushObject(io, svc->token, svc->cookie);
99 } else {
100 res = IpcIoPushRef(io, svc->handle, svc->cookie);
101 }
102 return res;
103 }
104
ReadRemoteObject(IpcIo * io,SvcIdentity * svc)105 bool ReadRemoteObject(IpcIo *io, SvcIdentity *svc)
106 {
107 if (io == NULL || svc == NULL) {
108 return false;
109 }
110 struct flat_binder_object *obj = IpcIoPopRef(io);
111 if (obj == NULL) {
112 RPC_LOG_ERROR("ReadRemoteObject failed: obj is null");
113 return false;
114 }
115 if (obj->type == BINDER_TYPE_BINDER) {
116 svc->token = obj->binder;
117 svc->handle = IPC_INVALID_HANDLE;
118 svc->cookie = obj->cookie;
119 } else {
120 svc->handle = obj->handle;
121 svc->cookie = obj->cookie;
122 WaitForProxyInit(svc);
123 }
124 return true;
125 }
126
WriteFileDescriptor(IpcIo * io,uint32_t fd)127 bool WriteFileDescriptor(IpcIo *io, uint32_t fd)
128 {
129 if (io == NULL) {
130 RPC_LOG_ERROR("push fd io is NULL.");
131 return false;
132 }
133 struct flat_binder_object *ptr = IoPushBinderObj(io);
134 if (ptr == NULL) {
135 RPC_LOG_ERROR("Io push fd IPC_IO_OVERFLOW.\n");
136 return false;
137 }
138 ptr->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
139 ptr->type = BINDER_TYPE_FD;
140 ptr->binder = 0;
141 ptr->cookie = 1;
142 ptr->handle = fd;
143 return true;
144 }
145
ReadFileDescriptor(IpcIo * io)146 int32_t ReadFileDescriptor(IpcIo *io)
147 {
148 if (io == NULL) {
149 return -1;
150 }
151 struct flat_binder_object *obj = IpcIoPopRef(io);
152 if (obj == NULL) {
153 RPC_LOG_ERROR("ReadFileDescriptor failed: obj is null");
154 return -1;
155 }
156 if (obj->type == BINDER_TYPE_FD) {
157 return obj->handle;
158 }
159 RPC_LOG_ERROR("ReadFileDescriptor failed: type:%d", obj->type);
160 return -1;
161 }
162