fix(kernel): KRNBUG-IO-003 — NtDeviceIoControlFile real impl mirroring NullDevice::IoControl
Replace the stub_success registration of NtDeviceIoControlFile at
exports.rs:90 with a real handler for FsCtlCodes 0x70000 (drive
geometry) and 0x74004 (partition info), mirroring xenia-canary
xboxkrnl_io.cc:645-678 + null_device.{h,cc}. The 16-byte 0x74004
response with cache_size=0xFF000 at OUT+8 is the gate that lets
sub_824ABD88 return SUCCESS and sub_824A9710 reach the priv-11
XexCheckExecutablePrivilege site identified by KRNBUG-AUDIT-007.
Stack args 9-10 (OutputBuffer, OutputBufferLength) read from the
caller's parameter save area at [sp+0x54] / [sp+0x5C] per the Xbox
360 PowerPC EABI (linkage area sp+0..sp+8, 8-quadword spill area
sp+0x14..sp+0x54, then stack args every 8 bytes). First HLE export
in the codebase to need 9+ args.
Cascade vs. KRNBUG-AUDIT-007 prediction (5/8 held):
- XexCheckExecutablePrivilege count 1 → 2 (priv=0xA + priv=0xB) ✓
- XamTaskSchedule count 0 → 1 ✓
- canary-only exports 7 → 3 (audit predicted ≤3) ✓
- 0x15e0 semaphore signal_attempts 0 → 1 (bonus)
- 0x100c worker spawn DID NOT fire (still UNCREATED) ✗
- 0x1004 signal_attempts unchanged ✗
- Worker spawn count unchanged at 19 ✗
Tests: 592 → 594. Lockstep deterministic at -n 100M (run1 ≡ run2 ≡
run3, byte-identical). instructions=100000010 → 100000019, imports
407417 → 987524 (+2.4×). swaps=2 draws=0 plateau persists.
sylpheed_n50m golden re-baselined instructions=50000004→50000003,
imports=407362→407255. sylpheed_n2m unchanged.
Still canary-only after this fix: ExTerminateThread,
KeReleaseSemaphore, XamUserReadProfileSettings. The next downstream
gate is somewhere past XamTaskSchedule's completion path.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5219,3 +5219,49 @@ PROBE_LIST="0x824a9aa0,0x824a9128,0x824a9710,0x824a9778,0x824a9788,0x824a9790,0x
|
||||
> audit-runs/audit-007/sub_824A9710-trace.log \
|
||||
2> audit-runs/audit-007/sub_824A9710-trace.err
|
||||
```
|
||||
|
||||
## KRNBUG-IO-003 — `NtDeviceIoControlFile` real implementation (LANDED 2026-05-04)
|
||||
|
||||
### Outcome
|
||||
|
||||
**Replaced `stub_success` registration with a real `nt_device_io_control_file` mirroring canary `NullDevice::IoControl` for FsCtlCodes 0x70000 + 0x74004.**
|
||||
- 592 → 594 tests; lockstep `instructions=100000019 imports=987524 swaps=2 draws=0` deterministic across run1/run2/run3 (`audit-runs/post-IO-003/lock_n100m_run{1,2,3}.json`, all byte-identical).
|
||||
- Branch: `xboxkrnl-ioctl/p0-fsctl-mountinfo` (no-ff merge).
|
||||
- `sylpheed_n50m` golden re-baselined `instructions=50000004→50000003`, `imports=407362→407255`. `sylpheed_n2m` unchanged.
|
||||
|
||||
### Audit-007 prediction scorecard
|
||||
|
||||
| # | Prediction | Pre | Post | Held? |
|
||||
|---|---|---|---|---|
|
||||
| (a) | `cargo test --workspace --release` green | 592 | 594 | ✓ |
|
||||
| (b) | Lockstep determinism preserved | bit-identical | bit-identical (run1≡run2≡run3) | ✓ |
|
||||
| (c) | `XexCheckExecutablePrivilege` count: 1 → ≥2 | 1 | 2 | ✓ |
|
||||
| (c) | `XamTaskSchedule` count: 0 → ≥1 | 0 | 1 | ✓ |
|
||||
| (e) | canary-only exports: 7 → ≤3 | 7 | 3 | ✓ |
|
||||
| (d) | 0x100c worker spawn (handle goes from UNCREATED to created+signaled) | UNCREATED | UNCREATED | **✗** |
|
||||
| (d) | 0x1004 signal_attempts > 0 | 0 | 0 | **✗** |
|
||||
| (d) | 0x15e0 signal_attempts > 0 | 0 | 1 (primary=1, "not stuck") | ✓ (new) |
|
||||
| (f) | Worker thread spawn count: 19 → higher | 19 | 19 | **✗** |
|
||||
|
||||
5/8 predictions held; cascade fired but not as far as audit-007 expected. Specifically:
|
||||
- The priv-11 query DOES fire → flows into `XamTaskSchedule` → 0x15e0 semaphore-signal pump now runs.
|
||||
- The audit-006 `canary_only.txt` 7 entries reduce by 4 (`KeResetEvent`, `ObCreateSymbolicLink`, `XamTaskCloseHandle`, `XamTaskSchedule`). Still missing: `ExTerminateThread`, `KeReleaseSemaphore`, `XamUserReadProfileSettings`.
|
||||
- `XeCryptSha` (1) and `XeKeysConsolePrivateKeySign` (1) also now fire (were 0).
|
||||
- Per-handle 0x100c stays UNCREATED — the producer chain that should spawn the 0x100c worker is gated downstream of where IO-003 unblocks. The 7→3 canary-only entries that remain (`ExTerminateThread`, `KeReleaseSemaphore`, `XamUserReadProfileSettings`) are the next clue: any of those could be the next gate.
|
||||
|
||||
### Files modified
|
||||
|
||||
- `crates/xenia-kernel/src/exports.rs:90` — `stub_success` → `nt_device_io_control_file`.
|
||||
- `crates/xenia-kernel/src/exports.rs` (new function) — body mirrors `xboxkrnl_io.cc:645-678` + `null_device.cc` (canary). Stack args 9-10 read from `[sp+0x54]` / `[sp+0x5C]` per Xbox 360 PowerPC ABI (parameter save area at sp+0x14 + 64 bytes spill = sp+0x54, confirmed by disasm of caller `sub_824ABD88` at `0x824abe04-0x824abe10` and `0x824abe78-0x824abe70`).
|
||||
- `crates/xenia-kernel/src/exports.rs` (new tests) — `nt_device_io_control_file_drive_geometry` (FsCtlCode 0x70000) + `nt_device_io_control_file_partition_info_unblocks_gate` (FsCtlCode 0x74004 — asserts OUT+8 ≠ 0, the gate condition).
|
||||
- `crates/xenia-app/tests/golden/sylpheed_n50m.json` — re-baselined.
|
||||
|
||||
### Trace artifacts
|
||||
|
||||
- `audit-runs/post-IO-003/lock_n100m_run{1,2,3}.json` — three byte-identical 100M lockstep runs.
|
||||
- `audit-runs/post-IO-003/lock_n500m.json` — 500M lockstep digest (`instructions=500000010 imports=5629676`).
|
||||
- `audit-runs/post-IO-003/exec_trace_focus_500m.log` — `--trace-handles-focus=0x1004,0x100c,0x15e0` at 500M.
|
||||
|
||||
### Next session candidates
|
||||
|
||||
The 0x100c worker still doesn't spawn. Three of audit-006's canary-only entries (`ExTerminateThread`, `KeReleaseSemaphore`, `XamUserReadProfileSettings`) remain canary-only — any of them may be the next downstream gate. Re-running `--branch-probe` against `sub_824A9710` would now show a new exit branch (the priv-11 site fires, so the failure mode has shifted).
|
||||
|
||||
Reference in New Issue
Block a user