Skip to content

Kernel panics on boot under the CI cross-toolchain (jump to address 0) #126

Description

@douglasmun

Summary

Under the nightly CI toolchain (i686-linux-gnu), the kernel does not boot. Every guest boot in the first nightly run panicked with an identical signature, at the point where the scheduler has started all tasks.

This does not reproduce with the local Homebrew i686-elf cross, where the same commit boots and passes harnesses.

Evidence

All four boots that got far enough to start a guest panicked identically:

*** PAGE FAULT ***
Faulting address: 0x00000000
Error code: 0x00000011      (present | instruction fetch)
EIP: 0x00000000
CS: 0x0010
Mode: KERNEL (CPL=0)
...
PT[0]: 0x8000000000000023
  Executable: No (NX set)
*** KERNEL PANIC ***  Kernel mode page fault

EIP=0 with an instruction-fetch error code is a call through a null function pointer. NX on PT[0] is what turns it into a fault rather than executing zeros.

Same signature in all four:

harness position in run
verify-editor-rowfail.sh 13
verify-exec-frame-leak.sh 18
verify-guard-page-release.sh 22
verify-tcp-rx-counters.sh 60

Not consecutive, and only two of the four use -DTINYOS_FAULT_INJECT, so this is not fault-inject object contamination.

Where it dies

Boot completes all init normally (entropy, ASLR, PAE, IDE, FAT32, all six tasks created). The panic lands just after the scheduler is running everything:

[SUPERVISOR] system task supervisor started [OK]
[EDR DAEMON] Starting EDR background daemon (PID 14583)
[EDR DAEMON] Configuration: scan_interval=500 ticks (5 seconds)
<panic>

One of the four survives a full EDR scan cycle first (Scan complete: 6 processes), so it is shortly after all tasks are live rather than at a fixed instruction.

Why this matters more than the failure count suggests

The first nightly run scored 53 FAIL / 5 INCONCL / 5 PASS. All 5 passes are static source checks that never boot a guest. No CI boot has ever reached the login prompt — grepping every serial log for Enter new root password returns nothing.

So the suite's real state is worse than the fixture failures implied: PR #125 fixes 48 of the 58 non-passing rows (35 × missing disk.img, 13 × dd bs=1m), but the boots that fix unblocks will then hit this.

Ruled out

  • Stack: 0x00000000 (ASLR randomized) appears on healthy local boots too — cosmetic reporting, not the cause.
  • First task entry is not null — CI reports Task entry: 0x0013539f (local: 0x001381d9). Both plausible.
  • Not fault-inject contamination (see above).
  • Not flaky — identical signature, every boot, deterministic.

Likely direction

The local and CI crosses differ in ways that have already produced three latent bugs (PR #113: dns.h bool, limits.h #include_next, linker.ld W^X assertion vs default-PIE; and later size_t being unsigned long vs unsigned int). A null function pointer that only materialises under one toolchain suggests a section/relocation difference — e.g. an initialiser array or a weak symbol that the GNU linker places differently — rather than a logic bug.

Suggested first step: build with the CI cross locally (i686-linux-gnu-gcc) and compare objdump/nm output against the i686-elf build, rather than debugging in CI.

Found while classifying the first nightly run's failures for #125.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions