aboutsummaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorAlexander Potapenko <glider@google.com>2026-01-19 09:38:53 +0100
committerAlexander Potapenko <glider@google.com>2026-01-19 11:05:35 +0000
commite2d17597c5c0f0be4b4b6e992d9434edef02c2f0 (patch)
treea2c78281c94c7a8e244863b40672d07afb3e97f0 /sys
parent8a9c6fb791de2ce75347ae863885b4584ac82afe (diff)
executor: sys/linux: SYZOS: add AMD SET_INTERCEPT primitive
This patch introduces SYZOS_API_NESTED_AMD_SET_INTERCEPT to SYZOS. This primitive enables the fuzzer to surgically modify intercept vectors in the AMD VMCB (Virtual Machine Control Block) Control Area. It implements a read-modify-write operation on 32-bit VMCB offsets, allowing the L1 hypervisor (SYZOS) to deterministically set or clear specific intercept bits (e.g., for RDTSC, HLT, or exceptions) for the L2 guest. This capability allows syzkaller to systematically explore KVM's nested SVM emulation logic by toggling intercepts on and off, rather than relying on static defaults or random memory corruption.
Diffstat (limited to 'sys')
-rw-r--r--sys/linux/dev_kvm_amd64.txt8
-rw-r--r--sys/linux/test/amd64-syz_kvm_nested_amd_set_intercept39
2 files changed, 47 insertions, 0 deletions
diff --git a/sys/linux/dev_kvm_amd64.txt b/sys/linux/dev_kvm_amd64.txt
index acd80540c..0d90ceeab 100644
--- a/sys/linux/dev_kvm_amd64.txt
+++ b/sys/linux/dev_kvm_amd64.txt
@@ -160,6 +160,13 @@ syzos_api_nested_amd_inject_event {
flags int64[0:3]
}
+syzos_api_nested_amd_set_intercept {
+ vm_id syzos_api_vm_id
+ offset int64
+ bit_mask int64
+ action int64[0:1]
+}
+
# IDs here must match those in executor/common_kvm_amd64_syzos.h.
syzos_api_call$x86 [
uexit syzos_api$x86[0, intptr]
@@ -183,6 +190,7 @@ syzos_api_call$x86 [
nested_amd_stgi syzos_api$x86[382, void]
nested_amd_clgi syzos_api$x86[383, void]
nested_amd_inject_event syzos_api$x86[384, syzos_api_nested_amd_inject_event]
+ nested_amd_set_intercept syzos_api$x86[385, syzos_api_nested_amd_set_intercept]
] [varlen]
kvm_text_x86 [
diff --git a/sys/linux/test/amd64-syz_kvm_nested_amd_set_intercept b/sys/linux/test/amd64-syz_kvm_nested_amd_set_intercept
new file mode 100644
index 000000000..91293ba0d
--- /dev/null
+++ b/sys/linux/test/amd64-syz_kvm_nested_amd_set_intercept
@@ -0,0 +1,39 @@
+#
+# requires: arch=amd64 -threaded
+#
+r0 = openat$kvm(0, &AUTO='/dev/kvm\x00', 0x0, 0x0)
+r1 = ioctl$KVM_CREATE_VM(r0, AUTO, 0x0)
+r2 = syz_kvm_setup_syzos_vm$x86(r1, &(0x7f0000c00000/0x400000)=nil)
+
+# Test AMD Nested Intercepts: The RDTSC Liberation
+#
+# 1. L1 Setup:
+# - SYZOS initializes VMCB with ALL intercepts enabled.
+# - We call SET_INTERCEPT to *CLEAR* the RDTSC intercept.
+# - Offset: 0xC (Control Vector 1)
+# - Bit: 14 (0x4000) = RDTSC
+# - Action: 0 (Clear/Disable)
+#
+# 2. L2 Payload:
+# - "rdtsc" (0x0f 0x31)
+# - "hlt" (0xf4)
+#
+# 3. Execution Flow:
+# - If RDTSC is intercepted: Exit Reason = RDTSC (0x4).
+# - If RDTSC is native: executes RDTSC -> executes HLT -> Exit Reason = HLT (0x1).
+#
+r3 = syz_kvm_add_vcpu$x86(r2, &AUTO={0x0, &AUTO=[@enable_nested={AUTO, AUTO, 0x0}, @nested_create_vm={AUTO, AUTO, 0x0}, @nested_amd_set_intercept={AUTO, AUTO, {0x0, 0xC, 0x4000, 0x0}}, @nested_load_code={AUTO, AUTO, {0x0, "0f31f4"}}, @nested_vmlaunch={AUTO, AUTO, 0x0}], AUTO})
+r4 = ioctl$KVM_GET_VCPU_MMAP_SIZE(r0, AUTO)
+r5 = mmap$KVM_VCPU(&(0x7f0000009000/0x1000)=nil, r4, 0x3, 0x1, r3, 0x0)
+
+# Run the VCPU.
+# Expectation: Success (Native Execution) -> HLT Exit.
+# Code: 0xe2e20001 (SYZOS_NESTED_EXIT_REASON_HLT)
+#
+ioctl$KVM_RUN(r3, AUTO, 0x0)
+syz_kvm_assert_syzos_uexit$x86(r3, r5, 0xe2e20001)
+
+# Cleanup
+#
+ioctl$KVM_RUN(r3, AUTO, 0x0)
+syz_kvm_assert_syzos_uexit$x86(r3, r5, 0xffffffffffffffff)