Guest Python (penguest) + first-class uncompiled init drop-ins - #905
Open
lacraig2 wants to merge 5 commits into
Open
Guest Python (penguest) + first-class uncompiled init drop-ins#905lacraig2 wants to merge 5 commits into
lacraig2 wants to merge 5 commits into
Conversation
Treat uncompiled init.d drop-ins (.sh/.py, or extension-less scripts with a shell/python shebang) as first-class init scripts alongside the existing .c compileables: normalize the shebang to a guest interpreter (/igloo/utils/sh, /igloo/utils/python3), warn on a foreign/missing one, and install the body. Non-scripts (binaries, .conf/.txt, deliberate foreign shebangs) stay verbatim. Stage the guest-side `penguest` Python binding into /igloo/pylib/penguest so in-guest Python -- and .py drop-ins -- can import it to reach the host over the portalcall ABI (portal_call/log/report) and over vsock (penguest.vsock). The python3 wrapper puts /igloo/pylib on PYTHONPATH. Draft 24 + draft 16 (guest module). Coupled: .py drop-ins require the staged guest Python interpreter.
…ened) Add the two host-side plugins the guest `penguest` binding talks to, both in default_plugins: - apis/penguest.py: portalcall log bridge. Reads guest log strings, emits them into the run log ([guest]/[guest finding]) and persists penguest_guest.log. Caps the read (64 KiB), strips control chars (no log-forgery/escape injection), bounds the log file (guest_log_max_bytes). - apis/penguest_vsock.py: framed-JSON vsock endpoint on <uds_path>_<port>. ping/echo built in; plugins register more via @endpoint. Per-connection worker pool capped at vsock_max_conns with a vsock_conn_timeout recv timeout so a stalled/flooding guest can't wedge it; deterministic teardown; 4 MiB frame cap. No-op when vsock/vpn is off. Both disable per run via {enabled: false}. Draft 16 slices 1 & 3.
A .py driver run via its #!/igloo/utils/python3 shebang imports penguest, makes a portal_call to a host test handler, calls log/report, and does a vsock echo round-trip through vhost-device-vsock to the penguest_vsock endpoint. Exercises the whole guest->host path on real guest CPython across the arch matrix.
The integration driver was /tests/penguest.py; CPython puts the script's own directory (/tests) first on sys.path, so `import penguest` imported the driver itself instead of the staged /igloo/pylib/penguest package -- AttributeError on portal_call, failing all four verifier conditions on every arch. Rename the driver to penguest_probe.py (and update the two stdout-path verifiers). Add a doc caveat so users don't hit the same shadowing with their own .py scripts.
lacraig2
force-pushed
the
workspace/guest-python-initd
branch
from
July 30, 2026 18:32
c82d94e to
2ee9c90
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements two coupled planning drafts:
Draft 24 — first-class uncompiled init drop-ins.
.sh/.pyfiles (and extension-less scripts with a shell/python shebang) dropped ininit.d/are now treated like the existing.ccompileables: their shebang is normalized to a guest interpreter (/igloo/utils/sh,/igloo/utils/python3), a foreign/missing one is rewritten with a warning, and the body is installed into/igloo/init.d/. Non-scripts (prebuilt binaries,.conf/.txt, deliberate foreign shebangs, busybox multi-call shebangs) stay verbatim.Draft 16 — guest Python + host comms. A guest-side
penguestPython module (staged into/igloo/pylib/penguest/, onPYTHONPATHvia the python3 wrapper) that wraps:portal_call(magic, *args)— the existing portalcallsendtoABI (per-arch syscall table), plus typedlog()/report()helpers.penguest.vsock— a framed length-prefixed-JSON AF_VSOCK client to the host.Host side (both in
default_plugins):apis/penguest.py(log bridge → run log + persistedpenguest_guest.log) andapis/penguest_vsock.py(vsock endpoint,ping/echobuilt in,@endpointregistration).The two are coupled:
.pydrop-ins only make sense because in-guest CPython is staged, andimport penguestworks with no extra setup.Security
The guest is untrusted firmware, so these are host-facing channels.
portal_calladds no new transport (the rawsendtowas always available). The two new default handlers take untrusted guest input and are hardened accordingly:vsock_max_conns) with a per-connection recv timeout (vsock_conn_timeout) so a stalled/flooding guest can't wedge it, 4 MiB frame cap, deterministic teardown.Disable per run for adversarial-firmware analysis:
penguest_vsockis inherently a no-op when vsock/vpn is off.Testing
tests/unit/, per the test-harness: host-side pyplugin testing (pyproject + CI fast lane + in-place harness) #881 host-testing contract):test_init_dropins.py(shebang resolution + end-to-end config load) andtest_penguest.py(portal_call packing vsportal_call.h, a round-trip through the realportalcall.py, vsock JSON framing, log/report packing, the host bridge reading guest memory + persisting/bounding the log, and the vsock endpoint incl. a live listener, connection cap, and stalled-connection drop). Full suite: 636 passed, flake8 clean, verified in a fresh venv.tests/integration/test_target/patches/tests/penguest.yaml, default arch matrix): a.pydriver run via its#!/igloo/utils/python3shebang thatimport penguest, makes aportal_call, callslog/report, and does avsock.connect()echo round-trip throughvhost-device-vsock— the one place the guest→host forwarding is exercised end-to-end on real guest CPython.Note: the 32-bit guest-python3 hang/ENOSYS (penguin#876) is fixed in the pinned penguin-tools via penguin-tools#20's glibc vDSO runtime-gate (mipsel/mipseb/armel); 64-bit arches were never affected.
Docs
docs/init_dropins.md,docs/penguest.md(incl. Security section), regenerateddocs/schema_doc.md.