summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorSean Christopherson <seanjc@google.com>2026-05-01 13:22:35 -0700
committerPaolo Bonzini <pbonzini@redhat.com>2026-05-29 20:25:29 +0200
commitc8cc238093ca6c99267032f6cfe78f59389f3157 (patch)
treeae7749e898b104245f073e2c16b4f7272fb04839 /arch
parent121d88de56bc5c0ba0ce2f6381af67f948a7e7c1 (diff)
downloadlinux-next-c8cc238093ca6c99267032f6cfe78f59389f3157.tar.gz
linux-next-c8cc238093ca6c99267032f6cfe78f59389f3157.zip
KVM: SEV: Use READ_ONCE() when reading entries/indices from PSC buffer
Use READ_ONCE() when reading entries/indices from the guest-accessible Page State Change buffer to defend against TOCTOU bugs. Don't bother with READ_ONCE()/WRITE_ONCE() for cases where KVM is writing (and not consuming the result!), as the guest isn't supposed to touch the buffer while it's being processed. I.e. using READ_ONCE() is all about protecting against misbehaving guests. Fixes: 9b54e248d264 ("KVM: SEV: Add support to handle Page State Change VMGEXIT") Cc: stable@vger.kernel.org Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com> Signed-off-by: Sean Christopherson <seanjc@google.com> Message-ID: <20260501202250.2115252-11-seanjc@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kvm/svm/sev.c12
1 files changed, 6 insertions, 6 deletions
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 6e8cbae2135a..62b5befe0eed 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -3872,9 +3872,9 @@ static void __snp_complete_one_psc(struct vcpu_svm *svm)
*/
for (idx = svm->sev_es.psc_idx; svm->sev_es.psc_inflight;
svm->sev_es.psc_inflight--, idx++) {
- struct psc_entry *entry = &entries[idx];
+ struct psc_entry entry = READ_ONCE(entries[idx]);
- entry->cur_page = entry->pagesize ? 512 : 1;
+ entries[idx].cur_page = entry.pagesize ? 512 : 1;
}
hdr->cur_entry = idx;
@@ -3938,8 +3938,8 @@ next_range:
* validation, so take care to only use validated copies of values used
* for things like array indexing.
*/
- idx_start = hdr->cur_entry;
- idx_end = hdr->end_entry;
+ idx_start = READ_ONCE(hdr->cur_entry);
+ idx_end = READ_ONCE(hdr->end_entry);
if (idx_end >= max_nr_entries) {
snp_complete_psc(svm, VMGEXIT_PSC_ERROR_INVALID_HDR);
@@ -3948,7 +3948,7 @@ next_range:
/* Find the start of the next range which needs processing. */
for (idx = idx_start; idx <= idx_end; idx++, hdr->cur_entry++) {
- entry_start = entries[idx];
+ entry_start = READ_ONCE(entries[idx]);
gfn = entry_start.gfn;
huge = entry_start.pagesize;
@@ -3992,7 +3992,7 @@ next_range:
* KVM_HC_MAP_GPA_RANGE exit.
*/
while (++idx <= idx_end) {
- struct psc_entry entry = entries[idx];
+ struct psc_entry entry = READ_ONCE(entries[idx]);
if (entry.operation != entry_start.operation ||
entry.gfn != entry_start.gfn + npages ||