watchthelight labs

Panic on load: FreeBSD sysctl_register_oid shadows XNU's inside the kext (NULL deref in _start) #1

closed
watchthelight 2026-10-21

On the Legion (Tahoe 26.7.1, x86_64) XeGfx 0.0.1 (b53b58b, IOResources personality only) panics as soon as it is loaded from the auxiliary kernel collection:

panic: Kernel trap, type 14 = page fault, CR2 0x0000000000000000
org.watchthelight.XeGfx : _sysctl_register_oid_locked + 0x29
org.watchthelight.XeGfx : _sysctl_register_oid + 0x3a
org.watchthelight.XeGfx : __start + 0x10
mach_kernel : OSKext::start <- OSKext::load <- OSKext::loadKextWithIdentifier <- IOCatalogue::isModuleLoaded <- IOService::probeCandidates

Cause: the kext links FreeBSD's kern_sysctl (pulled in through drm-kmod / LinuxKPI), and its sysctl_register_oid and sysctl_register_oid_locked are defined inside the kext. _start registers debug.xegfx_start, but the call binds to the FreeBSD copy instead of XNU's exported sysctl_register_oid. The FreeBSD OID tree was never initialised, so it dereferences NULL. The earlier N-208 boot (PCI personality) died at the same point.

Fix:

  • Rename the FreeBSD sysctl implementation at compile time, for example -Dsysctl_register_oid=bsd_sysctl_register_oid and the same for the other sysctl_* entry points the shim defines.
  • Alternatively, register the XeGfx sysctl from a translation unit that never sees the FreeBSD headers.
  • Add a link-time check in tools/kpi_check.py that fails when the kext defines any symbol that an XNU KPI also exports.

How it was found: evidence evidence/native/N-212/ and N-213/ in the project repo. The workaround in use is a codeless kext that takes the XeGfxResident match category, so XeGfx never loads.

watchthelight 2026-10-21

Fixed in 0ebcf13: the FreeBSD copies of all 40 kernel-exported names the kext used to define are renamed for every FreeBSD/Linux unit (shim/include/xg_bsdnames.h), and tools/shadow_check.py now fails the link if one comes back. _start imports XNU's sysctl_register_oid again (checked with nm/otool). The kext also no longer loads at boot at all (it waits for kmutil load). Leaving this open until the first hardware test (Legion N-214) confirms the load.

watchthelight 2026-10-21

Confirmed on hardware (Legion N-214, 2026-10-21): XeGfx 0.0.2 loads with kmutil and runs all four stages without touching the boot. Closing.

Reply on GitHub