• 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 "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