fix 5.2 audit findings on Windows: F-PROC-1 injection, F-MEM-5 UAF, F-PROC-2 restart race, F-PROC-3, F5, F6
This commit is contained in:
+33
-10
@@ -24,6 +24,10 @@ mod shm;
|
||||
/// không respawn bridge mới sau khi sidecar đã bị giết (fix: app còn sống
|
||||
/// sau khi đóng window → pump thấy stall 3s → spawn bridge mới → orphan).
|
||||
static SHUTTING_DOWN: AtomicBool = AtomicBool::new(false);
|
||||
// F-PROC-2 (audit 5.2): serialize kill_bridge -> spawn_bridge across the pump
|
||||
// watchdog thread and the sample-rate restart command. Without it both threads
|
||||
// can kill+spawn concurrently and leave two daw_vst_bridge.exe on the same SHM.
|
||||
static BRIDGE_RESTART_LOCK: Mutex<()> = Mutex::new(());
|
||||
use shm::{Shm, ShmState};
|
||||
|
||||
struct EngineProcess(Mutex<Option<CommandChild>>);
|
||||
@@ -513,7 +517,22 @@ pub fn run() {
|
||||
);
|
||||
// FIX: kill bridge cũ trước — không được để 2 bridge
|
||||
// cùng map SHM (race control queue / double load).
|
||||
// F-PROC-2: serialize with the sample-rate restart
|
||||
// command (same BRIDGE_RESTART_LOCK).
|
||||
let _restart_guard = match BRIDGE_RESTART_LOCK.lock() {
|
||||
Ok(g) => g,
|
||||
Err(p) => p.into_inner(),
|
||||
};
|
||||
// F-PROC-3: re-check after acquiring the lock AND
|
||||
// after kill — Destroyed may have been set while we
|
||||
// waited/killed; never respawn during app shutdown.
|
||||
if SHUTTING_DOWN.load(Ordering::Relaxed) {
|
||||
break;
|
||||
}
|
||||
kill_bridge(&pump_handle);
|
||||
if SHUTTING_DOWN.load(Ordering::Relaxed) {
|
||||
break;
|
||||
}
|
||||
if spawn_bridge(&pump_handle, &res_dir, &exe_dir, &mut line, &log_path) {
|
||||
// count restarts into bridge.log (same file as stdout redirect)
|
||||
let bridge_log = std::path::Path::new(&log_dir)
|
||||
@@ -672,17 +691,15 @@ fn open_vst_gui(app: AppHandle, plugin_id: String, channel: u8) -> Result<(), St
|
||||
// B9: bridge tự tạo native Win32 window cho editor VST3 (không qua
|
||||
// WebView2 — HTML window cũ vẽ ĐÈ lên GUI plugin). push_control(4,0,0,0)
|
||||
// với hwnd=0 báo bridge tạo window riêng trên ChannelWorker thread.
|
||||
// F5 (audit 5.2): trả Err khi lệnh không tới được bridge (SHM unavailable /
|
||||
// lock poisoned / queue full) — frontend openNativeGUI đã try/catch sẵn.
|
||||
let state = app.state::<ShmState>();
|
||||
let lock = state.0.lock();
|
||||
match lock {
|
||||
Ok(guard) => match guard.as_ref() {
|
||||
Some(shm) => {
|
||||
let ok = shm.push_control(4, 0, 0, channel as u32, &plugin_id);
|
||||
eprintln!("open_vst_gui: push_control type=4 hwnd=0 ch={} ok={}", channel, ok);
|
||||
}
|
||||
None => eprintln!("open_vst_gui: bridge shm unavailable"),
|
||||
},
|
||||
Err(e) => eprintln!("open_vst_gui: shm lock poisoned: {}", e),
|
||||
let guard = state.0.lock().map_err(|e| e.to_string())?;
|
||||
let shm = guard.as_ref().ok_or("bridge shm unavailable")?;
|
||||
let ok = shm.push_control(4, 0, 0, channel as u32, &plugin_id);
|
||||
if !ok {
|
||||
eprintln!("open_vst_gui: push_control type=4 hwnd=0 ch={} failed", channel);
|
||||
return Err("control queue full".into());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -770,6 +787,12 @@ fn restart_bridge_with_sample_rate(app: AppHandle, sample_rate: u32) -> Result<(
|
||||
*g = sample_rate;
|
||||
}
|
||||
}
|
||||
// F-PROC-2: serialize with the pump watchdog restart so two threads can
|
||||
// never both kill+spawn (two bridges on the same SHM).
|
||||
let _restart_guard = match BRIDGE_RESTART_LOCK.lock() {
|
||||
Ok(g) => g,
|
||||
Err(p) => p.into_inner(),
|
||||
};
|
||||
kill_bridge(&app);
|
||||
let res_dir = app.path().resource_dir().unwrap_or_default();
|
||||
let exe_dir = std::env::current_exe()
|
||||
|
||||
Reference in New Issue
Block a user