Repository navigation
feat(vm): allow an externally signed VM runtime on macOS - #5141
vineethsai7 wants to merge 3 commits into
Conversation
Signed-off-by: Vineeth Sai Narajala <vnarajal@cisco.com>
|
I have read the DCO document and I hereby sign the DCO. |
Signed-off-by: Vineeth Sai Narajala <vnarajal@cisco.com>
Signed-off-by: Vineeth Sai Narajala <vnarajal@cisco.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a5a78cb33a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| # that lookup, so expose a setter for the driver's canonical absolute path. | ||
| PATCH="${ROOT}/tasks/scripts/vm/patches/libkrun-macos-absolute-firmware.patch" | ||
| if git -C libkrun apply --unidiff-zero --check "$PATCH"; then | ||
| git -C libkrun apply --unidiff-zero "$PATCH" |
There was a problem hiding this comment.
Restore the libkrun tree before switching pinned refs
When target/libkrun-build/libkrun is reused after changing or overriding LIBKRUN_REF (the supported pin-update flow documented in crates/openshell-driver-vm/runtime/pins.env), this application leaves src/libkrun/src/lib.rs modified in the persistent clone. The next invocation attempts git checkout "$LIBKRUN_REF" before reaching the reverse-patch check, so if the new ref changes that file Git aborts and the pin cannot be verified without an undocumented manual reset; git checkout -h confirms that only -f will “force checkout (throw away local modifications).” Reverse the known patch before checkout or apply it in a disposable worktree.
Useful? React with 👍 / 👎.
Summary
Allow a hardened macOS VM driver to boot with a matching external runtime selected by
OPENSHELL_VM_RUNTIME_DIR. The driver opens both dylibs by canonical absolute path and tells libkrun the absolute firmware path before creating a VM context. This is the runtime-loading part of the managed-Mac signing request. Developer ID and notarized boot verification remain open because no Developer ID identity was available on the test host.Related Issue
Part of #4772. The issue remains
state:triage-needed.Changes
libkrun.dylibandlibkrunfw.5.dylibinside the configured runtime directory and load them by absolute path. Remove the temporary process-wide working-directory change.krun_set_fw_path. The driver calls it before the first VM context; older external runtime archives without this entry point receive a clear error.Design
The pinned libkrun opens firmware with
dlopen("libkrunfw.5.dylib"). Hardened dyld rejects that relative lookup even if the process enters the runtime directory:relative path not allowed in hardened program. The macOS runtime build now adds a one-time setter so libkrun opens the driver's canonical absolute firmware path. The driver verifies both files resolve inside the selected directory and preloads the exact firmware file. This avoidsDYLD_*settings and process-wide directory changes.A hardened driver needs
com.apple.security.hypervisorto run the VM. With ad-hoc libraries or libraries signed by a different Team ID, it also needscom.apple.security.cs.disable-library-validation; the successful ad-hoc proof used both. Apple's library validation rule permits libraries signed with the driver's Team ID, so a matching Developer ID package is expected to need only the Hypervisor entitlement, but that exact signing configuration has not been tested. The proof did not usecom.apple.security.cs.allow-dyld-environment-variables.Operator example
Build the
vm-runtime-darwin-aarch64archive from the same revision as the driver. The archive must include the patched libkrun withkrun_set_fw_path; an older published archive cannot be used with this override. Sign both libraries and the driver with the same Developer ID Application identity and the hardened runtime:Set
OPENSHELL_VM_RUNTIME_DIRin the gateway service for a persistent deployment; it is not agateway.tomlfield. Keep the directory writable only by administrators. For ad-hoc or different-Team-ID libraries, addcom.apple.security.cs.disable-library-validationto the driver's entitlement file.Compatibility
The override is opt-in. Without it, the driver uses its embedded runtime. Linux behavior is unchanged. The external macOS runtime must match the driver build and export
krun_set_fw_path; older archives are rejected rather than attempting a relative firmware lookup.Release Notes
A hardened macOS VM driver can boot with a matching, separately signed runtime selected by
OPENSHELL_VM_RUNTIME_DIR. Packages with ad-hoc or different-Team-ID libraries need the library-validation exception; matching Developer ID signatures remain to be verified.Testing
Through
dcb up-os-4772withnice -n 15:cargo fmt --check -p openshell-driver-vm,cargo clippy --locked -p openshell-driver-vm --all-targets -- -D warnings, andcargo test --locked -p openshell-driver-vm --all-targetspassed (297 tests). The final build-script syntax check andgit diff --checkpassed. The zero-context libkrun patch was checked against the pinned source.On macOS 15.8 arm64 with Hypervisor available, the final driver at
a5a78cb33a9daa11eb51443a39d935cd22248988was signed ad hoc with--options runtime, Hypervisor anddisable-library-validationentitlements. The patched runtime dylibs were also signed ad hoc with--options runtime. A sandbox reachedReady, and another VM executeduname -mand printedaarch64andBOOT-OK. Upstreammainatbe5e49499, built and signed with the same recipe and pointed at the same external runtime, failed withCouldn't find or load libkrunfw.5.dylibandProcessExited. SeePROOF-5141.mdfor the ready-to-paste manual verification section.Follow-ups
Checklist
Review follow-up
Reviewed upstream PR #5141 against NVIDIA/OpenShell
mainon 2026-11-02. Findings and technical reasoning are in REVIEW-5141.md. The GitHub review and review-comment APIs returned no human review findings.26bb2a2commit isolated the VM worker; this head removes the cwd change entirely.26bb2a2; the outer driver removes the private marker before asynchronous driver work.libkrunfw.5.dylibdynamically; the final head passes its absolute path.mainbecause dyld rejected libkrun's bare-name firmware lookup. The final heada5a78cb33boots the hardened ad-hoc VM with the absolute-path setter whilemainstill fails the same recipe. The disposable test account and private runtime are removed after evidence capture.Manual verification
Result: PASS. The hardened driver at
a5a78cb33a9daa11eb51443a39d935cd22248988boots an external-runtime VM; upstreammainatbe5e49499fails the same recipe.Environment and signing
arm64), Hypervisor.framework available. Both drivers were built in release mode on this host with Rust 1.95.0. Each ran behind a private VM gateway in a disposable local account.libkrun.dylibandlibkrunfw.5.dylib, built from the pinned runtime source with this PR's firmware-path patch.nmconfirms_krun_set_fw_pathis exported. The gateway setOPENSHELL_VM_RUNTIME_DIR=<runtime-dir>and unsetDYLD_LIBRARY_PATHandDYLD_FALLBACK_LIBRARY_PATH.codesign --options runtime.codesign --verifypassed for the final driver and both dylibs; all four displayed CodeDirectory flags0x10002(adhoc,runtime)with no Team ID. Both drivers had exactlycom.apple.security.hypervisorandcom.apple.security.cs.disable-library-validation. The latter is required here because the libraries are ad hoc signed; no dyld-environment entitlement was used.0 valid identities foundfor code signing. A real Developer ID signature, same-Team-ID library validation, and notarization were unavailable and remain unverified.Procedure
--options runtime, and sign each release driver ad hoc with--options runtime --entitlements <hypervisor-and-library-validation.plist>.OPENSHELL_VM_RUNTIME_DIR=<runtime-dir>and noDYLD_*settings.openshell sandbox create --name h1 --from ubuntu:24.04 -- sh -c 'uname -m; echo BOOT-OK'. For the final driver, also createhreadywithout a trailing command and runopenshell sandbox listto record a persistent phase.Before and after
mainbe5e49499--options runtime, Hypervisor + library-validation exceptionProcessExitederrora5a78cb33a9daa11eb51443a39d935cd22248988--options runtime, Hypervisor + library-validation exceptionaarch64andBOOT-OK; separate sandbox reachesReadyMain gateway and client output:
Final driver client output:
A direct hardened dyld probe of the prior implementation explained the difference:
dlopen("libkrunfw.5.dylib")from the runtime working directory failed withrelative path not allowed in hardened program. The final driver canonicalizes both dylib paths and calls the new libkrun setter with the absolute firmware path before creating the VM context. The test account, gateways, sandboxes, and private runtime were removed after evidence capture.The matching-Team-ID Developer ID recipe is documented from macOS library-validation behavior but was not exercised in this test.