Skip to content

Deliver penguin env off the kernel cmdline + per-arch length guard - #874

Merged
lacraig2 merged 3 commits into
mainfrom
workspace/env-off-cmdline
Jun 30, 2026
Merged

Deliver penguin env off the kernel cmdline + per-arch length guard#874
lacraig2 merged 3 commits into
mainfrom
workspace/env-off-cmdline

Conversation

@lacraig2

Copy link
Copy Markdown
Collaborator

Problem

Every penguin runtime knob is smuggled to the guest as key=value tokens on the kernel command line. The cmdline has a hard, arch-dependent cap (COMMAND_LINE_SIZE) — 256 bytes on MIPS vs 4096 elsewhere — and the kernel silently truncates anything longer, quietly dropping knobs (this bit us before, e.g. IGLOO_OWN_IFACES vanishing on MIPS). Anchors: #751, #706.

What this does

Slice 0 — the guard (safety net, no behavior change)

  • arch_registry: per-arch command_line_size (MIPS 256, others 4096).
  • penguin_run.check_cmdline_size: warns near the cap and raises on exceed — never silently truncates.

Slice 1 — move penguin's knobs off the cmdline

  • New penguin.boot_env partitions conf["env"]:
    • stays on the cmdline: user/config env: entries a vendor init may read from /proc/cmdline;
    • moves off: penguin-internal knobs (igloo_/IGLOO_ prefix + ROOT_SHELL, SHARED_DIR, WWW, CID, STRACE, PROJ_NAME, LD_LIBRARY_PATH, TERM).
  • LiveImage serves the internal knobs as an on-demand igloo_env.sh blob over the existing portal file channel (same mechanism as gen_live_image.sh); preinit.sh sources it right after insmod igloo.ko, so it lands in PID1's environment and propagates to the whole guest tree exactly as cmdline env did.
  • A realistic full env drops from ~221B → ~121B on -append; MIPS's 256B cap no longer gates how many IGLOO_* knobs we add.

Explicit cmdline control

  • New core.kernel_cmdline_append: verbatim tokens appended to -append, never diverted to the blob, still counted by the length guard (regenerated schema_doc.md).

Leak fix

  • init.sh scrubs penguin-internal env before exec-ing the firmware init, driven by the blob file (so it tracks new IGLOO_* knobs automatically), minus a keep-list for IGLOO_LTRACE/IGLOO_LTRACE_EXCLUDED/PROJ_NAME — guest tooling reads those inside the firmware process tree (ltrace via /etc/ld.so.preload constructor). Plugs a pre-existing igloo_init leak into the firmware environment.

Safety / why this is sound

All penguin knobs are consumed by guest userspace (source.d/*, init.sh, getenv in guest C) after insmod, never by the kernel/module — confirmed by a consumer audit. igloo_init is required for any boot to succeed, so the comprehensive suite (which boots real guests) is itself a strong end-to-end check of the new transport. User/firmware env: entries stay on the cmdline, so the existing env_cmp/env_unset tests remain valid.

Tests

New tests/unit_tests/test_cmdline_size.py and test_boot_env.py (partition rule, blob rendering incl. shell-quoting/None-skip, internal knobs off the cmdline, kernel_cmdline_append verbatim + counted by the guard). Pre-existing host-only asset-resolution failures in test_config.py are unrelated and unchanged.

Note: the boot-path changes (portal-fetch + source, init.sh scrub) are guest shell and not covered by the host unit suite — they want a container run of tests/comprehensive to validate the live boot.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lintly has detected code quality issues in this pull request.

@lacraig2
lacraig2 force-pushed the workspace/env-off-cmdline branch from 02bcab3 to e3efb38 Compare June 29, 2026 22:34

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lintly has detected code quality issues in this pull request.

@lacraig2
lacraig2 force-pushed the workspace/env-off-cmdline branch from e3efb38 to 6b2ae75 Compare June 29, 2026 22:47
lacraig2 added 2 commits June 29, 2026 22:20
The kernel cmdline has an arch-dependent COMMAND_LINE_SIZE cap (256B on
MIPS) and silently truncates anything longer, quietly dropping the env
knobs penguin smuggles onto -append. This adds a guard and moves
penguin's internal env off the cmdline entirely.

- arch_registry: per-arch command_line_size (MIPS 256, others 4096).
- penguin_run.check_cmdline_size: warn near the cap, raise on exceed
  (never silently truncate).
- boot_env: partition conf["env"] into firmware-expected (stays on the
  cmdline) vs penguin-internal (igloo_/IGLOO_ prefix + ROOT_SHELL,
  SHARED_DIR, WWW, CID, STRACE, PROJ_NAME, LD_LIBRARY_PATH, TERM).
- LiveImage serves the internal knobs as an on-demand igloo_env.sh blob
  over the existing portal file channel; preinit.sh sources it after
  insmod so it lands in PID1's env and propagates like cmdline env did.
- core.kernel_cmdline_append: explicit verbatim kernel-cmdline tokens,
  never diverted to the blob (regenerated schema_doc.md).
- init.sh scrubs the internal env before exec'ing the firmware init,
  driven by the blob (so it tracks new IGLOO_* knobs) minus a keep-list
  for IGLOO_LTRACE*/PROJ_NAME which guest tooling reads inside the
  firmware tree, so tooling-only env no longer leaks into the firmware.

Adds unit tests (test_cmdline_size.py, test_boot_env.py).
The 256B MIPS cap wasn't the kernel's COMMAND_LINE_SIZE (that's 4096 on
the MIPS kernels we ship, upstream since v3.7) -- it was QEMU's malta
board passing the cmdline through a single 256B prom env slot, which
truncated it before the kernel saw it. With hw/mips/malta.c's
ENVP_ENTRY_SIZE bumped to 0xfdc0 in rehosting/qemu, MIPS now matches
every other arch at 4096, so the length guard no longer fires on a
normal MIPS boot. Update the anti-drift and oversize tests accordingly.

Note: the 4096 is only fully deliverable once a rehosting/qemu release
carrying the malta bump is pinned by the Dockerfile's QEMU_VERSION;
until then the running qemu still truncates at 256, which is benign now
that boot-critical env rides the igloo_env.sh blob rather than the
cmdline.
@lacraig2
lacraig2 force-pushed the workspace/env-off-cmdline branch 2 times, most recently from fd8472b to 12fe783 Compare June 30, 2026 03:05
rehosting/qemu v0.0.14 is the malta ENVP_ENTRY_SIZE fix (256 -> 0xfdc0,
PR #15) cherry-picked onto the pre-Nixify v0.0.10 base and built via the
old Docker package path, so it is ABI-compatible with this ubuntu:22.04
image (CFFI env modules are cpython-310, not the cpython-313 of the
Nixified v0.0.11-v0.0.13 releases, which do not run here).

With malta in the running qemu, MIPS guests now receive the full
COMMAND_LINE_SIZE=4096 cmdline instead of being truncated at 256 by the
prom env slot, making the arch_registry 4096 cap real at runtime.

(Nixified qemu releases stay deferred to the penguin nixify rollout; see
the QEMU_VERSION provenance and arch_registry command_line_size note.)
@lacraig2
lacraig2 merged commit f3aeb31 into main Jun 30, 2026
28 of 29 checks passed
@lacraig2
lacraig2 deleted the workspace/env-off-cmdline branch July 1, 2026 18:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant