fix(windows-host): IDD-push resilience — driver-death recovery, reopenable control device, full interface discovery
Batch A of the audit's medium tier (M1+M2+M3): - M1 driver-death detection: a dead WUDFHost stops publishing, which at the ring is indistinguishable from an idle desktop — SDR sessions streamed a frozen frame forever (next_frame's 20 s bail is unreachable once anything presented). The ChannelBroker's process handle now doubles as a liveness probe (SYNCHRONIZE at OpenProcess); while no fresh frame arrives, try_consume polls it (rate-limited) and fails the capturer, landing in the session's bounded in-place rebuild. - M2 reopenable control device: the manager's OnceLock-cached handle is now a retire/reopen DeviceSlot — a gone-classified IOCTL failure (driver upgrade / WUDFHost restart; pinger, create, or REMOVE) retires the handle and the next use reopens + re-handshakes. Retired handles are deliberately kept alive forever: bare-HANDLE holders (pinger, ChannelBroker) rely on never-closed, and a retired handle only fails IOCTLs. CLEAR_ALL runs on the FIRST open only (a reopen races live-ish sessions); acquire retries the monitor create once after a reopen. The JOIN path now probes the active monitor's WUDFHost pid and preempts a DEAD monitor instead of handing the rebuilding session its stale target — without this the whole recovery chain starved to the rebuild budget. - M3 interface discovery: enumerate ALL interface instances with an SPINT_ACTIVE filter (a Code-10 devnode at index 0 no longer shadows the live interface), HDEVINFO behind RAII (error paths leaked one per probe), the raw device handle wrapped before GET_INFO (leaked on handshake failure), and the detail-sizing result guarded before the cbSize write. - pf-driver-proto: SetFrameChannelRequest doc now states the real adopt-on-success contract (the old wording invited a driver-side close-on-error — a cross-process double-close against the host's reap). - install: pf_vdisplay_present() passes /connected so a phantom devnode can't suppress creating a live ROOT node. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -151,9 +151,13 @@ pub mod control {
|
||||
}
|
||||
|
||||
/// `IOCTL_SET_FRAME_CHANNEL` input — the sealed frame channel's bootstrap. Every handle field is a
|
||||
/// handle VALUE already duplicated into the driver's WUDFHost process by the host; receiving it, the
|
||||
/// driver OWNS those handles (it closes whatever it doesn't consume — a replaced, invalid, or
|
||||
/// unmatched delivery must not leak entries in its own handle table).
|
||||
/// handle VALUE already duplicated into the driver's WUDFHost process by the host. Ownership is
|
||||
/// **adopt-on-success-only** (`design/idd-push-security.md` invariant 5): the driver owns (and
|
||||
/// eventually closes) the handles IFF it completes the IOCTL successfully — a replaced or
|
||||
/// later-unconsumed delivery is then the driver's to close. On ANY error completion (malformed
|
||||
/// request, unknown `target_id`) the driver must NOT close them: the HOST reaps its remote
|
||||
/// duplicates (`DUPLICATE_CLOSE_SOURCE`). Exactly one side closes each value; a driver that closed
|
||||
/// on error would double-close possibly-reused handle values against the host's reap.
|
||||
///
|
||||
/// Handle values are only meaningful inside the target process's handle table, so this struct is
|
||||
/// harmless to any third party: reading it leaks nothing openable, and spoofing it (were the control
|
||||
|
||||
Reference in New Issue
Block a user