Skip to content

Commit 12765c1

Browse files
mdouchapevik
authored andcommitted
Add test for CVE 2021-3653
GCC 13 prints out-of-bounds warnings for statements dereferencing avic_ptr. According to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105523 this is a GCC bug. Reviewed-by: Petr Vorel <[email protected]> Acked-by: Cyril Hrubis <[email protected]> Signed-off-by: Martin Doucha <[email protected]>
1 parent ae8d5d4 commit 12765c1

File tree

3 files changed

+125
-0
lines changed

3 files changed

+125
-0
lines changed

runtest/kvm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
kvm_pagefault01 kvm_pagefault01
2+
kvm_svm01 kvm_svm01

testcases/kernel/kvm/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
/kvm_pagefault01
2+
/kvm_svm01

testcases/kernel/kvm/kvm_svm01.c

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
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

Comments
 (0)