@@ -8,8 +8,11 @@ use std::{
88 ffi:: CString ,
99 mem,
1010 os:: raw:: { c_int, c_uint, c_void} ,
11+ path:: Path ,
1112 ptr,
1213 sync:: { Arc , OnceLock } ,
14+ thread,
15+ time:: Duration ,
1316} ;
1417
1518use anyhow:: { Context , Result } ;
@@ -40,7 +43,7 @@ struct CuseInfo {
4043#[ repr( C ) ]
4144struct CuseOperations {
4245 init : * const c_void ,
43- init_done : * const c_void ,
46+ init_done : Option < unsafe extern "C" fn ( * mut c_void ) > ,
4447 destroy : * const c_void ,
4548 open : Option < unsafe extern "C" fn ( FuseReq , * mut FuseFileInfo ) > ,
4649 read : * const c_void ,
@@ -116,6 +119,62 @@ unsafe extern "C" fn release(req: FuseReq, _fi: *mut FuseFileInfo) {
116119 ( cuse ( ) . reply_err ) ( req, 0 ) ;
117120}
118121
122+ unsafe extern "C" fn init_done ( _userdata : * mut c_void ) {
123+ if let Err ( error) = ensure_nsm_device ( ) {
124+ tracing:: error!( ?error, "failed to publish simulated NSM device" ) ;
125+ return ;
126+ }
127+ if let Err ( error) = sd_notify:: notify ( true , & [ sd_notify:: NotifyState :: Ready ] ) {
128+ tracing:: error!( ?error, "failed to notify systemd that NSM is ready" ) ;
129+ }
130+ }
131+
132+ fn ensure_nsm_device ( ) -> Result < ( ) > {
133+ let device_path = Path :: new ( "/dev/nsm" ) ;
134+ let sysfs_paths = [
135+ Path :: new ( "/sys/class/misc/nsm/dev" ) ,
136+ Path :: new ( "/sys/devices/virtual/misc/nsm/dev" ) ,
137+ ] ;
138+ let mut stable_checks = 0 ;
139+ for _ in 0 ..100 {
140+ if device_path. exists ( ) {
141+ stable_checks += 1 ;
142+ if stable_checks >= 10 {
143+ return Ok ( ( ) ) ;
144+ }
145+ thread:: sleep ( Duration :: from_millis ( 20 ) ) ;
146+ continue ;
147+ }
148+ stable_checks = 0 ;
149+ if let Some ( device) = sysfs_paths
150+ . iter ( )
151+ . find_map ( |path| fs_err:: read_to_string ( path) . ok ( ) )
152+ {
153+ let ( major, minor) = device
154+ . trim ( )
155+ . split_once ( ':' )
156+ . context ( "invalid NSM device number" ) ?;
157+ let major = major. parse :: < u32 > ( ) . context ( "invalid NSM major number" ) ?;
158+ let minor = minor. parse :: < u32 > ( ) . context ( "invalid NSM minor number" ) ?;
159+ let path = CString :: new ( "/dev/nsm" ) ?;
160+ let result = unsafe {
161+ libc:: mknod (
162+ path. as_ptr ( ) ,
163+ libc:: S_IFCHR | 0o660 ,
164+ libc:: makedev ( major, minor) ,
165+ )
166+ } ;
167+ if result == 0 || device_path. exists ( ) {
168+ thread:: sleep ( Duration :: from_millis ( 20 ) ) ;
169+ continue ;
170+ }
171+ return Err ( std:: io:: Error :: last_os_error ( ) ) . context ( "failed to create /dev/nsm" ) ;
172+ }
173+ thread:: sleep ( Duration :: from_millis ( 20 ) ) ;
174+ }
175+ anyhow:: bail!( "CUSE NSM device did not appear in sysfs" )
176+ }
177+
119178unsafe extern "C" fn ioctl (
120179 req : FuseReq ,
121180 _cmd : c_int ,
@@ -245,7 +304,7 @@ pub fn run(config: &TeeSimulatorConfig) -> Result<()> {
245304 } ;
246305 let operations = CuseOperations {
247306 init : ptr:: null ( ) ,
248- init_done : ptr :: null ( ) ,
307+ init_done : Some ( init_done ) ,
249308 destroy : ptr:: null ( ) ,
250309 open : Some ( open) ,
251310 read : ptr:: null ( ) ,
@@ -256,7 +315,6 @@ pub fn run(config: &TeeSimulatorConfig) -> Result<()> {
256315 ioctl : Some ( ioctl) ,
257316 poll : ptr:: null ( ) ,
258317 } ;
259- sd_notify:: notify ( true , & [ sd_notify:: NotifyState :: Ready ] ) ?;
260318 let program = CString :: new ( "dstack-tee-simulator" ) ?;
261319 let foreground = CString :: new ( "-f" ) ?;
262320 let single_threaded = CString :: new ( "-s" ) ?;
0 commit comments