Bug 2028584 (CVE-2021-4093)

Summary: CVE-2021-4093 kernel: KVM: SVM: out-of-bounds read/write in sev_es_string_io
Product: [Other] Security Response Reporter: Guilherme de Almeida Suckevicz <gsuckevi>
Component: vulnerabilityAssignee: Nobody <nobody>
Status: NEW --- QA Contact:
Severity: medium Docs Contact:
Priority: medium    
Version: unspecifiedCC: acaringi, adscvr, airlied, alciregi, bhu, blc, chwhite, crwood, dvlasenk, hdegoede, hkrzesin, jarod, jarodwilson, jburrell, jeremy, jforbes, jglisse, jlelli, jonathan, josef, jshortt, jstancek, jwboyer, kcarcia, kernel-maint, kernel-mgr, lgoncalv, linville, masami256, mcascell, mchehab, mlangsdo, nmurray, ptalbert, qzhao, rvrbovsk, steved, vkumar, walters, williams
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: kernel 5.15 Doc Type: If docs needed, set a value
Doc Text:
A flaw was found in the KVM's AMD code for supporting the Secure Encrypted Virtualization-Encrypted State (SEV-ES). A KVM guest using SEV-ES can trigger out-of-bounds reads and writes in the host kernel via a malicious VMGEXIT for a string I/O instruction (for example, outs or ins) using the exit reason SVM_EXIT_IOIO. This issue results in a crash of the entire system or a potential guest-to-host escape scenario.
Story Points: ---
Clone Of: Environment:
Last Closed: Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On: 2006441, 2009338, 2009340, 2028585, 2031089, 2031090, 2031091    
Bug Blocks: 2027465, 2031109    

Description Guilherme de Almeida Suckevicz 2021-12-02 17:07:35 UTC
A KVM guest using SEV-ES (Secure Encrypted Virtualization - Encrypted State) can trigger out-of-bounds reads and writes in the host kernel via a malicious VMGEXIT using the exit reason SVM_EXIT_IOIO.

Comment 1 Guilherme de Almeida Suckevicz 2021-12-02 17:08:01 UTC
Created kernel tracking bugs for this issue:

Affects: fedora-all [bug 2028585]

Comment 3 Mauro Matteo Cascella 2021-12-10 10:39:27 UTC
This issue was fixed in upstream kernel v5.15. The main commit fix is:

- KVM: SEV-ES: go over the sev_pio_data buffer in multiple passes if needed
  [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=95e16b4]

Together with the following preparative commits:

- KVM: SEV-ES: rename guest_ins_data to sev_pio_data
  [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b599840]

- KVM: x86: leave vcpu->arch.pio.count alone in emulator_pio_in_out
  [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0d33b1b]

- KVM: SEV-ES: clean up kvm_sev_es_ins/outs
  [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ea724ea]

- KVM: x86: split the two parts of emulator_pio_in
  [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3b27de2]

- KVM: x86: remove unnecessary arguments from complete_emulator_pio_in
  [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6b5efc9]

- KVM: SEV-ES: keep INS functions together
  [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4fa4b38]

Comment 4 Mauro Matteo Cascella 2021-12-10 10:43:23 UTC
Also consider the following commit, which fixes a related issue:

- KVM: SEV-ES: fix another issue with string I/O VMGEXITs
  [https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9b0971c]

Comment 6 Mauro Matteo Cascella 2021-12-10 13:48:16 UTC
AMD SEV-ES support was introduced in upstream kernel v5.10:

http://lkml.iu.edu/hypermail/linux/kernel/2010.1/05072.html

RHEL-6 and RHEL-7 kernels are not affected by this flaw as they did not include support for SEV-ES (not even for SEV, FWIW).

Comment 10 Mauro Matteo Cascella 2021-12-13 10:11:26 UTC
In reply to comment #0:
> A KVM guest using SEV-ES (Secure Encrypted Virtualization - Encrypted State)
> can trigger out-of-bounds reads and writes in the host kernel via a
> malicious VMGEXIT using the exit reason SVM_EXIT_IOIO.

In particular, the flaw occurs in sev_es_string_io() while handling string I/O instructions (e.g. outs or ins). The string is copied from the unencrypted guest memory into GHCB (Guest-Hypervisor Communication Block) using guest-controlled values for the length and I/O access size. At some point, the control flow will reach emulator_pio_out() where data is copied into `vcpu->arch.pio_data` which is only one virtual page size in length. If the guest provides a size that makes the memcpy() exceeds one page, it will trigger an out of bounds read/write access on adjacent pages.

Comment 11 Justin M. Forbes 2022-01-05 14:37:48 UTC
This was fixed for Fedora with the 5.14.15 stable kernel updates.