Skip to content

Commit a051c88

Browse files
authored
Merge pull request #853 from Dstack-TEE/codex/fix-simulator-nsm-readiness
fix(simulator): stabilize NSM device readiness
2 parents adc7b07 + 6ccbfeb commit a051c88

1 file changed

Lines changed: 61 additions & 3 deletions

File tree

  • dstack/tee-simulator/src

dstack/tee-simulator/src/nsm.rs

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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

1518
use anyhow::{Context, Result};
@@ -40,7 +43,7 @@ struct CuseInfo {
4043
#[repr(C)]
4144
struct 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+
119178
unsafe 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

Comments
 (0)