diff options
| author | Alexander Potapenko <glider@google.com> | 2025-11-18 12:07:13 +0100 |
|---|---|---|
| committer | Alexander Potapenko <glider@google.com> | 2025-11-19 08:59:40 +0000 |
| commit | 5af4be3c78a6a9fc6a3c9c3d1a48151f190c9221 (patch) | |
| tree | ffc583dc53550376e34eb33fceafad7b74076cf6 /executor | |
| parent | 3bf489934f218dfcb171b6db6db3ecce818971db (diff) | |
executor: sys/linux: implement SYZOS_API_NESTED_LOAD_CODE
The new command loads an instruction blob into the specified L2 VM.
Diffstat (limited to 'executor')
| -rw-r--r-- | executor/common_kvm_amd64_syzos.h | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/executor/common_kvm_amd64_syzos.h b/executor/common_kvm_amd64_syzos.h index 9f93af017..739868440 100644 --- a/executor/common_kvm_amd64_syzos.h +++ b/executor/common_kvm_amd64_syzos.h @@ -28,6 +28,7 @@ typedef enum { SYZOS_API_SET_IRQ_HANDLER = 200, SYZOS_API_ENABLE_NESTED = 300, SYZOS_API_NESTED_CREATE_VM = 301, + SYZOS_API_NESTED_LOAD_CODE = 302, SYZOS_API_STOP, // Must be the last one } syzos_api_id; @@ -46,6 +47,12 @@ struct api_call_code { uint8 insns[]; }; +struct api_call_nested_load_code { + struct api_call_header header; + uint64 vm_id; + uint8 insns[]; +}; + struct api_call_cpuid { struct api_call_header header; uint32 eax; @@ -85,6 +92,7 @@ GUEST_CODE static void guest_handle_out_dx(struct api_call_3* cmd); GUEST_CODE static void guest_handle_set_irq_handler(struct api_call_2* cmd); GUEST_CODE static void guest_handle_enable_nested(struct api_call_1* cmd, uint64 cpu_id); GUEST_CODE static void guest_handle_nested_create_vm(struct api_call_1* cmd, uint64 cpu_id); +GUEST_CODE static void guest_handle_nested_load_code(struct api_call_nested_load_code* cmd, uint64 cpu_id); typedef enum { UEXIT_END = (uint64)-1, @@ -185,6 +193,9 @@ guest_main(uint64 size, uint64 cpu) } else if (call == SYZOS_API_NESTED_CREATE_VM) { // Create a nested VM. guest_handle_nested_create_vm((struct api_call_1*)cmd, cpu); + } else if (call == SYZOS_API_NESTED_LOAD_CODE) { + // Load code into the nested VM. + guest_handle_nested_load_code((struct api_call_nested_load_code*)cmd, cpu); } addr += cmd->size; size -= cmd->size; @@ -534,6 +545,14 @@ GUEST_CODE static void guest_memset(void* s, uint8 c, int size) p[i] = c; } +GUEST_CODE static void guest_memcpy(void* dst, void* src, int size) +{ + volatile uint8* d = (volatile uint8*)dst; + volatile uint8* s = (volatile uint8*)src; + for (int i = 0; i < size; i++) + d[i] = s[i]; +} + GUEST_CODE static noinline void nested_enable_vmx_intel(uint64 cpu_id) { @@ -928,4 +947,26 @@ guest_handle_nested_create_vm(struct api_call_1* cmd, uint64 cpu_id) } } +GUEST_CODE static noinline void +guest_handle_nested_load_code(struct api_call_nested_load_code* cmd, uint64 cpu_id) +{ + uint64 vm_id = cmd->vm_id; + uint64 l2_code_addr = X86_SYZOS_ADDR_VM_CODE(cpu_id, vm_id); + uint64 l2_stack_addr = X86_SYZOS_ADDR_VM_STACK(cpu_id, vm_id); + // Code size = command size - header size - vm_id size. + uint64 l2_code_size = cmd->header.size - sizeof(struct api_call_header) - sizeof(uint64); + if (l2_code_size > KVM_PAGE_SIZE) + l2_code_size = KVM_PAGE_SIZE; + guest_memcpy((void*)l2_code_addr, (void*)cmd->insns, + l2_code_size); + if (get_cpu_vendor() == CPU_VENDOR_INTEL) { + nested_vmptrld(cpu_id, vm_id); + vmwrite(VMCS_GUEST_RIP, l2_code_addr); + vmwrite(VMCS_GUEST_RSP, l2_stack_addr + KVM_PAGE_SIZE - 8); + } else { + vmcb_write64(X86_SYZOS_ADDR_VMCS_VMCB(cpu_id, vm_id), VMCB_GUEST_RIP, l2_code_addr); + vmcb_write64(X86_SYZOS_ADDR_VMCS_VMCB(cpu_id, vm_id), VMCB_GUEST_RSP, l2_stack_addr + KVM_PAGE_SIZE - 8); + } +} + #endif // EXECUTOR_COMMON_KVM_AMD64_SYZOS_H |
