SNP: make SINGLE_SOCKET an owner-policy flag - #235
Merged
Merged
Conversation
A Linux KVM host cannot satisfy AMD guest policy bit 20 on a machine with more than one socket populated: 56860 section 8.10 fails SNP_ACTIVATE for such a guest and KVM never issues SNP_ACTIVATE_EX. Dual-socket operators were therefore refused at snp_single_socket_required no matter how honest their machine was, while passing every other admission check. cathedral_amd_sev_snp_policy_v1 gains an optional top-level boolean require_single_socket. Absent means true, so every existing policy file keeps its behaviour and its digest. Relaxing the bit does not let one host earn more than one machine's credit. Every SNP command on a Linux host runs on the master PSP, so all guests on a host report the same CHIP_ID and duplicate_hardware_indexes zeroes them. Measured on a live dual-socket host on 2026-09-08: two guests, one CHIP_ID, both VCEK-verified against the AMD chain. The production gate had no unit test. Adds one, plus the relaxed and strict cases, a check that relaxing this bit does not widen debug or migration-agent, and loader coverage for the new key. Machine rows now carry guest_policy_hex and single_socket so telemetry shows what was admitted. Claude-Session: https://claude.ai/code/session_011bg88Y8YjVJ6abHcuMWsaw
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_47ca588d-c005-44d8-a2ac-8f68a10bf950) |
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. |
This was referenced Sep 8, 2026
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.
Closes #234.
Why
A Linux KVM host cannot satisfy AMD guest policy bit 20 on a machine with more than one socket populated. AMD 56860 section 8.10 makes
SNP_ACTIVATEreturnPOLICY_FAILUREfor such a guest, and KVM never issuesSNP_ACTIVATE_EX(arch/x86/kvm/svm/sev.c:2274). A dual-socket operator therefore cannot present a single-socket guest at all, however honest they are.SN39 UID 68 is that case today. The machine passes signed evidence, fleet, SAT, and full VCEK verification against the AMD chain, and is then refused at
snp_single_socket_required(snp_production.py:362). Its axon is on chain and its incentive is zero, gated only on this.What changes
cathedral_amd_sev_snp_policy_v1gains an optional top-level booleanrequire_single_socket.true. Every policy file written before this key existed keeps exactly its previous behaviour and, because the digest is taken over the file bytes, its previous digest. Verified by test.load_snp_policyvalidates the key strictly: a non-boolean is refused, and unknown keys are still refused.SnpProductionVerifier.verifyconsults it at the point that returnssnp_single_socket_requiredtoday.guest_policy_hexandsingle_socket, so telemetry shows what was admitted rather than only what was refused.Nothing else about admission moves. VCEK signature and chain,
MaskChipKeyoff, non-zero CHIP_ID, VMPL 0, debug off, migration agent off, generation, measurement allowlist, componentwise TCB floor, report-data binding and same-channel SAT are all unchanged.Why this does not let one host farm many miners
Every SNP command on a Linux host executes on the master PSP, chosen by lowest PCI address and fixed at boot (
drivers/crypto/ccp/sev-dev.c:846-849,sp-pci.c:181-216). So every guest on a host reports the same CHIP_ID, andduplicate_hardware_indexes(multicompute.py:165-186) zeroes every row whose hardware identity appears more than once.That was the one open fact in #234, and it is now measured rather than assumed. On 2026-09-08 the operator started a second SNP guest on the same dual-socket host. Both guests return the identical chip pseudonym
5a8e82885be3a995, identical measurement, guest policy0x30000and reported TCB. Both bundles returnchain_verified: true,VERIFIED,chip_id_match: truethrough the pinned verifier, so both reports are signed by the same physical chip's VCEK. Full result in #234.Caveat kept in the record: n=1 host, and the socket placement of the two guests is unknown, so this establishes same-host CHIP_ID collision rather than the cross-socket routing claim specifically. The operational consequence is the same.
What we give up
The firmware-enforced guarantee that a guest's identity cannot change over its lifetime. On Linux the master-PSP routing gives the same property. On a hypervisor that routes each guest request to the PSP of the socket its vCPUs are on, it does not, and such a guest could present one identity per socket it spans. Nobody we know runs one.
Tests
The production gate had no unit test before this. Added:
snp_single_socket_requiredand no machine idBoth directions were mutation-checked: restoring the unconditional gate fails the relaxed test, and defaulting the flag to
falsefails the back-compat test.tests/thin: 2488 passed, 20 failed. The same 20 fail on an untouchedorigin/mainon this machine (six files, all systemd paths that do not run on macOS), where the count is 2482 passed. No regressions; the delta is the six new tests.Not in this PR
https://claude.ai/code/session_011bg88Y8YjVJ6abHcuMWsaw
Note
Medium Risk
Changes SNP hardware-identity admission policy and weakens a firmware-enforced identity guarantee when owners opt out, though duplicate-hardware dedup still limits credit farming on Linux KVM.
Overview
Production AMD SEV-SNP admission no longer always rejects guests without guest-policy bit 20 (
SINGLE_SOCKET). Owner policycathedral_amd_sev_snp_policy_v1now accepts optionalrequire_single_socket(missing meanstrue, preserving legacy policy files and digests). When set tofalse, multi-socket KVM guests can pass the same gate that previously returnedsnp_single_socket_required; debug and migration-agent checks are unchanged.SnpProductionVerifierreads the flag at verify time, returnsguest_policyon pass/fail at that gate, andfleet_scoremachine rows exposeguest_policy_hexandsingle_socketfor telemetry. Dev preview docs still hard-require the bit; production behavior is documented with the duplicate-hardware caveat.Tests cover refuse/admit paths, back-compat, strict JSON typing, and that relaxing single-socket does not widen other guest-policy bits.
Reviewed by Cursor Bugbot for commit fd5059c. Bugbot is set up for automated code reviews on this repo. Configure here.