11// SPDX-License-Identifier: Apache-2.0
22
33use super :: error:: NitroError ;
4+ use libc:: c_int;
45use nitro_enclaves:: {
56 launch:: { ImageType , Launcher , MemoryInfo , PollTimeout , StartFlags } ,
67 Device ,
@@ -12,7 +13,7 @@ use std::{
1213 os:: fd:: AsFd ,
1314 path:: PathBuf ,
1415} ;
15- use vsock:: { VsockAddr , VsockListener } ;
16+ use vsock:: { VsockAddr , VsockListener , VsockStream } ;
1617
1718type Result < T > = std:: result:: Result < T , NitroError > ;
1819
@@ -41,6 +42,22 @@ impl NitroEnclave {
4142 pub fn run ( & mut self ) -> Result < u32 > {
4243 let _rootfs_archive = self . rootfs_archive ( ) ?;
4344
45+ let ( cid, _stream) = self . start ( ) ?;
46+
47+ Ok ( cid)
48+ }
49+
50+ fn rootfs_archive ( & self ) -> Result < Vec < u8 > > {
51+ let mut builder = tar:: Builder :: new ( Vec :: new ( ) ) ;
52+
53+ builder
54+ . append_dir_all ( "rootfs" , self . rootfs . clone ( ) )
55+ . unwrap ( ) ;
56+
57+ Ok ( builder. into_inner ( ) . unwrap ( ) )
58+ }
59+
60+ fn launch ( & mut self ) -> Result < u32 > {
4461 let device = Device :: open ( ) . map_err ( NitroError :: DeviceOpen ) ?;
4562
4663 let mut launcher = Launcher :: new ( & device) . map_err ( NitroError :: VmCreate ) ?;
@@ -52,61 +69,59 @@ impl NitroEnclave {
5269 launcher. add_vcpu ( None ) . map_err ( NitroError :: VcpuAdd ) ?;
5370 }
5471
55- let sockaddr = VsockAddr :: new ( VMADDR_CID_PARENT , ENCLAVE_READY_VSOCK_PORT ) ;
56- let listener = VsockListener :: bind ( & sockaddr) . map_err ( NitroError :: HeartbeatBind ) ?;
57-
5872 let cid = launcher
5973 . start ( self . start_flags , None )
6074 . map_err ( NitroError :: VmStart ) ?;
6175
62- // Safe to unwrap.
63- let cid : u32 = cid . try_into ( ) . unwrap ( ) ;
76+ Ok ( cid . try_into ( ) . unwrap ( ) ) // Safe to unwrap.
77+ }
6478
79+ fn poll ( & self , listener : & VsockListener ) -> Result < ( ) > {
6580 let poll_timeout = PollTimeout :: try_from ( ( & self . image , self . mem_size_mib << 20 ) )
6681 . map_err ( NitroError :: PollTimeoutCalculate ) ?;
6782
68- enclave_check ( listener, poll_timeout. into ( ) , cid) ?;
83+ let mut poll_fds = [ PollFd :: new ( listener. as_fd ( ) , PollFlags :: POLLIN ) ] ;
84+ let result = poll (
85+ & mut poll_fds,
86+ NixPollTimeout :: from ( c_int:: from ( poll_timeout) as u16 ) ,
87+ ) ;
6988
70- Ok ( cid)
71- }
72-
73- fn rootfs_archive ( & self ) -> Result < Vec < u8 > > {
74- let mut builder = tar:: Builder :: new ( Vec :: new ( ) ) ;
89+ if result == Ok ( 0 ) {
90+ return Err ( NitroError :: PollNoSelectedEvents ) ;
91+ }
7592
76- builder
77- . append_dir_all ( "rootfs" , self . rootfs . clone ( ) )
78- . unwrap ( ) ;
93+ if result != Ok ( 1 ) {
94+ return Err ( NitroError :: PollMoreThanOneSelectedEvent ) ;
95+ }
7996
80- Ok ( builder . into_inner ( ) . unwrap ( ) )
97+ Ok ( ( ) )
8198 }
82- }
8399
84- fn enclave_check ( listener : VsockListener , poll_timeout_ms : libc:: c_int , cid : u32 ) -> Result < ( ) > {
85- let mut poll_fds = [ PollFd :: new ( listener. as_fd ( ) , PollFlags :: POLLIN ) ] ;
86- let result = poll ( & mut poll_fds, NixPollTimeout :: from ( poll_timeout_ms as u16 ) ) ;
87- if result == Ok ( 0 ) {
88- return Err ( NitroError :: PollNoSelectedEvents ) ;
89- } else if result != Ok ( 1 ) {
90- return Err ( NitroError :: PollMoreThanOneSelectedEvent ) ;
91- }
100+ fn start ( & mut self ) -> Result < ( u32 , VsockStream ) > {
101+ let sockaddr = VsockAddr :: new ( VMADDR_CID_PARENT , ENCLAVE_READY_VSOCK_PORT ) ;
102+ let listener = VsockListener :: bind ( & sockaddr) . map_err ( NitroError :: HeartbeatBind ) ?;
92103
93- let mut stream = listener. accept ( ) . map_err ( NitroError :: HeartbeatAccept ) ?;
104+ let cid = self . launch ( ) ?;
105+ self . poll ( & listener) ?;
94106
95- let mut buf = [ 0u8 ] ;
96- let bytes = stream. 0 . read ( & mut buf) . map_err ( NitroError :: HeartbeatRead ) ?;
107+ let mut stream = listener. accept ( ) . map_err ( NitroError :: HeartbeatAccept ) ?;
97108
98- if bytes != 1 || buf [ 0 ] != HEART_BEAT {
99- return Err ( NitroError :: EnclaveHeartbeatNotDetected ) ;
100- }
109+ if stream . 1 . cid ( ) != cid {
110+ return Err ( NitroError :: HeartbeatCidMismatch ) ;
111+ }
101112
102- stream
103- . 0
104- . write_all ( & buf)
105- . map_err ( NitroError :: HeartbeatWrite ) ?;
113+ let mut buf = [ 0u8 ] ;
114+ let bytes = stream. 0 . read ( & mut buf) . map_err ( NitroError :: HeartbeatRead ) ?;
106115
107- if stream . 1 . cid ( ) != cid {
108- return Err ( NitroError :: HeartbeatCidMismatch ) ;
109- }
116+ if bytes != 1 || buf [ 0 ] != HEART_BEAT {
117+ return Err ( NitroError :: EnclaveHeartbeatNotDetected ) ;
118+ }
110119
111- Ok ( ( ) )
120+ stream
121+ . 0
122+ . write_all ( & buf)
123+ . map_err ( NitroError :: HeartbeatWrite ) ?;
124+
125+ Ok ( ( cid, stream. 0 ) )
126+ }
112127}
0 commit comments