[BUG] CPL3 entry can overwrite its third argument during register setup #10

Closed
opened 2026-09-14 13:05:44 +02:00 by erikinkinen · 0 comments
Owner

Summary

The initial userspace transition describes its three ABI argument operands as arbitrary input registers, then overwrites rdi, rsi and rdx with sequential moves inside the assembly. A valid register allocation places the third argument in rdi; the first move destroys it before the final move copies it into rdx. Rootd receives an incorrect third argument and rejects its initial contract.

Reproduction

Build the original Kernel 4330175e27718490f06b93098e95e3c1553cb765 with Rust 1.97.1 for freestanding x86_64, using the ordinary release Rootd smoke feature set. Inspect the emitted enter_user transition. The observed artifact loads the third context argument into rdi, then emits mov rdi, rsi, mov rsi, r8, mov rdx, rdi, followed by iretq.

The existing Integration subsystem-ipc-transport-framing-positive scenario reproduces the native failure with the dependency-selector correction under validation and signed Bootloader e7fa39357a38c21529cccfd16cf3446eb07e8aa5. No host privileged instruction execution or additional diagnostic VM was used to establish the emitted overwrite.

Expected and actual behavior

Expected: the three distinct caller-selected initial values arrive intact in rdi, rsi and rdx, independently of compiler register allocation. Stack, instruction pointer, segment and flags setup must preserve their existing contract.

Actual: the third argument becomes the first argument. The real VM passes dynamic relocation, kernel entry and Rootd image setup, then reports ERIX_KERNEL:ROOTD_SMOKE:CONTRACT_INVALID before the first intake marker. QEMU exits with status 39 instead of 33; the enclosing scenario exits 1 with clean process cleanup after 35.89051 seconds. Zero QEMU stderr does not turn that failed exit into a pass.

Environment and identity

  • Original Kernel: 4330175e27718490f06b93098e95e3c1553cb765; current feature Kernel 03e13a784bde08914864267a4e2a6324a22d05c7 retains the same transition source.
  • Kernel ELF SHA256: fb157d3457aa75b95dc77847d0ca892f45ec08cc35c18dc75065d47a0863f801, 701,904 bytes.
  • Signed boot image SHA256: 17b8e4126248676ee3d8e0c3dcdfb73f13b35e7a882d682122158bdadaa1770a, 27,934,720 bytes.
  • Rootd: ac3c1847af9915164d4a819f5f15e1827884e8b1; Integration base 4b65755f1f2774798d4a909212db4e64c0349b86 plus the qualified-feature correction.
  • Linux x86_64 host, Rust 1.97.1, release freestanding objects, one-CPU TCG VM and existing 120-second hard / 45-second silence limits.
  • These arguments describe the existing initial handoff; the correction must create no new capability, endpoint or discovery path.

Evidence and prior checks

The actual disassembly demonstrates operand aliasing immediately before iretq. The two failed VM results are retained separately: the earlier Bootloader revision rejects runtime imports; the accepted Bootloader fix resolves them and exposes this later entry failure. All 159 Integration helper suites and its strict Rust matrix pass, including the real compiler tests for dependency feature routing; those checks do not exercise a CPL3 transition with three distinct arguments.

The existing native lifetime diagnostic primarily passes zero entry arguments, which cannot establish independent argument preservation. Add real native coverage with distinct values, inspect both emitted profiles and run the full Kernel matrix before accepting the correction. Keep the original source graph coherent when selecting the fix for ordinary and lifetime diagnostics.

Validation checkpoint — 14 September 2026: Signed feature e6bea362f9199230bf84269b1a8da6bd8da6470d carries original signed maintenance ancestor 2f85d8a0e2e502ff1126ba40263296bc72f4635a. The ordinary and lifetime graphs preserve their respective IPC/capability selections. All strict default/all development/release checks pass; the final fixture matrix passes 610/634 units plus one standalone on the feature graph and 586/610 units on the maintenance graph, with three pre-existing ignores. CI 532 and 533 pass with four complete logs, 624,386 bytes and zero warning candidates. Integration 7cc0593e101b2e0ca42f24d4fa189dd96cb1455c passes the actual native distinct-argument/lifetime VM in 20.204185 seconds and the unchanged ordinary Rootd IPC-framing VM in 45.264436 seconds, with empty stderr. These are host build/run durations, not guest performance results. Both signed images are byte-identical to the preceding accepted transition images. Realm producer adoption and full guest builds remain open.

Tracking

Related: the component authority audit #2, Kernel PR 3, Integration issue 50 and Integration PR 12. Bind the ABI registers explicitly and remove the conflicting argument moves. Native validation and signed publication remain pending; no unchanged VM retry is requested.

## Summary The initial userspace transition describes its three ABI argument operands as arbitrary input registers, then overwrites `rdi`, `rsi` and `rdx` with sequential moves inside the assembly. A valid register allocation places the third argument in `rdi`; the first move destroys it before the final move copies it into `rdx`. Rootd receives an incorrect third argument and rejects its initial contract. ## Reproduction Build the original Kernel `4330175e27718490f06b93098e95e3c1553cb765` with Rust 1.97.1 for freestanding x86_64, using the ordinary release Rootd smoke feature set. Inspect the emitted `enter_user` transition. The observed artifact loads the third context argument into `rdi`, then emits `mov rdi, rsi`, `mov rsi, r8`, `mov rdx, rdi`, followed by `iretq`. The existing Integration `subsystem-ipc-transport-framing-positive` scenario reproduces the native failure with the dependency-selector correction under validation and signed Bootloader `e7fa39357a38c21529cccfd16cf3446eb07e8aa5`. No host privileged instruction execution or additional diagnostic VM was used to establish the emitted overwrite. ## Expected and actual behavior Expected: the three distinct caller-selected initial values arrive intact in `rdi`, `rsi` and `rdx`, independently of compiler register allocation. Stack, instruction pointer, segment and flags setup must preserve their existing contract. Actual: the third argument becomes the first argument. The real VM passes dynamic relocation, kernel entry and Rootd image setup, then reports `ERIX_KERNEL:ROOTD_SMOKE:CONTRACT_INVALID` before the first intake marker. QEMU exits with status 39 instead of 33; the enclosing scenario exits 1 with clean process cleanup after 35.89051 seconds. Zero QEMU stderr does not turn that failed exit into a pass. ## Environment and identity - Original Kernel: `4330175e27718490f06b93098e95e3c1553cb765`; current feature Kernel `03e13a784bde08914864267a4e2a6324a22d05c7` retains the same transition source. - Kernel ELF SHA256: `fb157d3457aa75b95dc77847d0ca892f45ec08cc35c18dc75065d47a0863f801`, 701,904 bytes. - Signed boot image SHA256: `17b8e4126248676ee3d8e0c3dcdfb73f13b35e7a882d682122158bdadaa1770a`, 27,934,720 bytes. - Rootd: `ac3c1847af9915164d4a819f5f15e1827884e8b1`; Integration base `4b65755f1f2774798d4a909212db4e64c0349b86` plus the qualified-feature correction. - Linux x86_64 host, Rust 1.97.1, release freestanding objects, one-CPU TCG VM and existing 120-second hard / 45-second silence limits. - These arguments describe the existing initial handoff; the correction must create no new capability, endpoint or discovery path. ## Evidence and prior checks The actual disassembly demonstrates operand aliasing immediately before `iretq`. The two failed VM results are retained separately: the earlier Bootloader revision rejects runtime imports; the accepted Bootloader fix resolves them and exposes this later entry failure. All 159 Integration helper suites and its strict Rust matrix pass, including the real compiler tests for dependency feature routing; those checks do not exercise a CPL3 transition with three distinct arguments. The existing native lifetime diagnostic primarily passes zero entry arguments, which cannot establish independent argument preservation. Add real native coverage with distinct values, inspect both emitted profiles and run the full Kernel matrix before accepting the correction. Keep the original source graph coherent when selecting the fix for ordinary and lifetime diagnostics. Validation checkpoint — 14 September 2026: Signed feature `e6bea362f9199230bf84269b1a8da6bd8da6470d` carries original signed maintenance ancestor `2f85d8a0e2e502ff1126ba40263296bc72f4635a`. The ordinary and lifetime graphs preserve their respective IPC/capability selections. All strict default/all development/release checks pass; the final fixture matrix passes 610/634 units plus one standalone on the feature graph and 586/610 units on the maintenance graph, with three pre-existing ignores. CI [532](https://git.erikinkinen.fi/erix/kernel/actions/runs/532) and [533](https://git.erikinkinen.fi/erix/kernel/actions/runs/533) pass with four complete logs, 624,386 bytes and zero warning candidates. Integration `7cc0593e101b2e0ca42f24d4fa189dd96cb1455c` passes the actual native distinct-argument/lifetime VM in 20.204185 seconds and the unchanged ordinary Rootd IPC-framing VM in 45.264436 seconds, with empty stderr. These are host build/run durations, not guest performance results. Both signed images are byte-identical to the preceding accepted transition images. Realm producer adoption and full guest builds remain open. ## Tracking Related: the component authority audit #2, [Kernel PR 3](https://git.erikinkinen.fi/erix/kernel/pulls/3), [Integration issue 50](https://git.erikinkinen.fi/erix/integration/issues/50) and [Integration PR 12](https://git.erikinkinen.fi/erix/integration/pulls/12). Bind the ABI registers explicitly and remove the conflicting argument moves. Native validation and signed publication remain pending; no unchanged VM retry is requested.
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/kernel#10
No description provided.