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