• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <lib/coverage/common/cov_shm.h>
18 #include <interface/line-coverage/aggregator.h>
19 #include <lib/line-coverage/shm.h>
20 #include <lib/coverage/common/ipc.h>
21 #include <assert.h>
22 #include <lk/err_ptr.h>
23 #include <lk/list.h>
24 #include <stdbool.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <uapi/err.h>
29 #include <uapi/mm.h>
30 
31 #define TLOG_TAG "tipc-srv"
32 #include <lib/tipc/tipc_srv.h>
33 #include <trusty_log.h>
34 
35 #include "tipc_priv.h"
36 
37 static void port_event_handler_proc(const struct uevent* ev, void* port_ctx);
38 static void chan_event_handler_proc(const struct uevent* ev, void* chan_ctx);
39 
40 struct port_ctx {
41     struct tipc_event_handler event_handler;
42     const struct tipc_port* cfg;
43     struct tipc_srv* srv;
44     handle_t handle;
45 };
46 
47 struct chan_ctx {
48     struct list_node chan_list_node;
49     struct tipc_event_handler event_handler;
50     struct port_ctx* port;
51     handle_t handle;
52     void* user_ctx;
53 };
54 
55 struct tipc_srv {
56     struct list_node chan_list;
57     const struct tipc_srv_ops* ops;
58     struct tipc_hset* hset;
59     uint32_t chan_cnt;
60     uint32_t max_chan_cnt;
61     uint32_t port_cnt;
62     struct port_ctx ports[0];
63 };
64 
65 /*
66  * Helper to mask/unmask events for all ports
67  */
set_ports_event_mask(struct tipc_srv * srv,uint32_t mask)68 static void set_ports_event_mask(struct tipc_srv* srv, uint32_t mask) {
69     uint32_t i;
70     struct port_ctx* p;
71 
72     /* unmask ports here */
73     for (i = 0, p = srv->ports; i < srv->port_cnt; i++, p++) {
74         (void)tipc_hset_mod_entry(srv->hset, p->handle, mask,
75                                   &p->event_handler);
76     }
77 }
78 
server_at_max_chan_cnt(struct tipc_srv * srv)79 static bool server_at_max_chan_cnt(struct tipc_srv* srv) {
80     return (srv->max_chan_cnt && (srv->chan_cnt == srv->max_chan_cnt));
81 }
82 
83 /*
84  * Helper to close channel
85  */
tipc_chan_close(struct chan_ctx * chan)86 static void tipc_chan_close(struct chan_ctx* chan) {
87     int rc;
88     struct tipc_srv* srv = chan->port->srv;
89     void* user_ctx = chan->user_ctx;
90 
91     /* remove it from handle set */
92     rc = tipc_hset_remove_entry(srv->hset, chan->handle);
93     if (rc != NO_ERROR) {
94         /* the only reason for this to fail if any handle is somehow
95          * becomes invalid. There is no reasonable way to recover
96          * from this.
97          */
98         TLOGE("hset_remove_entry failed (%d)\n", rc);
99         abort();
100     }
101 
102     /* remove it from list */
103     list_delete(&chan->chan_list_node);
104 
105     /*
106      * if we had  a maximum number of channels we will now be below maximum.
107      * Unmask ports for this service so we can create channels.
108      */
109     if (server_at_max_chan_cnt(srv)) {
110         set_ports_event_mask(srv, ~0u);
111     }
112 
113     /* decrement channel count */
114     srv->chan_cnt--;
115 
116     /* close channel */
117     close(chan->handle);
118 
119     /* free memory */
120     free(chan);
121 
122     /*  cleanup user allocated state if any */
123     if (srv->ops->on_channel_cleanup && user_ctx) {
124         srv->ops->on_channel_cleanup(user_ctx);
125     }
126 }
127 
128 /*
129  *  channel event handler
130  */
chan_event_handler_proc(const struct uevent * ev,void * chan_ctx)131 static void chan_event_handler_proc(const struct uevent* ev, void* chan_ctx) {
132     int rc;
133     struct chan_ctx* chan = chan_ctx;
134     struct tipc_srv* srv = chan->port->srv;
135 
136     assert(ev->handle == chan->handle);
137 
138     tipc_handle_chan_errors(ev);
139 
140     setup_shm();
141 
142     if (ev->event & IPC_HANDLE_POLL_MSG) {
143         rc = srv->ops->on_message(chan->port->cfg, chan->handle,
144                                   chan->user_ctx);
145         if (rc < 0) {
146             /* report an error and close channel */
147             TLOGE("failed (%d) to handle event on channel %d\n", rc,
148                   ev->handle);
149             tipc_chan_close(chan);
150             dump_shm();
151             return;
152         }
153     }
154 
155     if (ev->event & IPC_HANDLE_POLL_HUP) {
156         /* closed by peer. */
157         TLOGD("close connection\n");
158         dump_shm();
159         if (srv->ops->on_disconnect) {
160             srv->ops->on_disconnect(chan->port->cfg, chan->handle,
161                                     chan->user_ctx);
162         }
163 
164         tipc_chan_close(chan);
165         return;
166     }
167 
168     if (ev->event & IPC_HANDLE_POLL_SEND_UNBLOCKED) {
169         if (srv->ops->on_send_unblocked) {
170             rc = srv->ops->on_send_unblocked(chan->port->cfg, chan->handle,
171                                              chan->user_ctx);
172             if (rc < 0) {
173                 /* report an error and close channel */
174                 TLOGE("failed (%d) to handle event on channel %d\n", rc,
175                       ev->handle);
176                 tipc_chan_close(chan);
177                 return;
178             }
179         } else {
180             TLOGE("send-unblocking not handled for channel %d\n", ev->handle);
181             tipc_chan_close(chan);
182             return;
183         }
184     }
185 }
186 
187 /*
188  *  Check if client is allowed to connect on specified port
189  */
client_is_allowed(const struct tipc_port_acl * acl,const struct uuid * peer)190 static bool client_is_allowed(const struct tipc_port_acl* acl,
191                               const struct uuid* peer) {
192     uint32_t i;
193 
194     if (!acl->uuid_num)
195         return true;
196 
197     for (i = 0; i < acl->uuid_num; i++) {
198         if (memcmp(peer, acl->uuids[i], sizeof(*peer)) == 0) {
199             /* match */
200             return true;
201         }
202     }
203 
204     return false;
205 }
206 
207 /*
208  *  Handle incoming connection
209  */
handle_connect(struct port_ctx * port)210 static void handle_connect(struct port_ctx* port) {
211     int rc;
212     handle_t hchan;
213     struct uuid peer;
214     void* user_ctx = NULL;
215     struct chan_ctx* chan;
216     struct tipc_srv* srv = port->srv;
217 
218     TLOGD("Incoming connection on %s\n", port->cfg->name);
219 
220     /* incoming connection: accept it */
221     rc = accept(port->handle, &peer);
222     if (rc < 0) {
223         TLOGE("failed (%d) to accept on port %s\n", rc, port->cfg->name);
224         return;
225     }
226     hchan = (handle_t)rc;
227 
228     if (server_at_max_chan_cnt(srv)) {
229         /* we should not ever get here after we implement port mask */
230         TLOGE("too many channels for port %s\n", port->cfg->name);
231         goto err_too_many_chan;
232     }
233 
234     /* do access control */
235     if (!client_is_allowed(port->cfg->acl, &peer)) {
236         TLOGE("access denied on port %s\n", port->cfg->name);
237         goto err_access;
238     }
239 
240     chan = calloc(1, sizeof(*chan));
241     if (!chan) {
242         TLOGE("oom while handling port %s\n", port->cfg->name);
243         goto err_oom;
244     }
245 
246     /* fill channel structure */
247     chan->event_handler.proc = chan_event_handler_proc;
248     chan->event_handler.priv = chan;
249     chan->port = port;
250     chan->handle = hchan;
251 
252     /* add new channel to handle set */
253     rc = tipc_hset_add_entry(srv->hset, hchan, ~0u, &chan->event_handler);
254     if (rc != NO_ERROR) {
255         TLOGE("failed (%d) to add chan to hset\n", rc);
256         goto err_hset_add;
257     }
258 
259     /* invoke on_connect handler if any */
260     if (srv->ops->on_connect) {
261         rc = srv->ops->on_connect(port->cfg, chan->handle, &peer, &user_ctx);
262         if (rc < 0) {
263             TLOGE("on_connect failed (%d) on port %s\n", rc, port->cfg->name);
264             goto err_on_connect;
265         }
266     }
267 
268     /* attach context provided by caller */
269     chan->user_ctx = user_ctx;
270 
271     /* add it to the list */
272     list_add_tail(&srv->chan_list, &chan->chan_list_node);
273     srv->chan_cnt++;
274 
275     /* mask all ports if max number of connections has been reached */
276     if (server_at_max_chan_cnt(srv)) {
277         set_ports_event_mask(srv, 0u);
278     }
279 
280     TLOGD("got connection on %s\n", port->cfg->name);
281     return;
282 
283 err_on_connect:
284 err_hset_add:
285     free(chan);
286 err_oom:
287 err_too_many_chan:
288 err_access:
289     close(hchan);
290 }
291 
292 /*
293  *  Port event handler
294  */
port_event_handler_proc(const struct uevent * ev,void * ctx)295 static void port_event_handler_proc(const struct uevent* ev, void* ctx) {
296     tipc_handle_port_errors(ev);
297 
298     if (ev->event & IPC_HANDLE_POLL_READY) {
299         struct port_ctx* port = ctx;
300         assert(port->handle == ev->handle);
301         handle_connect(port);
302     }
303 }
304 
305 /*
306  *  Add new TIPC service to handle set
307  */
tipc_add_service(struct tipc_hset * hset,const struct tipc_port * ports,uint32_t num_ports,uint32_t max_chan_cnt,const struct tipc_srv_ops * ops)308 int tipc_add_service(struct tipc_hset* hset,
309                      const struct tipc_port* ports,
310                      uint32_t num_ports,
311                      uint32_t max_chan_cnt,
312                      const struct tipc_srv_ops* ops) {
313     int rc;
314     uint32_t i;
315     struct tipc_srv* srv;
316     struct port_ctx* port;
317 
318     if (IS_ERR(hset)) {
319         TLOGE("invalid handle set (%d)\n", PTR_ERR(hset));
320         return ERR_INVALID_ARGS;
321     }
322 
323     if (!hset || !ports || !num_ports || !ops) {
324         TLOGE("required parameter is missing\n");
325         return ERR_INVALID_ARGS;
326     }
327 
328     /* allocate new service */
329     srv = calloc(1,
330                  sizeof(struct tipc_srv) + sizeof(struct port_ctx) * num_ports);
331     if (!srv) {
332         return ERR_NO_MEMORY;
333     }
334 
335     /* and initialize it */
336     srv->hset = hset;
337     srv->port_cnt = num_ports;
338     srv->max_chan_cnt = max_chan_cnt;
339 
340     list_initialize(&srv->chan_list);
341 
342     srv->ops = ops;
343     for (i = 0; i < num_ports; i++) {
344         srv->ports[i].handle = INVALID_IPC_HANDLE;
345     }
346 
347     /* for each port */
348     for (i = 0; i < num_ports; i++) {
349         TLOGD("Initialize port: %s\n", ports[i].name);
350 
351         port = &srv->ports[i];
352 
353         if (!ports[i].acl) {
354             TLOGE("ACL is required to create port\n");
355             rc = ERR_INVALID_ARGS;
356             goto err_no_acl;
357         }
358 
359         /* create port */
360         rc = port_create(ports[i].name, ports[i].msg_queue_len,
361                          ports[i].msg_max_size, ports[i].acl->flags);
362         if (rc < 0) {
363             TLOGE("failed (%d) to create port\n", rc);
364             goto err_port_create;
365         }
366         port->handle = (handle_t)rc;
367 
368         /* init event handler and other pointers */
369         port->cfg = &ports[i];
370         port->event_handler.proc = port_event_handler_proc;
371         port->event_handler.priv = port;
372         port->srv = srv;
373 
374         /* and add it to the handle set */
375         rc = tipc_hset_add_entry(hset, port->handle, ~0u, &port->event_handler);
376         if (rc < 0) {
377             TLOGE("failed (%d) to register port\n", rc);
378             goto err_hset_add;
379         }
380     }
381     setup_mailbox(ports, num_ports);
382     return 0;
383 
384 err_hset_add:
385 err_port_create:
386 err_no_acl:
387     /* kill all ports we have created so far */
388     for (i = 0; i < num_ports; i++) {
389         if (srv->ports[i].handle != INVALID_IPC_HANDLE) {
390             /* Note: closing handle also removes it from all handle sets */
391             rc = close(srv->ports[i].handle);
392             assert(rc == 0);
393         }
394     }
395     /* then free service */
396     free(srv);
397 
398     return rc;
399 }
400