feat(kernel): KRNBUG-XEX-001 — real XexCheckExecutablePrivilege from XEX header bitmap
Replace stub_return_zero with a canary-faithful implementation that returns bit `priv` of the loaded XEX's XEX_HEADER_SYSTEM_FLAGS (key 0x00030000) bitmap. Mirrors xenia-canary xboxkrnl_modules.cc:22-39: `(flags >> priv) & 1` for priv < 32, else 0. Plumbing: - xenia-xex: header_keys::SYSTEM_FLAGS const + get_system_flags() accessor. - xenia-kernel/state.rs: pub xex_system_flags: u32 + xex_priv_logged HashSet for one-shot per-priv tracing. - xenia-app: kernel.xex_system_flags wired in cmd_exec_inner. - xenia-kernel/exports.rs: real export body + unit test covering bits 10/11/0/64 + zero-flags case. Sylpheed's bitmap is 0x00000400 (only XEX_SYSTEM_PAL50_INCOMPATIBLE, bit 10). At -n 500M with the fix: - XGetAVPack: 0 -> 1 (priv-10 gate at lr=0x824ab598 flipped). - 10 other canary-only exports + 9 producer PCs + 3 parked handles unchanged. Priv-11 site at sub_824A9710 is downstream and still not reached — AV/crypto block aborts after XGetAVPack returns our placeholder 0x16 (canary returns 8/HDMI; Sylpheed accepts only 3/4/6/8 per xenia-canary xam_info.cc:250-251). Tests 588 -> 589. Lockstep deterministic (3 reruns identical): n50m goes 50000008 -> 50000005 instr / 407415 -> 407417 imp / swaps=2 / draws=0. Goldens re-baselined (sylpheed_n50m, sylpheed_n2m); oracle test green. Full chain-of-effects + next-frontier hand-off in audit-findings.md under KRNBUG-XEX-001. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -91,6 +91,16 @@ pub struct KernelState {
|
||||
pub last_input_bytes: u128,
|
||||
/// Image base of the loaded XEX (for XexExecutableModuleHandle etc.)
|
||||
pub image_base: u32,
|
||||
/// `XEX_HEADER_SYSTEM_FLAGS` (key `0x00030000`) parsed from the loaded
|
||||
/// XEX header. Queried by `XexCheckExecutablePrivilege`: privilege bit
|
||||
/// `n` is set iff `(xex_system_flags & (1 << n)) != 0`. Zero before the
|
||||
/// app installs the loaded image — that matches canary's behavior when
|
||||
/// no executable module is registered (returns 0).
|
||||
pub xex_system_flags: u32,
|
||||
/// One-shot log gate for `XexCheckExecutablePrivilege`: tracks which
|
||||
/// privilege numbers have already produced a `tracing::info!` line so
|
||||
/// the import-hot path doesn't spam at -n 500M.
|
||||
pub xex_priv_logged: std::collections::HashSet<u32>,
|
||||
/// Next thread ID. M2.4: atomic.
|
||||
pub next_thread_id: std::sync::atomic::AtomicU32,
|
||||
/// Virtual file system for NtCreateFile/NtReadFile/etc. The app mounts
|
||||
@@ -248,6 +258,8 @@ impl KernelState {
|
||||
input_packet_number: 0,
|
||||
last_input_bytes: 0,
|
||||
image_base: 0,
|
||||
xex_system_flags: 0,
|
||||
xex_priv_logged: std::collections::HashSet::new(),
|
||||
next_thread_id: AtomicU32::new(1),
|
||||
vfs: None,
|
||||
ui: None,
|
||||
|
||||
Reference in New Issue
Block a user