diff options
| author | Alexander Potapenko <glider@google.com> | 2025-09-30 11:02:37 +0200 |
|---|---|---|
| committer | Alexander Potapenko <glider@google.com> | 2025-10-17 06:51:20 +0000 |
| commit | 6ca4530067ac25a78291b176b6d3dbe6ba592d15 (patch) | |
| tree | 731490cefa5b43b5ccf48f83f77979a829da72c0 /executor | |
| parent | 554d3ef1c24ae1bc3c8c439e8c8f3a9006434244 (diff) | |
executor: introduce DEFINE_GUEST_FN_TO_GPA_FN()
DEFINE_GUEST_FN_TO_GPA_FN() allows to define helper functions to
calculate guest addresses in the host/guest code.
Diffstat (limited to 'executor')
| -rw-r--r-- | executor/common_kvm.h | 18 | ||||
| -rw-r--r-- | executor/common_kvm_amd64.h | 12 | ||||
| -rw-r--r-- | executor/common_kvm_arm64.h | 11 |
3 files changed, 39 insertions, 2 deletions
diff --git a/executor/common_kvm.h b/executor/common_kvm.h index fecd00922..b11e3e06b 100644 --- a/executor/common_kvm.h +++ b/executor/common_kvm.h @@ -5,6 +5,24 @@ // Common KVM-related definitions. +extern char *__start_guest, *__stop_guest; + +// Define a function that calculates the guest physical address for a guest function. +// Execute failure_action if the function does not belong to the guest section. +// This function is using volatile accesses, otherwise the compiler may attempt +// to store e.g. &__start_guest + offset as a constant in .rodata. +#define DEFINE_GUEST_FN_TO_GPA_FN(fn_name, offset, failure_action) \ + static inline uintptr_t fn_name(uintptr_t f) \ + { \ + volatile uintptr_t start = (uintptr_t)&__start_guest; \ + volatile uintptr_t stop = (uintptr_t)&__stop_guest; \ + if (f >= start && f < stop) { \ + return f - start + (offset); \ + } \ + (failure_action); \ + return 0; \ + } + #if SYZ_EXECUTOR || __NR_syz_kvm_assert_syzos_kvm_exit static long syz_kvm_assert_syzos_kvm_exit(volatile long a0, volatile long a1) { diff --git a/executor/common_kvm_amd64.h b/executor/common_kvm_amd64.h index 718d63243..39804b4b8 100644 --- a/executor/common_kvm_amd64.h +++ b/executor/common_kvm_amd64.h @@ -883,6 +883,16 @@ static volatile long syz_kvm_setup_cpu(volatile long a0, volatile long a1, volat #endif #if SYZ_EXECUTOR || __NR_syz_kvm_add_vcpu + +// Post-processing code in pkg/csource/csource.go is very picky and won't let us directly pass +// fail() to DEFINE_GUEST_FN_TO_GPA_FN. +static inline void error_in_executor_fn_guest_addr() +{ + fail("SYZOS: executor_fn_guest_addr: invalid guest address"); +} + +DEFINE_GUEST_FN_TO_GPA_FN(executor_fn_guest_addr, X86_SYZOS_ADDR_EXECUTOR_CODE, error_in_executor_fn_guest_addr()); + static void reset_cpu_regs(int cpufd, int cpu_id, size_t text_size) { struct kvm_regs regs; @@ -890,7 +900,7 @@ static void reset_cpu_regs(int cpufd, int cpu_id, size_t text_size) regs.rflags |= 2; // bit 1 is always set // PC points to the relative offset of guest_main() within the guest code. - regs.rip = X86_SYZOS_ADDR_EXECUTOR_CODE + ((uint64)guest_main - (uint64)&__start_guest); + regs.rip = executor_fn_guest_addr((uintptr_t)guest_main); regs.rsp = X86_SYZOS_ADDR_STACK0; // Pass parameters to guest_main(). regs.rdi = text_size; diff --git a/executor/common_kvm_arm64.h b/executor/common_kvm_arm64.h index 4428a3484..badfcf417 100644 --- a/executor/common_kvm_arm64.h +++ b/executor/common_kvm_arm64.h @@ -144,11 +144,20 @@ static void vcpu_set_reg(int vcpu_fd, uint64 id, uint64 val) ioctl(vcpu_fd, KVM_SET_ONE_REG, ®); } +// Post-processing code in pkg/csource/csource.go is very picky and won't let us directly pass +// fail() to DEFINE_GUEST_FN_TO_GPA_FN. +static inline void error_in_executor_fn_guest_addr() +{ + fail("SYZOS: executor_fn_guest_addr: invalid guest address"); +} + +DEFINE_GUEST_FN_TO_GPA_FN(executor_fn_guest_addr, ARM64_ADDR_EXECUTOR_CODE, error_in_executor_fn_guest_addr()); + // Set up CPU registers. static void reset_cpu_regs(int cpufd, int cpu_id, size_t text_size) { // PC points to the relative offset of guest_main() within the guest code. - vcpu_set_reg(cpufd, KVM_ARM64_REGS_PC, ARM64_ADDR_EXECUTOR_CODE + ((uint64)guest_main - (uint64)&__start_guest)); + vcpu_set_reg(cpufd, KVM_ARM64_REGS_PC, executor_fn_guest_addr((uintptr_t)guest_main)); vcpu_set_reg(cpufd, KVM_ARM64_REGS_SP_EL1, ARM64_ADDR_EL1_STACK_BOTTOM + KVM_PAGE_SIZE - 128); // Store the CPU ID in TPIDR_EL1. vcpu_set_reg(cpufd, KVM_ARM64_REGS_TPIDR_EL1, cpu_id); |
