[BUG] Dynamic boot rejects existing Rust v0 runtime symbols #5

Closed
opened 2026-09-14 11:06:19 +02:00 by erikinkinen · 0 comments
Owner

Summary

A signed dynamic image built with Rust 1.97.1 passes image verification and host artifact closure checks, then fails in Bootloader before entering Kernel. Shared libraries import Rust v0 names for runtime functions that are present in the kernel. The fallback namespace predicate recognizes only the older Rust encoding.

Reproduction

Build the isolated native lifetime diagnostic using Kernel 213c4606b2bf94d7ed87f339bf4c7462cad90987, Bootloader 8cb4383699c47812f64f086f54da6b2a7b9e9133 and the coherent dependency graph described in Integration issue 49. Boot its signed fixture under x86_64 TCG with one CPU, 1 GiB memory and no network. One actual VM has reproduced the failure; no unchanged rerun is used as evidence.

Expected and actual behavior

Expected: the runtime fallback can resolve an existing permitted core/alloc/compiler-builtins symbol using the selected toolchain's encoding, while arbitrary Kernel or foreign-crate names remain unavailable through that fallback.

Actual serial sequence includes BOOTIMG_VERIFY_OK, BOOTIMG_VERIFIED, ACPI_RSDP_FOUND, then KERNEL_DYNLINK_UNRESOLVED_SYMBOL. Kernel entry and the lifetime diagnostic never execute. The unchanged 45-second silence watchdog terminates QEMU within its 60-second hard deadline. Inspecting all dynamic objects finds no globally absent import. The shared objects' remaining Kernel-backed imports are v0 core functions, including string conversion, slice bounds and formatting.

Environment and identity

Bootloader 8cb4383699c47812f64f086f54da6b2a7b9e9133; Rust 1.97.1, x86_64 UEFI release build; Kernel 213c4606b2bf94d7ed87f339bf4c7462cad90987, IPC de6892790de69f40f749c393d24078b287b36175, capability ABI 984c9f7b0ca910488f8c5b035d2f0cb88f18d304. Signed test image SHA256 407595510b163113bb6c9a72f5a253b107211ff80d7b493742c6e791ba095d9e; UEFI binary SHA256 8cdb48693235a25c4d9297c4ad58db7ad062570ebfd415578019a5919053c984. Signing uses the explicit repository fixture key, with no production trust or release promotion. A last known working v0 image is not established.

Evidence and prior checks

The correction is signed as e7fa39357a38c21529cccfd16cf3446eb07e8aa5. The actual namespace predicate now follows the defining crate in legacy and Rust v0 names, preserving the four exact C memory names and the core/alloc/compiler-builtins boundary. Foreign definitions cannot gain access by mentioning a permitted type later in the name. Prefix recognition uses checked lengths and iterative traversal; the unchanged loader still requires an exact authenticated kernel export.

The original predicate fails against an observed v0 import. Five new classifier regressions pass, including observed names, namespace refusal, malformed prefixes and 4,096 nested path components. All strict development/release default/all-feature host and UEFI checks pass locally: 34 unit and seven standalone tests per selection, plus the 12/22/13/6 Python suites. Formatting, private/build-script rustdoc and canonical documents pass with no compiler or lint warnings.

Push CI 135 and PR CI 136 pass for that signed head. Four complete logs total 144,258 bytes without warning candidates. Both workflows complete the original source preparation, fresh profile comparisons and deliberate release diagnostic checks; raw CI EFI/PDB artifacts are not published for independent byte inspection.

A new signed-image VM using this Bootloader resolves imports, seals mappings and enters Kernel under the unchanged 60-second hard and 45-second silence limits. The loader defect is resolved. The overall lifetime scenario still fails its required serial markers; Kernel issue 9 tracks that separate diagnostic defect. No realm rollout or full guest build is established.

The loader's object dependency search remains explicit. Its subsequent is_approved_kernel_runtime_symbol check admits four C memory symbols and legacy core/alloc/compiler-builtins prefixes, but no v0 names. Dynamic-symbol inspection confirms the observed v0 imports have exact definitions in the kernel. The image, complete serial log, watchdog result and true process status are retained; host validation is not VM acceptance.

The original correction plan was to move this pure predicate into a host-testable module and recognize the defining crate through the documented v0 path prefix, preserving the same permitted runtime namespaces and exact symbol lookup. It must reject foreign defining crates even when later generic/type/name text mentions core, reject malformed or unrecognized ownership prefixes, and retain length-delimited legacy recognition. No generic Rust-prefix allowance, arbitrary Kernel fallback, new search root or provider discovery is permitted. Add regressions using observed imports, scoped negative cases and long nested paths; then run strict host/UEFI checks and a newly built bounded VM. Reference: rustc v0 symbol format.

Tracking

Related: native lifetime contract and Integration builder fixes. The loader defect is resolved; complete lifetime scenario acceptance remains open. Keep the prior failed image and status, update the isolated Bootloader pin only after a signed tested correction, and validate the normal dependency graph separately.

## Summary A signed dynamic image built with Rust 1.97.1 passes image verification and host artifact closure checks, then fails in Bootloader before entering Kernel. Shared libraries import Rust v0 names for runtime functions that are present in the kernel. The fallback namespace predicate recognizes only the older Rust encoding. ## Reproduction Build the isolated native lifetime diagnostic using Kernel `213c4606b2bf94d7ed87f339bf4c7462cad90987`, Bootloader `8cb4383699c47812f64f086f54da6b2a7b9e9133` and the coherent dependency graph described in [Integration issue 49](https://git.erikinkinen.fi/erix/integration/issues/49). Boot its signed fixture under x86_64 TCG with one CPU, 1 GiB memory and no network. One actual VM has reproduced the failure; no unchanged rerun is used as evidence. ## Expected and actual behavior Expected: the runtime fallback can resolve an existing permitted core/alloc/compiler-builtins symbol using the selected toolchain's encoding, while arbitrary Kernel or foreign-crate names remain unavailable through that fallback. Actual serial sequence includes `BOOTIMG_VERIFY_OK`, `BOOTIMG_VERIFIED`, `ACPI_RSDP_FOUND`, then `KERNEL_DYNLINK_UNRESOLVED_SYMBOL`. Kernel entry and the lifetime diagnostic never execute. The unchanged 45-second silence watchdog terminates QEMU within its 60-second hard deadline. Inspecting all dynamic objects finds no globally absent import. The shared objects' remaining Kernel-backed imports are v0 core functions, including string conversion, slice bounds and formatting. ## Environment and identity Bootloader `8cb4383699c47812f64f086f54da6b2a7b9e9133`; Rust 1.97.1, x86_64 UEFI release build; Kernel `213c4606b2bf94d7ed87f339bf4c7462cad90987`, IPC `de6892790de69f40f749c393d24078b287b36175`, capability ABI `984c9f7b0ca910488f8c5b035d2f0cb88f18d304`. Signed test image SHA256 `407595510b163113bb6c9a72f5a253b107211ff80d7b493742c6e791ba095d9e`; UEFI binary SHA256 `8cdb48693235a25c4d9297c4ad58db7ad062570ebfd415578019a5919053c984`. Signing uses the explicit repository fixture key, with no production trust or release promotion. A last known working v0 image is not established. ## Evidence and prior checks The correction is signed as `e7fa39357a38c21529cccfd16cf3446eb07e8aa5`. The actual namespace predicate now follows the defining crate in legacy and Rust v0 names, preserving the four exact C memory names and the core/alloc/compiler-builtins boundary. Foreign definitions cannot gain access by mentioning a permitted type later in the name. Prefix recognition uses checked lengths and iterative traversal; the unchanged loader still requires an exact authenticated kernel export. The original predicate fails against an observed v0 import. Five new classifier regressions pass, including observed names, namespace refusal, malformed prefixes and 4,096 nested path components. All strict development/release default/all-feature host and UEFI checks pass locally: 34 unit and seven standalone tests per selection, plus the 12/22/13/6 Python suites. Formatting, private/build-script rustdoc and canonical documents pass with no compiler or lint warnings. [Push CI 135](https://git.erikinkinen.fi/erix/bootloader/actions/runs/135) and [PR CI 136](https://git.erikinkinen.fi/erix/bootloader/actions/runs/136) pass for that signed head. Four complete logs total 144,258 bytes without warning candidates. Both workflows complete the original source preparation, fresh profile comparisons and deliberate release diagnostic checks; raw CI EFI/PDB artifacts are not published for independent byte inspection. A new signed-image VM using this Bootloader resolves imports, seals mappings and enters Kernel under the unchanged 60-second hard and 45-second silence limits. The loader defect is resolved. The overall lifetime scenario still fails its required serial markers; [Kernel issue 9](https://git.erikinkinen.fi/erix/kernel/issues/9) tracks that separate diagnostic defect. No realm rollout or full guest build is established. The loader's object dependency search remains explicit. Its subsequent `is_approved_kernel_runtime_symbol` check admits four C memory symbols and legacy core/alloc/compiler-builtins prefixes, but no v0 names. Dynamic-symbol inspection confirms the observed v0 imports have exact definitions in the kernel. The image, complete serial log, watchdog result and true process status are retained; host validation is not VM acceptance. The original correction plan was to move this pure predicate into a host-testable module and recognize the defining crate through the documented v0 path prefix, preserving the same permitted runtime namespaces and exact symbol lookup. It must reject foreign defining crates even when later generic/type/name text mentions core, reject malformed or unrecognized ownership prefixes, and retain length-delimited legacy recognition. No generic Rust-prefix allowance, arbitrary Kernel fallback, new search root or provider discovery is permitted. Add regressions using observed imports, scoped negative cases and long nested paths; then run strict host/UEFI checks and a newly built bounded VM. Reference: [rustc v0 symbol format](https://doc.rust-lang.org/rustc/symbol-mangling/v0.html). ## Tracking Related: [native lifetime contract](https://git.erikinkinen.fi/erix/kernel/issues/7) and [Integration builder fixes](https://git.erikinkinen.fi/erix/integration/issues/49). The loader defect is resolved; complete lifetime scenario acceptance remains open. Keep the prior failed image and status, update the isolated Bootloader pin only after a signed tested correction, and validate the normal dependency graph separately.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
erix/bootloader#5
No description provided.