aboutsummaryrefslogtreecommitdiffstats
path: root/executor/common_kvm_amd64.h
Commit message (Collapse)AuthorAgeFilesLines
* executor: fix TestGenerate/linux/amd64/Alexander Potapenko2026-02-171-1/+1
| | | | Follow-up fix for https://github.com/google/syzkaller/pull/6820
* executor: introduce gpa_to_hva() for x86 SYZOSAlexander Potapenko2026-02-171-8/+38
| | | | | | | | | | L1 guest memory is non-contiguous, but previously host setup assumed the opposite, using L1 guest addresses as offsets in the host memory block. This led to subtle bugs in IRQ handling (and possibly elsewhere). Fix this by using gpa_to_hva() to translate guest physical addresses to host virtual addresses. This function is cold, so we can afford O(SYZOS_REGION_COUNT) complexity.
* executor: fix x86 L1 SYZOS GDT setupAlexander Potapenko2026-02-111-2/+1
| | | | | | | | | | Moving setup_pg_table() before setup_gdt_64() prevents the page table initialization from accidentally erasing the newly created Global Descriptor Table (GDT). If the GDT is zeroed out, the CPU hardware cannot fetch the necessary code segment descriptors to deliver interrupts or exceptions, leading to unhandled #GP or #DF crashes.
* executor: dump GPRs in dump_vcpu_state()Alexander Potapenko2026-02-111-0/+3
| | | | This is only needed for tests generated by prog2c.
* executor: rework L1 segment setup in SYZOSAlexander Potapenko2026-02-091-8/+14
| | | | | | | | | | | | | | 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.
* executor: sys/linux: Implement nested SYZOS loadingAlexander Potapenko2026-02-091-8/+17
| | | | | | | | | | | | | | | | | | | 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.
* executor: enable X86_EFER_SVME for AMDAlexander Potapenko2026-02-091-2/+21
| | | | | When setting up L1 guest, execute CPUID and enable X86_EFER_SVME for AMD CPUs.
* executor: implement L2 memory mirroring and dynamic code loadingAlexander Potapenko2026-02-091-9/+0
| | | | | | | | | | | | | | | | Refactor the SYZOS L1 guest to construct L2 page tables dynamically by mirroring its own memory layout (provided via boot arguments) instead of using a static 2MB identity map. This change introduces l2_map_page to allocate unique backing memory for most regions, while mapping X86_SYZOS_ADDR_USER_CODE and X86_SYZOS_ADDR_STACK_BOTTOM to specific per-VM buffers reserved in L1. This allows L1 to inject code and stack content into backing buffers while the L2 guest executes them from standard virtual addresses. Additionally, MEM_REGION_FLAG_* definitions are moved to the guest header to support this logic.
* executor, tools: rename SyzOS to SYZOS6eanut2026-01-281-1/+1
|
* executor: implement dynamic L2 page table allocation in SYZOSAlexander Potapenko2026-01-261-12/+0
| | | | | | | | | | | | | | | | | | | Enable the SYZOS guest (L1) to dynamically allocate memory for nested L2 page tables, replacing the previous rigid static layout. Move the mem_region and syzos_boot_args struct definitions to the guest header (common_kvm_amd64_syzos.h) to allow the guest to parse the memory map injected by the host. Introduce a bump allocator, guest_alloc_page(), which targets the X86_SYZOS_ADDR_UNUSED heap. This allocator relies on a new struct syzos_globals located at X86_SYZOS_ADDR_GLOBALS to track the allocation offset. Refactor setup_l2_page_tables() to allocate intermediate paging levels (PDPT, PD, PT) via guest_alloc_page() instead of using fixed contiguous offsets relative to the PML4. This allows for disjoint memory usage and supports future recursion requirements.
* executor: introduce global state page for SYZOSAlexander Potapenko2026-01-261-0/+2
| | | | | | | | | | 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.
* executor: add boot arguments page to SYZOS layoutAlexander Potapenko2026-01-261-13/+50
| | | | | | | | | | | | | | | | | | | | 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.
* executor: isolate x86 page table pool to high memory in SYZOSAlexander Potapenko2026-01-261-18/+38
| | | | | | | | | | | | | | | | | | | | | | 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.
* executor: sys/linux: Add VCPU fd to `syz_kvm_assert_syzos_uexit`Alexander Potapenko2026-01-161-7/+55
| | | | | | | | Enhance the debugging capabilities of C reproducers by passing the VCPU file descriptor to the syz_kvm_assert_syzos_uexit function. With access to the VCPU fd, the function can now dump the VCPU's register state upon assertion failure, providing critical context for debugging guest execution issues.
* executor: x86: Configure L1 guest TSS for nested virtualizationAlexander Potapenko2025-11-191-3/+36
| | | | Set up the L1 guest's 64-bit Task State Segment (TSS), a prerequisite for VMX/SVM.
* executor: x86: Prepare memory layout and hardware constants for NVAlexander Potapenko2025-11-191-0/+2
| | | | | | | | | | | 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
* executor: add include guards to KVM headersAlexander Potapenko2025-10-271-0/+5
| | | | | Not having these results in three copies of every KVM-related #define in each reproducer.
* executor: introduce __addrspace_guestAlexander Potapenko2025-10-171-11/+3
| | | | | | | | | | | | Apply __addrspace_guest to every guest function and use a C++ template to statically validate that host functions are not passed to executor_fn_guest_addr(). This only works in Clang builds of syz-executor, because GCC does not support address spaces, and C reproducers cannot use templates. The static check allows us to drop the dynamic checks in DEFINE_GUEST_FN_TO_GPA_FN(). While at it, replace DEFINE_GUEST_FN_TO_GPA_FN() with explicit declarations of host_fn_guest_addr() and guest_fn_guest_addr().
* executor: unify ARM64_ADDR_EXECUTOR_CODE and X86_SYZOS_ADDR_EXECUTOR_CODEAlexander Potapenko2025-10-171-1/+1
| | | | | Use SYZOS_ADDR_EXECUTOR_CODE instead of both. Also put platform-specific definitions under #if GOARCH_xxx.
* executor: fix setup_cpuid() declarationAlexander Potapenko2025-10-171-0/+2
| | | | Make sure setup_cpuid() is only declared together with install_user_code()
* executor: sys/linux: implement SYZOS_API_SET_IRQ_HANDLERAlexander Potapenko2025-10-171-12/+0
| | | | | | | | | | The new API call allows to initialize the handler with one of the three possible values: - NULL (should cause a page fault) - dummy_null_handler (should call iret) - uexit_irq_handler (should perform guest_uexit(UEXIT_IRQ)) Also add a test for uexit_irq_handler()
* executor: use dynamic page table allocation for guestAlexander Potapenko2025-10-171-52/+35
| | | | | | | | 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.
* executor: refactor x86 SYZOS setupAlexander Potapenko2025-10-171-64/+65
| | | | | Pass around struct kvm_syzos_vm instead of one-off pointers to various guest memory ranges.
* executor: rework GDT setup for SYZOSAlexander Potapenko2025-10-171-54/+97
| | | | | Untangle SYZOS GDT setup from the legacy one. Drop LDT and TSS for now.
* executor: fix the definition of struct tss64Alexander Potapenko2025-10-171-2/+2
| | | | | Per https://wiki.osdev.org/Task_State_Segment#Long_Mode, io_bitmap and reserved3 should be 16-bit.
* executor: use a list of memory regions to set up SYZOS guestAlexander Potapenko2025-10-171-35/+44
| | | | | Instead of open-coding every memory region in several places, use a single array to configure their creation.
* executor: more robust x86 page table creation in SYZOSAlexander Potapenko2025-10-171-14/+97
| | | | | | Provide map_4k_region() to ease page table creation for different regions. While at it, also move the stack from 0x0 to 0x90000.
* executor: introduce DEFINE_GUEST_FN_TO_GPA_FN()Alexander Potapenko2025-10-171-1/+11
| | | | | DEFINE_GUEST_FN_TO_GPA_FN() allows to define helper functions to calculate guest addresses in the host/guest code.
* executor: rename SYZOS-related address definitionsAlexander Potapenko2025-10-171-10/+10
| | | | | | | To distinguish SYZOS addresses from other x86 definitions, change them to start with X86_SYZOS_ADDR_ No functional change.
* executor: sys/linux/: pkg/runtest: pkg/vminfo: add syz_kvm_assert_syzos_kvm_exitAlexander Potapenko2025-09-191-0/+1
| | | | Implement a pseudo-syscall to check the value of kvm_run.exit_reason
* executor/kvm: add x86-64 SYZOS fuzzerMarios Pomonis2025-04-231-7/+298
| | | | | | 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.
* executor/kvm: set up X86-64 SYZOSMarios Pomonis2025-04-231-0/+32
| | | | | This commit prepares adding the X86-64 SYZOS by declaring the relevant functions, updating their ARM64 versions and adding placeholders.
* executor/kvm: bug fix and minor refactor in KVMMarios Pomonis2025-03-271-204/+147
| | | | | | | | | | | | | | | | * 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.
* executor: fix uninitialized variable when generating kvm codeCookedMelon2024-04-051-0/+4
| | | | | | | | The "avl" fields (variable type is u8) of the kvm_segment structure variables such as seg_cs16 and seg_ldt are not initialized to zero. During creation, there is a chance that they are set to values other than 0 or 1, which can cause the "avl" fields to overwrite other fields when executing the fill_segment_descriptor function, leading to erroneous results.
* sys: skip kvm const extraction for non i386/amd64Aleksandr Nogikh2021-09-131-1/+1
| | | | | | | | | | | | It is impossible to compile a number of definitions in include/uapi/linux/kvm.h for other platforms, which leads to syz-extract failing to update constants. Skip processing of this file for all arches except i386 and amd64. This is a hacky and (hopefully) temporary solution until #2754 is implemented.
* executor: prepare code generator to allow other achitecturesAlexey Kardashevskiy2021-07-191-1/+1
| | | | | | | At the moment only AMD64 is supported, change file names to emphasise this. Signed-off-by: Alexey Kardashevskiy <aik@linux.ibm.com>
* executor: warn about C89-style var declarationsDmitry Vyukov2020-08-141-7/+4
| | | | | | | | | | | | | | | | | We generally use the newer C99 var declarations combined with initialization because: - declarations are more local, reduced scope - fewer lines of code - less potential for using uninit vars and other bugs However, we have some relic code from times when we did not understand if we need to stick with C89 or not. Also some external contributions that don't follow style around. Add a static check for C89-style declarations and fix existing precedents. Akaros toolchain uses -std=gnu89 (or something) and does not allow variable declarations inside of for init statement. And we can't switch it to -std=c99 because Akaros headers are C89 themselves. So in common.h we need to declare loop counters outside of for.
* executor: fix build errors in setup_32bit_idt()Denis Efremov2020-07-211-1/+1
| | | | | | | | | | GCC10 fails to build the code with errors: executor/common_kvm_amd64.h:143:64: error: ‘gate.kvm_segment::type’ may be used uninitialized in this function [-Werror=maybe-uninitialized] executor/common_kvm_amd64.h:143:56: error: ‘gate.kvm_segment::base’ may be used uninitialized in this function [-Werror=maybe-uninitialized] Replace 'case 6' with 'case 5' since 'i % 6' results in [0..5]. Signed-off-by: Denis Efremov <efremov@linux.com>
* executor: remove NONFAILING from pseudo-syscallsDmitry Vyukov2020-07-151-53/+46
| | | | | | This is not needed anymore afer the previous commit. Fixes #1918
* executor: prevent non-null expected warningsDmitry Vyukov2019-03-211-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | The added test triggers warnings like these: <stdin>: In function ‘syz_mount_image.constprop’: <stdin>:298:3: error: argument 1 null where non-null expected [-Werror=nonnull] In file included from <stdin>:26:0: /usr/include/x86_64-linux-gnu/sys/stat.h:320:12: note: in a call to function ‘mkdir’ declared here extern int mkdir (const char *__path, __mode_t __mode) ^~~~~ cc1: all warnings being treated as errors <stdin>: In function ‘syz_open_procfs.constprop’: <stdin>:530:41: error: ‘%s’ directive argument is null [-Werror=format-truncation=] <stdin>:85:110: note: in definition of macro ‘NONFAILING’ <stdin>:532:41: error: ‘%s’ directive argument is null [-Werror=format-truncation=] <stdin>:85:110: note: in definition of macro ‘NONFAILING’ <stdin>:534:41: error: ‘%s’ directive argument is null [-Werror=format-truncation=] <stdin>:85:110: note: in definition of macro ‘NONFAILING’ Use volatile for all arguments of syz_ functions to prevent compiler from treating the arguments as constants in reproducers. Popped up during bisection that used a repro that previously worked. Update #501
* executor: compile with -O2Dmitry Vyukov2018-02-101-10/+11
| | | | | We don't frequently debug it and it does some intensive computations on coverage, so no reason to not compile with -O2.
* executor: introduce uint64/32/16/8 typesDmitry Vyukov2017-12-271-94/+94
| | | | | | | | | | | | | | | The "define uint64_t unsigned long long" were too good to work. With a different toolchain I am getting: cstdint:69:11: error: expected unqualified-id using ::uint64_t; ^ executor/common.h:34:18: note: expanded from macro 'uint64_t' Do it the proper way: introduce uint64/32/16/8 types and use them. pkg/csource then does s/uint64/uint64_t/ to not clutter code with additional typedefs.
* csource: don't use guard macros for debug() and NONFAILING()Andrey Konovalov2017-06-121-76/+69
|
* csource: only handle SIGSEGV when necessaryAndrey Konovalov2017-06-121-0/+9
|
* sys: improve kvm descriptionDmitry Vyukov2017-01-281-62/+103
| | | | | | Allow fuzzer to change types of segment descriptors. Alter more flags. Allow fuzzer to do a random vmwrite.
* executor: protect against memory corruptions betterDmitry Vyukov2017-01-251-1/+1
| | | | | | | | | | | Fuzzer has figured out how to corrupt input/output shmem regions abusing the text memcpy in syz_kvm_setup_cpu. It guessed a negative text_size value that causes the memcpy to overwrite shmem regions. Protect better against such cases: 1. Make text_size unsigned (there is already a check that it is less than 1000). 2. Map input region as readable only, we don't write to it. 3. Add address sanity check to segv_handler, if we see that we are writing into executable data, it's better to crash instantly.
* sys, executor: more kvm improvementsDmitry Vyukov2017-01-121-0/+768
1. Basic support for arm64 kvm testing. 2. Fix compiler warnings in x86 kvm code. 3. Test all pseudo syz calls in csource. 4. Fix handling of real code in x86.