|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | +/* |
| 3 | + * Copyright (C) 2023 SUSE LLC |
| 4 | + * Author: Nicolai Stange <[email protected]> |
| 5 | + * LTP port: Martin Doucha <[email protected]> |
| 6 | + */ |
| 7 | + |
| 8 | +/*\ |
| 9 | + * CVE 2021-3653 |
| 10 | + * |
| 11 | + * Check that KVM either blocks enabling virtual interrupt controller (AVIC) |
| 12 | + * in nested VMs or correctly sets up the required memory address translation. |
| 13 | + * If AVIC is enabled without address translation in the host kernel, |
| 14 | + * the nested VM will be able to read and write an arbitraty physical memory |
| 15 | + * page specified by the parent VM. Unauthorized memory access fixed in: |
| 16 | + * |
| 17 | + * commit 0f923e07124df069ba68d8bb12324398f4b6b709 |
| 18 | + * Author: Maxim Levitsky <[email protected]> |
| 19 | + * Date: Thu Jul 15 01:56:24 2021 +0300 |
| 20 | + * |
| 21 | + * KVM: nSVM: avoid picking up unsupported bits from L2 in int_ctl (CVE-2021-3653) |
| 22 | + */ |
| 23 | + |
| 24 | +#include "kvm_test.h" |
| 25 | + |
| 26 | +#ifdef COMPILE_PAYLOAD |
| 27 | +#if defined(__i386__) || defined(__x86_64__) |
| 28 | + |
| 29 | +#include "kvm_x86_svm.h" |
| 30 | + |
| 31 | +#define AVIC_REG_ADDR 0x280 |
| 32 | +#define AVIC_TEST_VAL 0xec |
| 33 | +#define AVIC_READ_FAIL 0x12ead |
| 34 | + |
| 35 | +#define AVIC_INFO_MASK ((1ULL << 32) | 0xff0) |
| 36 | +#define AVIC_INFO_EXP ((1ULL << 32) | AVIC_REG_ADDR) |
| 37 | + |
| 38 | +static uint32_t * const avic_ptr = (uint32_t *)AVIC_REG_ADDR; |
| 39 | + |
| 40 | +static int guest_main(void) |
| 41 | +{ |
| 42 | + if (*avic_ptr != 0xaaaaaaaa) |
| 43 | + return AVIC_READ_FAIL; |
| 44 | + |
| 45 | + *avic_ptr = AVIC_TEST_VAL; |
| 46 | + return 0; |
| 47 | +} |
| 48 | + |
| 49 | +void main(void) |
| 50 | +{ |
| 51 | + struct kvm_svm_vcpu *vcpu; |
| 52 | + |
| 53 | + kvm_init_svm(); |
| 54 | + vcpu = kvm_create_svm_vcpu(guest_main, 1); |
| 55 | + |
| 56 | + /* |
| 57 | + * Enable AVIC and set both the AVIC base address (where the nested VM |
| 58 | + * will write) and backing page address (where the parent VM expects |
| 59 | + * to see the changes) to 0 |
| 60 | + */ |
| 61 | + vcpu->vmcb->virt_intr_ctl |= SVM_INTR_AVIC; |
| 62 | + vcpu->vmcb->avic_backing_page = 0; |
| 63 | + vcpu->vmcb->avic_bar = 0; |
| 64 | + memset((void *)8, 0xaa, PAGESIZE - 8); |
| 65 | + |
| 66 | + /* Write into AVIC backing page in the nested VM */ |
| 67 | + kvm_svm_vmrun(vcpu); |
| 68 | + |
| 69 | + switch (vcpu->vmcb->exitcode) { |
| 70 | + case SVM_EXIT_HLT: |
| 71 | + if (vcpu->vmcb->rax == AVIC_READ_FAIL) { |
| 72 | + tst_res(TFAIL, "Nested VM can read host memory"); |
| 73 | + return; |
| 74 | + } |
| 75 | + |
| 76 | + if (vcpu->vmcb->rax) |
| 77 | + tst_brk(TBROK, "Unexpected guest_main() return value"); |
| 78 | + |
| 79 | + break; |
| 80 | + |
| 81 | + case SVM_EXIT_AVIC_NOACCEL: |
| 82 | + if ((vcpu->vmcb->exitinfo1 & AVIC_INFO_MASK) == AVIC_INFO_EXP) { |
| 83 | + tst_res(TPASS, "AVIC register write caused VMEXIT"); |
| 84 | + break; |
| 85 | + } |
| 86 | + |
| 87 | + /* unexpected exit, fall through */ |
| 88 | + |
| 89 | + default: |
| 90 | + tst_brk(TBROK, "Nested VM exited unexpectedly"); |
| 91 | + } |
| 92 | + |
| 93 | + if (*avic_ptr != AVIC_TEST_VAL) { |
| 94 | + tst_res(TFAIL, "Write into AVIC ESR redirected to host memory"); |
| 95 | + return; |
| 96 | + } |
| 97 | + |
| 98 | + tst_res(TPASS, "Writes into AVIC backing page were not redirected"); |
| 99 | +} |
| 100 | + |
| 101 | +#else /* defined(__i386__) || defined(__x86_64__) */ |
| 102 | +TST_TEST_TCONF("Test supported only on x86"); |
| 103 | +#endif /* defined(__i386__) || defined(__x86_64__) */ |
| 104 | + |
| 105 | +#else /* COMPILE_PAYLOAD */ |
| 106 | + |
| 107 | +static struct tst_test test = { |
| 108 | + .test_all = tst_kvm_run, |
| 109 | + .setup = tst_kvm_setup, |
| 110 | + .cleanup = tst_kvm_cleanup, |
| 111 | + .supported_archs = (const char *const []) { |
| 112 | + "x86_64", |
| 113 | + "x86", |
| 114 | + NULL |
| 115 | + }, |
| 116 | + .tags = (struct tst_tag[]){ |
| 117 | + {"linux-git", "0f923e07124d"}, |
| 118 | + {"CVE", "2021-3653"}, |
| 119 | + {} |
| 120 | + } |
| 121 | +}; |
| 122 | + |
| 123 | +#endif /* COMPILE_PAYLOAD */ |
0 commit comments