| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This patch enables syzos for riscv64 and implements
the corresponding pseudo syscalls.
Pseudo syscalls:
- syz_kvm_setup_syzos_vm
- syz_kvm_add_vcpu
- syz_kvm_assert_syzos_uexit
Syzos guest support:
- guest_uexit
- guest_execute_code
- guest_handle_csrr and guest_handle_csrw
Test seeds:
- riscv64-syz_kvm_setup_syzos_vm
- riscv64-syz_kvm_setup_syzos_vm-csrr
- riscv64-syz_kvm_setup_syzos_vm-csrw
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
This commit corrects the GDT setup for the data and TSS segments in L1.
Previously, the data segment was incorrectly using the TSS base address,
and the TSS base address was not properly set.
The data segment base is now set to 0, as it should be for a flat 64-bit
model. The TSS segment descriptor in the GDT now correctly points to
X86_SYZOS_ADDR_VAR_TSS and uses the full 64-bit address.
The attributes are also updated to mark the TSS as busy.
Additionally, the TSS region is now explicitly copied from L1 to L2 to
ensure the L2 environment has a valid TSS.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This commit introduces the `SYZOS_API_NESTED_LOAD_SYZOS` command to
enable running full SYZOS programs within a nested L2 guest, enhancing
fuzzing capabilities for nested virtualization.
Key changes include:
- Nested SYZOS Execution: The new command loads a SYZOS program into an
L2 VM, setting up its execution environment.
- ABI Refinement: Program size is now passed via the shared `syzos_globals`
memory region instead of registers, standardizing the ABI for L1 and L2.
- L2 State Management: Improved saving and restoring of L2 guest GPRs
across VM-exits using inline assembly wrappers for Intel and AMD.
- Nested UEXIT Propagation: Intercepts EPT/NPT faults on the exit page to
capture the L2 exit code from saved registers and forward it to L0 with
an incremented nesting level.
- L2 Memory Management: Updates to L2 page table setup, including skipping
NO_HOST_MEM regions to force exits, and a new `l2_gpa_to_pa` helper.
|
| |
|
|
|
| |
X86_CR4_OSFXSR is 1<<9 according to
https://wiki.osdev.org/CPU_Registers_x86
|
| |
|
|
|
|
|
|
|
|
| |
Reserve a dedicated 4KB page at X86_SYZOS_ADDR_GLOBALS (0x17F000) to
store global state shared across the SYZOS L1 guest environment.
This region is required to store the state of the guest-side memory
allocator (specifically the allocation offset and total size of the
unused heap), enabling thread-safe dynamic memory allocation for nested
L2 page tables.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Introduce a dedicated page at X86_SYZOS_ADDR_BOOT_ARGS to pass
configuration data from the executor to the SYZOS guest. This will allow
dynamic adjustments to the guest environment, such as specifying memory
region sizes.
- Added `MEM_REGION_FLAG_REMAINING` to flag the last memory region, which
will consume the rest of the available guest memory.
- Defined `struct syzos_boot_args` to pass the memory region layout to the
guest.
- Modified `syzos_mem_regions`:
- Reduced X86_SYZOS_ADDR_VAR_IDT size to 10 pages.
- Inserted the new X86_SYZOS_ADDR_BOOT_ARGS region.
- Added a final region with MEM_REGION_FLAG_REMAINING.
- Updated `setup_vm` to:
- Calculate the size of the REMAINING region.
- Populate the `syzos_boot_args` structure in the boot args page.
- Updated `setup_pg_table` to use the REMAINING flag to map the last region.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Refactor the SYZOS guest memory layout to decouple the dynamic page table
allocator from the fixed system data structures (GDT, IDT, initial PML4).
Previously, the page table pool was located at 0x5000, tightly packed with
the initial system pages. This rigid structure made it difficult to expand
the pool or inject configuration data without shifting fixed offsets.
Move X86_SYZOS_ADDR_PT_POOL to 0x180000, creating a distinct high-memory
region well above the L2 VCPU data, and increase the pool size to 64 pages
(256KB) to support deeper nested hierarchies.
Update the syz_kvm_setup_syzos_vm logic to handle non-contiguous
Guest-to-Host address translation via a new get_host_pte_ptr() helper.
This is necessary because the executor's host memory allocation remains
strictly linear while the guest physical address space now contains
significant gaps.
This layout change is a prerequisite for enabling "SYZOS inside SYZOS"
(L2 nesting), allowing the future injection of boot arguments into the
gap created between fixed data and dynamic regions.
|
| |
|
|
|
|
|
| |
Enable basic RDTSCP handling. Ensure that Intel hosts exit on RDTSCP
in L2, and that both Intel and AMD can handle RDTSCP exits.
Add amd64-syz_kvm_nested_vmresume-rdtscp to test that.
|
| |
|
|
|
|
|
| |
Enable basic RDTSC handling. Ensure that Intel hosts exit on RDTSC
in L2, and that both Intel and AMD can handle RDTSC exits.
Add amd64-syz_kvm_nested_vmresume-rdtsc to test that.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Provide the SYZOS API command to resume L2 execution after a VM exit,
using VMRESUME on Intel and VMRUN on AMD.
For testing purpose, implement basic handling of the INVD instruction:
- enable INVD interception on AMD (set all bits in VMCB 00Ch);
- map EXIT_REASON_INVD and VMEXIT_INVD into SYZOS_NESTED_EXIT_REASON_INVD;
- advance L2 RIP to skip to the next instruction.
While at it, perform minor refactorings of L2 exit reason handling.
sys/linux/test/amd64-syz_kvm_nested_vmresume tests the new command by
executing two instructions, INVD and HLT, in the nested VM.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Provide a SYZOS API command to launch the L2 VM using the
VMLAUNCH (Intel) or VMRUN (AMD) instruction.
For testing purposes, each L2->L1 exit is followed by a guest_uexit_l2()
returning the exit code to L0. Common exit reasons (like HLT) will be
mapped into a common exit code space (0xe2e20000 | reason), so that
a single test can be used for both Intel and AMD.
Vendor-specific exit codes will be returned using the 0xe2110000 mask
for Intel and 0xe2aa0000 for AMD.
|
| |
|
|
|
|
| |
Provide basic setup for registers, page tables, and segments to create
Intel/AMD-based nested virtual machines.
Note that the machines do not get started yet.
|
| |
|
|
|
|
| |
Add vendor-specific code to turn on nested virtualization on Intel
and AMD. Also provide get_cpu_vendor() to pick the correct
implementation.
|
| |
|
|
| |
Set up the L1 guest's 64-bit Task State Segment (TSS), a prerequisite for VMX/SVM.
|
| |
|
|
|
|
|
|
|
|
|
| |
This patch lays the groundwork for nested virtualization by rearranging
the KVM guest's memory map.
Key changes include:
- Introducing a dedicated per-VCPU memory region for L2 VMs.
- Updating `executor/kvm.h` with:
- Adjusted stack addresses for the L1 guest.
- Detailed memory layout macros for L2 VM structures
|
| |
|
|
|
| |
Not having these results in three copies of every KVM-related #define
in each reproducer.
|
| |
|
|
|
| |
Use SYZOS_ADDR_EXECUTOR_CODE instead of both. Also put platform-specific
definitions under #if GOARCH_xxx.
|
| |
|
|
|
|
|
|
| |
Use a pool of 32 pages to allocate PT and PE entries for the guest
page tables.
This eliminates the need for manually assigned page table entries
that are brittle and may break when someone changes the memory
layout.
|
| |
|
|
|
| |
Pass around struct kvm_syzos_vm instead of one-off pointers to
various guest memory ranges.
|
| |
|
|
|
| |
Untangle SYZOS GDT setup from the legacy one.
Drop LDT and TSS for now.
|
| |
|
|
|
|
| |
Provide map_4k_region() to ease page table creation for different
regions.
While at it, also move the stack from 0x0 to 0x90000.
|
| |
|
|
|
|
|
| |
To distinguish SYZOS addresses from other x86 definitions, change them
to start with X86_SYZOS_ADDR_
No functional change.
|
| |
|
|
|
|
| |
This commit adds the actual SyzOS fuzzer for x86-64 and a small test. It
also updates some necessary parts of the ARM version and adds some glue
for i386.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* Fixes a bug when setting up a 64-bit guest by making the bit
manipulation macros produce unsigned long long: To create a VCPU that
has paging enabled, one needs to set the CR0.PE and CR0.PG bits in
CR0. The latter is problematic when setting up a 64-bit guest since if
the macro is not using 1ULL, it sign extends the output (in 64-bit
mode the control registers are extended to 64-bits with some of the
CR0[32:63] bits reserved). This results in either failing the
KVM_SET_SREGS ioctl (in newer kernel versions) or just failing the
KVM_RUN ioctl with EXIT_REASON_INVALID_STATE.
* Moved the bit manipulation definitions from the amd64 specific to the generic
kvm header to consolidate them with the already existing ones.
Prefixed them with X86_ to avoid confusion.
|
| |
|
|
|
| |
The new API call implements basic setup of the ARM Interrupt Translation Service
for the given number of CPUs, virtual devices, and LPIs.
|
| | |
|
| |
|
|
|
|
|
| |
Reserve SYZOS address for the ITS redistributor at 0x08080000, add it to the
list of kvm_guest_addrs.
Also implement a syzlang test for the host part of ITS configuration as per
https://www.kernel.org/doc/html/v6.1/virt/kvm/devices/arm-vgic-its.html
|
| |
|
|
|
| |
To ease fuzzing the dirty ring, explicitly reserve two pages with
the KVM_MEM_LOG_DIRTY_PAGES flag at known address.
|
| |
|
|
|
| |
The new pseudo-syscall sets up VGICv3 IRQ controller on the host.
That still requires guest setup code, which will be submitted separately.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
MSR is an ARM64 instruction that writes a value from a GP register to
one of the system CPU registers. Exposing those registers to a fuzzer will
let us trigger unexpected behavior in handling them on the kernel side.
The SYZOS_API_MSR call has two int64 arguments, register ID and value.
Register IDs are 64-bit values obtained from ARM64_SYS_REG() in the Linux asm/kvm.h
UAPI header. Same register IDs are used by ioctl$KVM_GET_ONE_REG and
ioctl$KVM_SET_ONE_REG.
Also add sys/linux/test/syz_kvm_setup_cpu_arm64-msr
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Allow guest payload to call syzos API functions. The available calls
are enumerated by SYZOS_API_* constants, and have a form of:
struct api_call {
uint64 call;
uint64 struct_size;
/* arbitrary call-related data here */
};
Complex instruction sequences are too easy to break, so most of the time
fuzzer won't be able to efficiently mutate them.
We replace kvm_text_arm64 with a sequence of `struct api_call`, making it
possible to intermix assembly instructions (SYZOS_API_CODE) with
higher-level constructs.
Right now the supported calls are:
- SYZOS_API_UEXIT - abort from KVM_RUN (1 argument: exit code, uint64)
- SYZOS_API_CODE - execute an ARM64 assembly blob
(1 argument: inline array of int32's)
|
| |
|
|
|
|
|
|
|
|
| |
For KVM fuzzing we are going to need some library code that will be
running inside KVM to perform common tasks (e.g. register accesses,
device setup etc.)
This code will reside in a special ".guest" section that the executor
will map at address 0xeeee8000. For now it contains just the main function,
but will be extended in further patches.
|
| |
|
|
|
|
|
| |
Refactor phys page allocation in syz_kvm_setup_cpu$arm64 to prepare for
more address ranges.
Load user-supplied code at ARM64_ADDR_USER_CODE and allocate EL1 stack
at ARM64_ADDR_EL1_STACK_BOTTOM.
|
| |
|
|
|
|
| |
Allow fuzzer to change types of segment descriptors.
Alter more flags.
Allow fuzzer to do a random vmwrite.
|
|
|
Add new pseudo syscall syz_kvm_setup_cpu that setups VCPU into
interesting states for execution. KVM is too difficult to setup otherwise.
Lots of improvements possible, but this is a starting point.
|