1+ use fnv:: FnvHashMap ;
12use nix:: sys:: select:: { select, FdSet } ;
23use nix:: sys:: socket:: SockAddr as NixSockAddr ;
34use serde_cbor;
@@ -7,8 +8,10 @@ use std::thread::{self, JoinHandle};
78use std:: io:: { self , Error as IoError , ErrorKind as IoErrorKind , Read , Write } ;
89use std:: net:: { Shutdown , TcpListener , TcpStream } ;
910use std:: os:: unix:: io:: AsRawFd ;
11+ use std:: os:: unix:: prelude:: RawFd ;
12+ use std:: sync:: { Arc , Mutex } ;
1013use fortanix_vme_abi:: { self , Response , Request } ;
11- use vsock:: { self , Std , VsockListener , VsockStream } ;
14+ use vsock:: { self , Std , Vsock , VsockListener , VsockStream } ;
1215
1316const PROXY_BUFF_SIZE : usize = 4192 ;
1417
@@ -17,8 +20,6 @@ enum Direction {
1720 Right ,
1821}
1922
20- pub struct Server ;
21-
2223pub trait StreamConnection : Read + Write {
2324 fn protocol ( ) -> & ' static str ;
2425
@@ -79,6 +80,22 @@ impl StreamConnection for VsockStream {
7980 }
8081}
8182
83+ struct ListenerInfo {
84+ listener : TcpListener ,
85+ enclave_cid : u32 ,
86+ enclave_port : u32 ,
87+ }
88+
89+ pub struct Server {
90+ command_listener : Mutex < VsockListener > ,
91+ /// Tracks information about TCP sockets that are currently listening for new connections. For
92+ /// every TCP listener socket in the runner, there is a vsock listener socket in the enclave.
93+ /// When the enclave instructs to accept a new connection, the runner accepts a new TCP
94+ /// connection. It then locates the ListenerInfo and finds the information it needs to set up a
95+ /// new vsock connection to the enclave
96+ listeners : Mutex < FnvHashMap < RawFd , Arc < Mutex < ListenerInfo > > > > ,
97+ }
98+
8299impl Server {
83100 fn log_communication ( src : & str , src_port : u32 , dst : & str , dst_port : u32 , msg : & str , arrow : Direction , prot : & str ) {
84101 let src = format ! ( "{}:{}" , src, src_port) ;
@@ -159,13 +176,14 @@ impl Server {
159176 * [2] remote
160177 * [3] proxy
161178 */
162- fn handle_request_connect ( remote_addr : & String , enclave : & mut VsockStream ) -> Result < ( ) , IoError > {
179+ fn handle_request_connect ( & self , remote_addr : & String , enclave : & mut VsockStream ) -> Result < ( ) , IoError > {
163180 // Connect to remote server
164181 let mut remote_socket = TcpStream :: connect ( remote_addr) ?;
165182 let remote_name = remote_addr. split_terminator ( ":" ) . next ( ) . unwrap_or ( remote_addr) ;
166183
167184 // Create listening socket that the enclave can connect to
168- let ( proxy_server, _proxy_server_cid, proxy_server_port) = Self :: bind ( 0 ) ?;
185+ let proxy_server = VsockListener :: < Std > :: bind_with_cid_port ( vsock:: VMADDR_CID_ANY , 0 ) ?;
186+ let proxy_server_port = proxy_server. local_addr ( ) ?. port ( ) ;
169187
170188 // Notify the enclave on which port her proxy is listening on
171189 let response = Response :: Connected {
@@ -190,12 +208,23 @@ impl Server {
190208 Ok ( ( ) )
191209 }
192210
211+ fn add_listener_info ( & self , info : ListenerInfo ) -> RawFd {
212+ let fd = info. listener . as_raw_fd ( ) ;
213+ self . listeners . lock ( ) . unwrap ( ) . insert ( fd, Arc :: new ( Mutex :: new ( info) ) ) ;
214+ fd
215+ }
216+
217+ fn listener_info ( & self , fd : & RawFd ) -> Option < Arc < Mutex < ListenerInfo > > > {
218+ self . listeners . lock ( ) . unwrap ( ) . get ( & fd) . map ( |m| m. clone ( ) )
219+ }
220+
193221 /*
194222 * +-----------+
195223 * | remote |
196224 * +-----------+
197225 * ^
198226 * |
227+ * TCP
199228 * |
200229 * v
201230 * +----[2]-----+ +-------------+
@@ -207,12 +236,17 @@ impl Server {
207236 * [1] enclave
208237 * [2] remote
209238 * [3] proxy
239+ * `addr`: The address to bind the TCP connection on
240+ * `enclave_port`: The vsock port the enclave is listening on for new connections from the
241+ * runner
242+ * `enclave`: The runner-enclave vsock connection
210243 */
211- fn handle_request_bind ( addr : & String , enclave_port : u32 , enclave : & mut VsockStream ) -> Result < ( ) , IoError > {
212- let cid: u32 = enclave. peer ( ) . unwrap ( ) . parse ( ) . unwrap_or ( 0 ) ;
244+ fn handle_request_bind ( & self , addr : & String , enclave_port : u32 , enclave : & mut VsockStream ) -> Result < ( ) , IoError > {
245+ let cid: u32 = enclave. peer ( ) . unwrap ( ) . parse ( ) . unwrap_or ( vsock :: VMADDR_CID_HYPERVISOR ) ;
213246 let listener = TcpListener :: bind ( addr) ?;
214247 let port = listener. local_addr ( ) . map ( |addr| addr. port ( ) ) ?;
215- let response = Response :: Bound { port } ;
248+ let fd = self . add_listener_info ( ListenerInfo { listener, enclave_cid : cid, enclave_port } ) ;
249+ let response = Response :: Bound { port, fd } ;
216250 Self :: log_communication (
217251 "runner" ,
218252 enclave. local_port ( ) . unwrap_or_default ( ) ,
@@ -222,14 +256,37 @@ impl Server {
222256 Direction :: Right ,
223257 "vsock" ) ;
224258 enclave. write ( & serde_cbor:: ser:: to_vec ( & response) . unwrap ( ) ) ?;
259+ Ok ( ( ) )
260+ }
225261
226- for incoming in listener. incoming ( ) {
227- let _ = thread:: Builder :: new ( ) . spawn ( move || {
228- let mut proxy = VsockStream :: connect_with_cid_port ( cid, enclave_port) . unwrap ( ) ;
229- Self :: proxy_connection ( ( & mut incoming. unwrap ( ) , "remote" ) , ( & mut proxy, "proxy" ) ) ;
230- } ) ;
262+ fn handle_request_accept ( & self , fd : RawFd , enclave : & mut VsockStream ) -> Result < ( ) , IoError > {
263+ let listener_info = self . listener_info ( & fd) . unwrap ( ) ;
264+ let listener_info = listener_info. lock ( ) . unwrap ( ) ;
265+ let ( cid, port) = ( listener_info. enclave_cid , listener_info. enclave_port ) ;
266+ match listener_info. listener . accept ( ) {
267+ Ok ( ( mut conn, peer) ) => {
268+ let vsock = Vsock :: new :: < Std > ( ) ?;
269+ let response = Response :: IncomingConnection {
270+ peer : peer. into ( ) ,
271+ proxy_port : vsock. addr :: < Std > ( ) ?. port ( ) ,
272+ } ;
273+ Self :: log_communication (
274+ "runner" ,
275+ enclave. local_port ( ) . unwrap_or_default ( ) ,
276+ "enclave" ,
277+ enclave. peer_port ( ) . unwrap_or_default ( ) ,
278+ & format ! ( "{:?}" , & response) ,
279+ Direction :: Right ,
280+ "vsock" ) ;
281+ enclave. write ( & serde_cbor:: ser:: to_vec ( & response) . unwrap ( ) ) ?;
282+ let _ = thread:: Builder :: new ( ) . spawn ( move || {
283+ let mut proxy = vsock. connect_with_cid_port ( cid, port) . unwrap ( ) ;
284+ Self :: proxy_connection ( ( & mut conn, "remote" ) , ( & mut proxy, "proxy" ) ) ;
285+ } ) ;
286+ Ok ( ( ) )
287+ } ,
288+ Err ( e) => Err ( e) ,
231289 }
232- Ok ( ( ) )
233290 }
234291
235292 fn proxy_connection ( remote : ( & mut TcpStream , & str ) , proxy : ( & mut VsockStream , & str ) ) {
@@ -255,39 +312,40 @@ impl Server {
255312 let _ = remote. 0 . shutdown ( Shutdown :: Both ) ;
256313 }
257314
258- fn handle_client ( stream : & mut VsockStream ) -> Result < ( ) , IoError > {
315+ fn handle_client ( & self , stream : & mut VsockStream ) -> Result < ( ) , IoError > {
259316 match Self :: read_request ( stream) {
260- Ok ( Request :: Connect { addr } ) => Self :: handle_request_connect ( & addr, stream) ?,
261- Ok ( Request :: Bind { addr, enclave_port } ) => Self :: handle_request_bind ( & addr, enclave_port, stream) ?,
317+ Ok ( Request :: Connect { addr } ) => self . handle_request_connect ( & addr, stream) ?,
318+ Ok ( Request :: Bind { addr, enclave_port } ) => self . handle_request_bind ( & addr, enclave_port, stream) ?,
319+ Ok ( Request :: Accept { fd } ) => self . handle_request_accept ( fd, stream) ?,
262320 Err ( _e) => return Err ( IoError :: new ( IoErrorKind :: InvalidData , "Failed to read request" ) ) ,
263321 } ;
264322 Ok ( ( ) )
265323 }
266324
267- fn bind ( port : u32 ) -> io:: Result < ( VsockListener , u32 , u32 ) > {
268- let listener = VsockListener :: < Std > :: bind_with_cid_port ( vsock:: VMADDR_CID_ANY , port) ?;
269- let addr = listener. local_addr ( ) ?;
270-
271- if let NixSockAddr :: Vsock ( addr) = addr. into ( ) {
272- Ok ( ( listener, addr. cid ( ) , addr. port ( ) ) )
273- } else {
274- Err ( IoError :: new ( IoErrorKind :: InvalidInput , "Unexpected address type" ) )
275- }
325+ fn bind ( port : u32 ) -> io:: Result < Server > {
326+ let command_listener = VsockListener :: < Std > :: bind_with_cid_port ( vsock:: VMADDR_CID_ANY , port) ?;
327+ Ok ( Server {
328+ command_listener : Mutex :: new ( command_listener) ,
329+ listeners : Mutex :: new ( FnvHashMap :: default ( ) ) ,
330+ } )
276331 }
277332
278333 pub fn run ( port : u32 ) -> std:: io:: Result < ( JoinHandle < ( ) > , u32 ) > {
279334 println ! ( "Starting enclave runner." ) ;
280- let ( listener, _cid, port) = Self :: bind ( port) ?;
335+ let server = Arc :: new ( Self :: bind ( port) ?) ;
336+ let port = server. command_listener . lock ( ) . unwrap ( ) . local_addr ( ) ?. port ( ) ;
281337 println ! ( "Listening on vsock port {}..." , port) ;
282338
283339 let handle = thread:: Builder :: new ( ) . spawn ( move || {
284- let listener = listener;
285- loop {
286- let ( stream, _addr) = listener. accept ( ) . unwrap ( ) ;
340+ let server = server;
341+ let server = server. clone ( ) ;
342+ let command_listener = server. command_listener . lock ( ) . unwrap ( ) ;
343+ for stream in command_listener. incoming ( ) {
344+ let server = server. clone ( ) ;
287345 let _ = thread:: Builder :: new ( )
288346 . spawn ( move || {
289- let mut stream = stream;
290- if let Err ( e) = Self :: handle_client ( & mut stream) {
347+ let mut stream = stream. unwrap ( ) ;
348+ if let Err ( e) = server . handle_client ( & mut stream) {
291349 eprintln ! ( "Error handling connection: {}, shutting connection down" , e) ;
292350 let _ = stream. shutdown ( Shutdown :: Both ) ;
293351 }
0 commit comments