1 /*
2  * Copyright (c) 2013, 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 
24 #pragma once
25 
26 #include <bits.h>
27 #include <kernel/mutex.h>
28 #include <kernel/thread.h>
29 #include <reflist.h>
30 #include <stdbool.h>
31 #include <stdint.h>
32 #include <sys/types.h>
33 
34 #include <lib/trusty/handle.h>
35 #include <lib/trusty/ipc_msg.h>
36 #include <lib/trusty/trusty_app.h>
37 #include <lib/trusty/uuid.h>
38 
39 __BEGIN_CDECLS
40 
41 enum {
42     IPC_PORT_STATE_INVALID = 0,
43     IPC_PORT_STATE_LISTENING = 1,
44 };
45 
46 enum {
47     IPC_PORT_ALLOW_TA_CONNECT = 0x1,
48     IPC_PORT_ALLOW_NS_CONNECT = 0x2,
49 };
50 
51 #define IPC_PORT_PATH_MAX 64
52 
53 struct ipc_port {
54     /* e.g. /service/sys/crypto, /service/usr/drm/widevine */
55     char path[IPC_PORT_PATH_MAX];
56     const struct uuid* uuid;
57 
58     uint32_t state;
59     uint32_t flags;
60 
61     uint num_recv_bufs;
62     size_t recv_buf_size;
63 
64     struct handle handle;
65 
66     struct list_node pending_list;
67 
68     struct list_node node;
69 };
70 
71 enum {
72     IPC_CHAN_STATE_ACCEPTING = 1,
73     IPC_CHAN_STATE_CONNECTING = 2,
74     IPC_CHAN_STATE_CONNECTED = 3,
75     IPC_CHAN_STATE_DISCONNECTING = 4,
76 };
77 
78 enum {
79     IPC_CHAN_FLAG_SERVER = 0x1,
80 };
81 
82 /* aux state bitmasks */
83 #define IPC_CHAN_AUX_STATE_PEER_SEND_BLOCKED (1U << 1)
84 #define IPC_CHAN_AUX_STATE_SEND_UNBLOCKED (1U << 2)
85 #define IPC_CHAN_AUX_STATE_CONNECTED (1U << 3)
86 
87 #define IPC_CHAN_MAX_BUFS 32
88 #define IPC_CHAN_MAX_BUF_SIZE 4096
89 
90 struct ipc_chan {
91     struct obj refobj;
92     spin_lock_t ref_slock;
93     struct obj_ref peer_ref;
94     struct ipc_chan* peer;
95     const struct uuid* uuid;
96 
97     uint32_t state;
98     uint32_t flags;
99     uint32_t aux_state;
100 
101     /* handle_ref is a self reference when there are
102      * outstanding handles out there. It is removed
103      * when last handle ref goes away.
104      */
105     struct obj_ref handle_ref;
106     struct handle handle;
107 
108     /* used for port's pending list. node_ref field is a
109      * self reference when node field is inserted in the list.
110      *
111      * TODO: consider creating generic solution by grouping
112      * together list_node and struct obj_ref into single struct.
113      */
114     struct obj_ref node_ref;
115     struct list_node node;
116 
117     struct ipc_msg_queue* msg_queue;
118 
119     /*
120      * TODO: consider changing async connect to preallocate
121      *       not-yet-existing port object then we can get rid
122      *      of this field.
123      */
124     const char* path;
125 
126     struct mutex mlock;
127 };
128 
129 /* called by server to create port */
130 int ipc_port_create(const uuid_t* sid,
131                     const char* path,
132                     uint num_recv_bufs,
133                     size_t recv_buf_size,
134                     uint32_t flags,
135                     struct handle** phandle_ptr);
136 
137 /* called by server to publish the port */
138 int ipc_port_publish(struct handle* phandle);
139 
140 /* server calls to accept a pending connection */
141 int ipc_port_accept(struct handle* phandle,
142                     struct handle** chandle_ptr,
143                     const uuid_t** uuid_ptr);
144 
145 /**
146  * ipc_connection_waiting_for_port () - Query if the given port path has any
147  * valid connection waiting for it.
148  * @path: port for the query
149  * @flags: flags to validate connections against
150  *
151  * Return: true if there is a valid connection waiting for @port_path, false
152  * otherwise.
153  */
154 bool ipc_connection_waiting_for_port(const char* path, uint32_t flags);
155 
156 /**
157  * ipc_remove_connection_waiting_for_port () - Remove all valid connections
158  * waiting for a given port path.
159  * @path: port for the query
160  * @flags: flags to validate connections against
161  */
162 void ipc_remove_connection_waiting_for_port(const char* path, uint32_t flags);
163 
164 /* client requests a connection to a port */
165 #define IPC_CONNECT_WAIT_FOR_PORT 0x1U
166 #define IPC_CONNECT_ASYNC 0x2U
167 #define IPC_CONNECT_MASK (IPC_CONNECT_WAIT_FOR_PORT | IPC_CONNECT_ASYNC)
168 
169 int ipc_port_connect_async(const uuid_t* cid,
170                            const char* path,
171                            size_t max_path,
172                            uint flags,
173                            struct handle** chandle_ptr);
174 
175 bool ipc_is_channel(struct handle* handle);
176 bool ipc_is_port(struct handle* handle);
177 
178 /**
179  *  is_ns_client() - checks if specified uuid represents a non-secure client
180  *  @uuid: pointer to struct uuid representin IPC client
181  *
182  *  Each IPC client is identified by uuid that originated connection which
183  *  could be an app, external TIPC device, or kernel entity. This call
184  *  is typically implemented by a module that configures external TIPC
185  *  devices and check if specified UUID represents non-secure TIPC device.
186  *
187  *  Return: true if uuds represents non-secure client, false otherwise
188  */
189 bool is_ns_client(const uuid_t* uuid);
190 
191 /**
192  * ipc_port_check_access() - Check if an application can access a port with the
193  * given flags.
194  * @port_flags: flags of the port to check against
195  * @uuid: uuid of the application to check
196  *
197  * Return: NO_ERROR if the access is allowed, ERR_ACCESS_DENIED otherwise.
198  */
199 int ipc_port_check_access(uint32_t port_flags, const uuid_t* uuid);
200 
201 #if TEST_BUILD
202 /**
203  * ipc_get_port_list() - List all ports used by application
204  * @out_port_list: pointer to list of ports. must be freed by caller
205  *
206  * Return: The size of the list if positive. An Error if negative.
207  */
208 int ipc_get_port_list(struct ipc_port** out_port_list);
209 
210 /**
211  * ipc_free_port_list() - Free the given pointer to port list
212  * @out_port_list: pointer to list of ports.
213  *
214  */
215 void ipc_free_port_list(struct ipc_port* out_port_list);
216 #endif
217 
218 __END_CDECLS
219