From: Sean Christopherson <seanjc@google.com>
To: Michael Roth <michael.roth@amd.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>,
Paolo Bonzini <pbonzini@redhat.com>,
kvm@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2 2/6] KVM: selftests: Add a test to verify SEV {en,de}crypt debug ioctls
Date: Wed, 24 Jun 2026 14:24:24 -0700 [thread overview]
Message-ID: <ajxLCMgLQe-JiRfq@google.com> (raw)
In-Reply-To: <ajsjQtpZb-h2BdPh@google.com>
On Tue, Jun 23, 2026, Sean Christopherson wrote:
> On Tue, Jun 23, 2026, Michael Roth wrote:
> > On Tue, Jun 23, 2026 at 07:55:27PM +0000, Sean Christopherson wrote:
> > since your proposed fix seems nicer and more complete anyway.
>
> It's missing a case though :-(
Ah, but so is the revert, and it's not a coincidence that the old code didn't
bounce buffer the destination for KVM_SEV_DBG_ENCRYPT.
> The final write for ENCRYPT writes to the destination directly:
>
> r = sev_issue_dbg_cmd(kvm, __sme_set(__pa(buf)), dst_pa,
> nr_bytes, KVM_SEV_DBG_ENCRYPT, err);
>
> More at the bottom.
Once more, with feeling...
> > > diff --git arch/x86/kvm/svm/sev.c arch/x86/kvm/svm/sev.c
> > > index 87025d0d2f91..7e3334c90c57 100644
> > > --- arch/x86/kvm/svm/sev.c
> > > +++ arch/x86/kvm/svm/sev.c
> > > @@ -1406,7 +1406,8 @@ static int sev_dbg_crypt(struct kvm *kvm, struct kvm_sev_cmd *argp,
> > > sev_clflush_pages(&src_p, 1);
> > > sev_clflush_pages(&dst_p, 1);
> > >
> > > - if (IS_ALIGNED(src, 16) && IS_ALIGNED(dst, 16) && IS_ALIGNED(len, 16))
> > > + if (IS_ALIGNED(src, 16) && IS_ALIGNED(dst, 16) && IS_ALIGNED(len, 16) &&
> > > + (!cc_platform_has(CC_ATTR_HOST_SEV_SNP) || cmd != KVM_SEV_DBG_DECRYPT))
> > > ret = sev_issue_dbg_cmd(kvm,
> > > __sme_page_pa(src_p) + s_off,
> > > __sme_page_pa(dst_p) + d_off,
> > >
> > > But if firmware temporarily converts *both* pages, then we're "stuck" because at
> > > some point KVM needs to actually target the correct guest-owned page. The only
> > > option I can think of is to require capable(CAP_SYS_BOOT), *if* the above doesn't
> > > suffice.
> >
> > Not sure I understand fully, but snp_populate_cmd_buf_desc_list() in the
> > firmware driver requires the transiton for the destination page that we
> > write to both for 'encrypt' as well as 'decrypt'. What the issue with
> > using a temp buffer as the destination for the 'encrypt' case?
>
> The problem is if KVM does NOT use a temporary buffer, which is the "fast" path
> where src, dst, and len are all 16-byte aligned. In that case, KVM does inline
> {de,en}cryption between src and dst. But those pages are also mapped into
> userspace (they have to be, since KVM pins them via gup()), which means that
> userspace could feed the same pages to a different chunk of the kernel that
> reads/write userspace memory via gup() (or gup-like equivalent).
>
> E.g. pread()/read() on shmem-backed memory.
pread() doesn't work, because the source or destination needs to be a userspace
address, and so any RMP #PFs will get eaten. But copy_file_range() makes the
world go kablooie.
Weirdly, I haven't been able to get a splat of any kind, the host just goes
AWOL and reboots. But I'm very confident RMP #PFs are the issue, because doing
the same operation via writes in userspace yields:
sev_dbg_test-24385 [049] d.... 1892.853197: page_fault_user: address=0x7fc63f8fe000 ip=0x41cb44 error_code=0x80000007
sev_dbg_test-24385 [049] d.... 1892.853202: page_fault_user: address=0x7fc63f8fe000 ip=0x41cb44 error_code=0x80000007
sev_dbg_test-24385 [049] d.... 1892.853204: page_fault_user: address=0x7fc63f8fe000 ip=0x41cb44 error_code=0x80000007
sev_dbg_test-24385 [049] d.... 1892.853206: page_fault_user: address=0x7fc63f8fe000 ip=0x41cb44 error_code=0x80000007
sev_dbg_test-24385 [049] d.... 1892.853207: page_fault_user: address=0x7fc63f8fe000 ip=0x41cb44 error_code=0x80000007
sev_dbg_test-24385 [049] d.... 1892.853209: page_fault_user: address=0x7fc63f8fe000 ip=0x41cb44 error_code=0x80000007
sev_dbg_test-24385 [049] d.... 1892.853211: page_fault_user: address=0x7fc63f8fe000 ip=0x41cb44 error_code=0x80000007
sev_dbg_test-24385 [049] d.... 1892.853212: page_fault_user: address=0x7fc63f8fe000 ip=0x41cb44 error_code=0x80000007
> Looking at the full picture, isn't this a bug in the PSP driver that affects all
> commands? With pre-SNP VMs, "guest owned" isn't really a thing, since nothing
> guarantees that the destination page is accessible *only* by the guest.
>
> If we rip that out and always bounce-buffer, then KVM won't have to force its
> own bounce buffering of sub-page lengths for SNP, and that would eliminate the
> race I described above.
>
> Completely untested (I'll give this a whirl tomorrow).
So this doesn't work. Dredging up some knowledge of how this all works, I'm
fairly certain the issue is that the encryption is salted with the physical address,
and so encrypting at X instead of Y will yield different ciphertext. I.e. any
command that encrypts the contents in the destination (or in theory, decrypts,
though AFAICT none of the commands do so) *can't* be bounce buffered.
I don't see a way to salvage SEV/SEV-ES on SNP systems, short of requiring
CAP_SYS_BOOT or some other elevated permission to do *anything*. Or redo SEV/SEV-ES
support to require guest_memfd for operations that require putting pages into
Firmware state.
next prev parent reply other threads:[~2026-06-24 21:24 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-01 20:35 [PATCH v2 0/6] KVM: SEV: sev_dbg_crypt() fix and overhaul Sean Christopherson
2026-05-01 20:35 ` [PATCH v2 1/6] KVM: SVM: Fix page overflow in sev_dbg_crypt() for ENCRYPT path Sean Christopherson
2026-05-01 20:35 ` [PATCH v2 2/6] KVM: selftests: Add a test to verify SEV {en,de}crypt debug ioctls Sean Christopherson
2026-05-21 7:04 ` [PATCH v2 2/6] KVM: selftests: Add a test to verify SEV {en,de}crypt kernel test robot
2026-05-21 14:28 ` Sean Christopherson
[not found] ` <ajNQ_Ix5e0p6FuFT@google.com>
[not found] ` <tx3hcnrhfbcz2p7e7umc5o2zrw74pluzuzgtlqt4dz5cc5nhxx@6tzzorc25nqw>
[not found] ` <s7jfbw3tnfgmp6blfqlfoi7yhq6f5n6xl62zzty5up45cqtsty@ljpjlvqw2gyy>
2026-06-23 19:55 ` [PATCH v2 2/6] KVM: selftests: Add a test to verify SEV {en,de}crypt debug ioctls Sean Christopherson
2026-06-23 23:22 ` Michael Roth
2026-06-24 0:22 ` Sean Christopherson
2026-06-24 21:24 ` Sean Christopherson [this message]
2026-06-24 23:11 ` Michael Roth
2026-06-25 0:25 ` Sean Christopherson
2026-05-01 20:35 ` [PATCH v2 3/6] KVM: SEV: Explicitly validate the dst buffer for debug operations Sean Christopherson
2026-05-01 20:35 ` [PATCH v2 4/6] KVM: SEV: Add helper function to pin/unpin a single page Sean Christopherson
2026-05-01 20:35 ` [PATCH v2 5/6] KVM: SEV: Rewrite logic to {de,en}crypt memory for debug Sean Christopherson
2026-05-01 20:35 ` [PATCH v2 6/6] KVM: SEV: Allocate only as many bytes as needed for temp crypt buffers Sean Christopherson
2026-05-19 0:41 ` [PATCH v2 0/6] KVM: SEV: sev_dbg_crypt() fix and overhaul Sean Christopherson
-- strict thread matches above, loose matches on Subject: below --
2026-04-16 23:10 Sean Christopherson
2026-04-16 23:10 ` [PATCH v2 2/6] KVM: selftests: Add a test to verify SEV {en,de}crypt debug ioctls Sean Christopherson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ajxLCMgLQe-JiRfq@google.com \
--to=seanjc@google.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=michael.roth@amd.com \
--cc=pbonzini@redhat.com \
--cc=thomas.lendacky@amd.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox