aboutsummaryrefslogtreecommitdiffstats
path: root/executor
diff options
context:
space:
mode:
authorAlexander Potapenko <glider@google.com>2025-09-30 14:12:48 +0200
committerAlexander Potapenko <glider@google.com>2025-10-17 06:51:20 +0000
commitfe2df35c1db3ce6dece1feb776f6a7c22e89be22 (patch)
treea585b24445c2e982625b1b41afae95e271d2b0b4 /executor
parentc7354acdafe9a5bdf11bafed36b695588185a198 (diff)
executor: use a list of memory regions to set up SYZOS guest
Instead of open-coding every memory region in several places, use a single array to configure their creation.
Diffstat (limited to 'executor')
-rw-r--r--executor/common_kvm_amd64.h79
1 files changed, 44 insertions, 35 deletions
diff --git a/executor/common_kvm_amd64.h b/executor/common_kvm_amd64.h
index 4792c47a1..0cc21753c 100644
--- a/executor/common_kvm_amd64.h
+++ b/executor/common_kvm_amd64.h
@@ -202,6 +202,31 @@ static void setup_64bit_idt(struct kvm_sregs* sregs, char* host_mem, uintptr_t g
}
#endif
+#if SYZ_EXECUTOR || __NR_syz_kvm_setup_cpu || __NR_syz_kvm_setup_syzos_vm
+// Flags for mem_region
+#define MEM_REGION_FLAG_USER_CODE (1 << 0)
+#define MEM_REGION_FLAG_DIRTY_LOG (1 << 1)
+#define MEM_REGION_FLAG_READONLY (1 << 2)
+#define MEM_REGION_FLAG_EXECUTOR_CODE (1 << 3)
+
+struct mem_region {
+ uint64 gpa;
+ int pages;
+ uint32 flags;
+};
+
+static const struct mem_region syzos_mem_regions[] = {
+ {X86_SYZOS_ADDR_ZERO, 20, 0},
+ {X86_SYZOS_ADDR_SMRAM, 10, 0},
+ {X86_SYZOS_ADDR_DIRTY_PAGES, 2, MEM_REGION_FLAG_DIRTY_LOG},
+ {X86_SYZOS_ADDR_USER_CODE, KVM_MAX_VCPU, MEM_REGION_FLAG_READONLY | MEM_REGION_FLAG_USER_CODE},
+ {X86_SYZOS_ADDR_EXECUTOR_CODE, 4, MEM_REGION_FLAG_READONLY | MEM_REGION_FLAG_EXECUTOR_CODE},
+ {X86_SYZOS_ADDR_SCRATCH_CODE, 1, 0},
+ {X86_SYZOS_ADDR_STACK_BOTTOM, 1, 0},
+ {X86_SYZOS_ADDR_IOAPIC, 1, 0},
+};
+#endif
+
#if SYZ_EXECUTOR || __NR_syz_kvm_setup_cpu || __NR_syz_kvm_add_vcpu
struct kvm_text {
uintptr_t typ;
@@ -303,14 +328,8 @@ static void setup_pg_table(void* host_mem)
memset((void*)((uint64)host_mem + X86_SYZOS_ADDR_PT_IOAPIC), 0, KVM_PAGE_SIZE);
// Map all the regions defined in setup_vm()
- total -= map_4k_region(host_mem, X86_SYZOS_ADDR_ZERO, 20);
- total -= map_4k_region(host_mem, X86_SYZOS_ADDR_SMRAM, 10);
- total -= map_4k_region(host_mem, X86_SYZOS_ADDR_DIRTY_PAGES, 2);
- total -= map_4k_region(host_mem, X86_SYZOS_ADDR_USER_CODE, KVM_MAX_VCPU);
- total -= map_4k_region(host_mem, X86_SYZOS_ADDR_EXECUTOR_CODE, 4);
- total -= map_4k_region(host_mem, X86_SYZOS_ADDR_SCRATCH_CODE, 1);
- total -= map_4k_region(host_mem, X86_SYZOS_ADDR_STACK_BOTTOM, 1);
- total -= map_4k_region(host_mem, X86_SYZOS_ADDR_IOAPIC, 1);
+ for (size_t i = 0; i < sizeof(syzos_mem_regions) / sizeof(syzos_mem_regions[0]); i++)
+ total -= map_4k_region(host_mem, syzos_mem_regions[i].gpa, syzos_mem_regions[i].pages);
map_4k_region(host_mem, X86_SYZOS_ADDR_UNUSED, total);
// Mapping for MMIO region should be present even though there is no
// corresponding physical memory.
@@ -1059,35 +1078,25 @@ static void setup_vm(int vmfd, void* host_mem, void** text_slot)
// This *needs* to be the first allocation to avoid passing pointers
// around for the gdt/ldt/page table setup.
- struct addr_size next = alloc_guest_mem(&allocator, 20 * KVM_PAGE_SIZE);
- vm_set_user_memory_region(vmfd, slot++, 0, X86_SYZOS_ADDR_ZERO, next.size, (uintptr_t)next.addr);
-
- next = alloc_guest_mem(&allocator, 10 * KVM_PAGE_SIZE);
- vm_set_user_memory_region(vmfd, slot++, 0, X86_SYZOS_ADDR_SMRAM, next.size, (uintptr_t)next.addr);
-
- next = alloc_guest_mem(&allocator, 2 * KVM_PAGE_SIZE);
- vm_set_user_memory_region(vmfd, slot++, KVM_MEM_LOG_DIRTY_PAGES, X86_SYZOS_ADDR_DIRTY_PAGES, next.size, (uintptr_t)next.addr);
-
- next = alloc_guest_mem(&allocator, KVM_MAX_VCPU * KVM_PAGE_SIZE);
- vm_set_user_memory_region(vmfd, slot++, KVM_MEM_READONLY, X86_SYZOS_ADDR_USER_CODE, next.size, (uintptr_t)next.addr);
- if (text_slot)
- *text_slot = next.addr;
-
- struct addr_size host_text = alloc_guest_mem(&allocator, 4 * KVM_PAGE_SIZE);
- install_syzos_code(host_text.addr, host_text.size);
- vm_set_user_memory_region(vmfd, slot++, KVM_MEM_READONLY, X86_SYZOS_ADDR_EXECUTOR_CODE, host_text.size, (uintptr_t)host_text.addr);
-
- next = alloc_guest_mem(&allocator, KVM_PAGE_SIZE);
- vm_set_user_memory_region(vmfd, slot++, 0, X86_SYZOS_ADDR_SCRATCH_CODE, next.size, (uintptr_t)next.addr);
-
- next = alloc_guest_mem(&allocator, KVM_PAGE_SIZE);
- vm_set_user_memory_region(vmfd, slot++, 0, X86_SYZOS_ADDR_STACK_BOTTOM, next.size, (uintptr_t)next.addr);
-
- next = alloc_guest_mem(&allocator, KVM_PAGE_SIZE);
- vm_set_user_memory_region(vmfd, slot++, 0, X86_SYZOS_ADDR_IOAPIC, next.size, (uintptr_t)next.addr);
+ for (size_t i = 0; i < sizeof(syzos_mem_regions) / sizeof(syzos_mem_regions[0]); i++) {
+ const struct mem_region* r = &syzos_mem_regions[i];
+ struct addr_size next = alloc_guest_mem(&allocator, r->pages * KVM_PAGE_SIZE);
+ uint32 flags = 0;
+ if (r->flags & MEM_REGION_FLAG_DIRTY_LOG)
+ flags |= KVM_MEM_LOG_DIRTY_PAGES;
+ if (r->flags & MEM_REGION_FLAG_READONLY)
+ flags |= KVM_MEM_READONLY;
+ if (r->flags & MEM_REGION_FLAG_USER_CODE) {
+ if (text_slot)
+ *text_slot = next.addr;
+ }
+ if (r->flags & MEM_REGION_FLAG_EXECUTOR_CODE)
+ install_syzos_code(next.addr, next.size);
+ vm_set_user_memory_region(vmfd, slot++, flags, r->gpa, next.size, (uintptr_t)next.addr);
+ }
// Map the remaining pages at an unused address.
- next = alloc_guest_mem(&allocator, allocator.size);
+ struct addr_size next = alloc_guest_mem(&allocator, allocator.size);
vm_set_user_memory_region(vmfd, slot++, 0, X86_SYZOS_ADDR_UNUSED, next.size, (uintptr_t)next.addr);
}
#endif