1 /*
2  * Copyright (c) 2020, Google Inc. All rights reserved
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files
6  * (the "Software"), to deal in the Software without restriction,
7  * including without limitation the rights to use, copy, modify, merge,
8  * publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 #pragma once
24 
25 #include <kernel/event.h>
26 #include <kernel/thread.h>
27 #include <lib/trusty/handle_set.h>
28 #include <lib/trusty/ipc_msg.h>
29 #include <lib/trusty/uio.h>
30 
31 __BEGIN_CDECLS
32 
33 struct ktipc_server {
34     const char* name;
35     struct handle* hset;
36     struct thread* thread;
37     struct event have_handles_evt;
38 };
39 
40 /**
41  * KTIPC_SERVER_INITIAL_VALUE() - ktipc server static initializer
42  * @ksrv: pointer to @struct ktipc_server to initialize
43  * @name: server name
44  *
45  * @name should not be deallocated while server is running
46  */
47 #define KTIPC_SERVER_INITIAL_VALUE(ksrv, nm)                          \
48     {                                                                 \
49         .name = (nm), .hset = NULL, .thread = NULL,                   \
50         .have_handles_evt =                                           \
51                 EVENT_INITIAL_VALUE(ksrv.have_handles_evt, false, 0), \
52     }
53 
54 /**
55  * ktipc_server_init() - initialize ktipc server structure
56  * @ksrv: pointer to @struct ktipc_server to initialize
57  * @name: server name
58  *
59  * @name should not be deallocated while server is running
60  *
61  * Return: none
62  */
ktipc_server_init(struct ktipc_server * ksrv,const char * name)63 static inline void ktipc_server_init(struct ktipc_server* ksrv,
64                                      const char* name) {
65     ksrv->name = name;
66     ksrv->hset = NULL;
67     ksrv->thread = NULL;
68     event_init(&ksrv->have_handles_evt, false, 0);
69 }
70 
71 /**
72  *  ktipc_server_start() - start specified ktipc server
73  *  @server: server to start
74  *  @name: server name
75  *
76  *  The &struct ktipc_server must be initialized by calling ktipc_server_init()
77  *  or static initializer KTIPC_SERVER_INITIAL_VALUE.
78  *
79  *
80  *  Return: 0 on success, negative error code otherwise
81  */
82 int ktipc_server_start(struct ktipc_server* server);
83 
84 /**
85  * struct tipc_port_acl - tipc port ACL descriptor
86  * @flags:      a combination of IPC_PORT_ALLOW_XXX_CONNECT flags that will be
87  *              directly passed to underlying port_create call.
88  * @uuid_num:   number of entries in an array pointed by @uuids field
89  * @uuids:      pointer to array of pointers to uuids of apps allowed to connect
90  * @extra_data: pointer to extra data associated with this ACL structure, which
91  *              can be used in application specific way.
92  *
93  * Note: @uuid_num parameter can be 0 to indicate that there is no filtering by
94  * UUID and connection from any client will be accepted. In this case @uuids
95  * parameter is ignored and can be set to NULL.
96  */
97 struct ktipc_port_acl {
98     uint32_t flags;
99     uint32_t uuid_num;
100     const struct uuid** uuids;
101     const void* extra_data;
102 };
103 
104 /**
105  * struct tipc_port - TIPC port descriptor
106  * @name:          port name
107  * @uuid:          UUID of the service
108  * @msg_max_size:  max message size supported
109  * @msg_queue_len: max number of messages in queue
110  * @acl:           pointer to &struct tipc_port_acl specifying ACL rules
111  * @priv:          port specific private data
112  *
113  * Note: @acl is a required parameter for specifying any port even if
114  * service does not require access control.
115  *
116  * Most services should use ``&kernel_uuid`` as the value of @uuid,
117  * unless there is a legitimate reason to use a different UUID.
118  */
119 struct ktipc_port {
120     const char* name;
121     const struct uuid* uuid;
122     uint32_t msg_max_size;
123     uint32_t msg_queue_len;
124     const struct ktipc_port_acl* acl;
125     const void* priv;
126 };
127 
128 /**
129  * struct ktipc_srv_ops - service specific ops (callbacks)
130  * @on_connect:    is invoked when a new connection is established.
131  * @on_message:    is invoked when a new message is available
132  * @on_disconnect: is invoked when the peer terminates connection
133  * @on_channel_cleanup: is invoked to cleanup user allocated state
134  * @on_send_unblocked:  is invoked when the channel is unblocked for sending
135  *
136  * The overall call flow is as follow:
137  *
138  * Upon receiving a connection request from client framework accepts it and
139  * validates against configured ACL rules. If connection is allowed, the
140  * framework allocates a channel tracking structure and invokes an optional
141  * @on_connect callback if specified. The user who choose to implement this
142  * callback can allocate its own tracking structure and return pointer to that
143  * through @ctx_p parameter. After that this pointer will be associated with
144  * particular channel and it will be passed to all other callbacks.
145  *
146  * Upon receiving a message directed to particular channel, a corresponding
147  * @on_message callback is invoked so this message can be handled according
148  * with application specific protocol. The @on_message call back is a
149  * mandatory in this implementation.
150  *
151  * Upon receiving a disconnect request an optional @on_disconnect callback is
152  * invoked to indicate that peer closed connection. At this point the channel
153  * is still alive but in disconnected state, it will be closed by framework
154  * after control returns from executing this callback.
155  *
156  * The @on_channel_cleanup callback is invoked by framework to give the user
157  * a chance to release channel specific resources if allocated by
158  * @on_connect callback, after the channel have been closed. This
159  * callback is mandatory if the user implements @on_connect callback and
160  * allocates per channel state.
161  *
162  * The @on_send_unblocked callback is invoked when a channel becomes unblocked
163  * for sending after an earlier %ERR_NOT_ENOUGH_BUFFER error code returned
164  * by tipc_send1() or ipc_send_msg().
165  *
166  * Note: an application implementing these callbacks MUST not close channel
167  * received as @chan parameter directly, instead it should return an error
168  * and the channel will be closed by the framework.
169  *
170  */
171 struct ktipc_srv_ops {
172     int (*on_connect)(const struct ktipc_port* port,
173                       struct handle* chan,
174                       const struct uuid* peer,
175                       void** ctx_p);
176 
177     int (*on_message)(const struct ktipc_port* port,
178                       struct handle* chan,
179                       void* ctx);
180 
181     void (*on_disconnect)(const struct ktipc_port* port,
182                           struct handle* chan,
183                           void* ctx);
184 
185     void (*on_channel_cleanup)(void* ctx);
186 
187     int (*on_send_unblocked)(const struct ktipc_port* port,
188                              struct handle* chan,
189                              void* ctx);
190 };
191 
192 /**
193  * ktipc_server_add_port() - Add new port to kernel tipc server
194  * @ksrv: pointer to kernel tipc server to add port to
195  * @port: pointer to &struct ktipc_port
196  * @ops:  pointer to &struct ktipc_srv_ops with service specific
197  *        callbacks
198  *
199  * Note: the caller retains ownership of structures pointed by @port
200  * parameters and should not modify these structures in any way after the
201  * service has been instantiated. Also, the caller is responsible for keeping
202  * them alive while service is running.
203  *
204  * Return: 0 on success, negative error code otherwise
205  */
206 int ktipc_server_add_port(struct ktipc_server* ksrv,
207                           const struct ktipc_port* port,
208                           const struct ktipc_srv_ops* ops);
209 
210 #define KTIPC_INTERNAL_IOV_INIT(buf, len) \
211     { .iov_base = (void*)(buf), .iov_len = (len) }
212 
213 #define ktipc_internal_send(chan, arg_handles, arg_num_handles, buf0, sz0,    \
214                             buf1, sz1, buf2, sz2, buf3, sz3, buf4, sz4, buf5, \
215                             sz5, buf6, sz6, buf7, sz7, db0, ds0, db1, ds1,    \
216                             db2, ds2, db3, ds3, db4, ds4, db5, ds5, db6, ds6, \
217                             db7, ds7, count, rest...)                         \
218     ({                                                                        \
219         /*                                                                    \
220          * Put the rest of the arguments in a fixed array so we get a         \
221          * static error if the caller passed in too many buffers              \
222          */                                                                   \
223         __UNUSED int rest_array[2 * 8] = {rest};                              \
224         struct iovec_kern iov[] = {                                           \
225                 KTIPC_INTERNAL_IOV_INIT(buf0, sz0),                           \
226                 KTIPC_INTERNAL_IOV_INIT(buf1, sz1),                           \
227                 KTIPC_INTERNAL_IOV_INIT(buf2, sz2),                           \
228                 KTIPC_INTERNAL_IOV_INIT(buf3, sz3),                           \
229                 KTIPC_INTERNAL_IOV_INIT(buf4, sz4),                           \
230                 KTIPC_INTERNAL_IOV_INIT(buf5, sz5),                           \
231                 KTIPC_INTERNAL_IOV_INIT(buf6, sz6),                           \
232                 KTIPC_INTERNAL_IOV_INIT(buf7, sz7),                           \
233         };                                                                    \
234         struct ipc_msg_kern msg = {                                           \
235                 .iov = iov,                                                   \
236                 .num_iov = count,                                             \
237                 .handles = (struct handle**)(arg_handles),                    \
238                 .num_handles = (arg_num_handles),                             \
239         };                                                                    \
240         ipc_send_msg((chan), &msg);                                           \
241     })
242 
243 /**
244  * ktipc_send_handles() - send a message from zero or more buffers
245  * @chan: handle of the channel to send message over
246  * @handles: pointer to an array of handles or %NULL
247  * @num_handles: size of @handles array
248  * @buffers: zero or more pairs of two arguments: a pointer to a buffer
249  *           and the size of that buffer; up to 8 buffer pairs are currently
250  *           supported by the implementation
251  *
252  * If there are no handles to send, @handles should be %NULL
253  * and @num_handles should be zero.
254  *
255  * Return: the total number of bytes sent on success, a negative
256  *         error code otherwise.
257  */
258 #define ktipc_send_handles(chan, handles, num_handles, buffers...)             \
259     ktipc_internal_send(chan, handles, num_handles, buffers, NULL, 0, NULL, 0, \
260                         NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0,  \
261                         8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 0)
262 
263 /**
264  * ktipc_send() - send a message from zero or more buffers
265  * @chan: handle of the channel to send message over
266  * @buffers: zero or more pairs of two arguments: a pointer to a buffer
267  *           and the size of that buffer; up to 8 buffer pairs are currently
268  *           supported by the implementation
269  *
270  * Return: the total number of bytes sent on success, a negative
271  *         error code otherwise.
272  */
273 #define ktipc_send(chan, buffers...) ktipc_send_handles(chan, NULL, 0, buffers)
274 
275 /**
276  * ktipc_recv_iov() - receive message into a set of iovecs
277  * @chan: handle of the channel to receive message from
278  * @min_sz: minimum size of the message expected
279  * @iov: pointer to an array of &struct iovec_kern elements
280  * @num_iov: number of iovecs to receive
281  * @handles: pointer to an array of handles or %NULL
282  * @num_handles: size of @handles array
283  *
284  * The received message has to contain at least @min_sz bytes and
285  * fully fit into provided buffers.
286  *
287  * If there are no handles to receive, @handles should be %NULL
288  * and @num_handles should be zero.
289  *
290  * Return: the number of bytes stored into the iovecs
291  *         parameter on success, a negative error code otherwise
292  */
293 int ktipc_recv_iov(struct handle* chan,
294                    size_t min_sz,
295                    struct iovec_kern* iov,
296                    uint32_t num_iov,
297                    struct handle** handles,
298                    uint32_t num_handles);
299 
300 #define ktipc_internal_recv(chan, min_sz, handles, num_handles, buf0, sz0,    \
301                             buf1, sz1, buf2, sz2, buf3, sz3, buf4, sz4, buf5, \
302                             sz5, buf6, sz6, buf7, sz7, db0, ds0, db1, ds1,    \
303                             db2, ds2, db3, ds3, db4, ds4, db5, ds5, db6, ds6, \
304                             db7, ds7, count, rest...)                         \
305     ({                                                                        \
306         /*                                                                    \
307          * Put the rest of the arguments in a fixed array so we get a         \
308          * static error if the caller passed in too many buffers              \
309          */                                                                   \
310         __UNUSED int rest_array[2 * 8] = {rest};                              \
311         struct iovec_kern iov[] = {                                           \
312                 KTIPC_INTERNAL_IOV_INIT(buf0, sz0),                           \
313                 KTIPC_INTERNAL_IOV_INIT(buf1, sz1),                           \
314                 KTIPC_INTERNAL_IOV_INIT(buf2, sz2),                           \
315                 KTIPC_INTERNAL_IOV_INIT(buf3, sz3),                           \
316                 KTIPC_INTERNAL_IOV_INIT(buf4, sz4),                           \
317                 KTIPC_INTERNAL_IOV_INIT(buf5, sz5),                           \
318                 KTIPC_INTERNAL_IOV_INIT(buf6, sz6),                           \
319                 KTIPC_INTERNAL_IOV_INIT(buf7, sz7),                           \
320         };                                                                    \
321         ktipc_recv_iov((chan), (min_sz), iov, count, (handles),               \
322                        (num_handles));                                        \
323     })
324 
325 /**
326  * ktipc_recv_handles() - receive a message into zero or more buffers
327  * @chan: handle of the channel to send message over
328  * @min_sz: minimum size of the message expected
329  * @handles: pointer to an array of handles or %NULL
330  * @num_handles: size of @handles array
331  * @buffers: zero or more pairs of two arguments: a pointer to a buffer
332  *           and the size of that buffer; up to 8 buffer pairs are currently
333  *           supported by the implementation
334  *
335  * The received message has to contain at least @min_sz bytes and
336  * fully fit into provided buffer.
337  *
338  * If there are no handles to send, @handles should be %NULL
339  * and @num_handles should be zero.
340  *
341  * Return: the number of bytes stored into the buffers pointed by @buffers
342  *         on success, a negative error code otherwise
343  */
344 #define ktipc_recv_handles(chan, min_sz, handles, num_handles, buffers...)    \
345     ktipc_internal_recv(chan, min_sz, handles, num_handles, buffers, NULL, 0, \
346                         NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, \
347                         NULL, 0, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, \
348                         1, 0)
349 
350 /**
351  * ktipc_recv() - receive a message into zero or more buffers
352  * @chan: handle of the channel to send message over
353  * @min_sz: minimum size of the message expected
354  * @buffers: zero or more pairs of two arguments: a pointer to a buffer
355  *           and the size of that buffer; up to 8 buffer pairs are currently
356  *           supported by the implementation
357  *
358  * The received message has to contain at least @min_sz bytes and
359  * fully fit into provided buffer.
360  *
361  * Return: the number of bytes stored into the buffers pointed by @buffers
362  *         on success, a negative error code otherwise
363  */
364 #define ktipc_recv(chan, min_sz, buffers...) \
365     ktipc_recv_handles(chan, min_sz, NULL, 0, buffers)
366 
367 __END_CDECLS
368