aboutsummaryrefslogtreecommitdiffstats
path: root/executor
diff options
context:
space:
mode:
Diffstat (limited to 'executor')
-rw-r--r--executor/common_kvm.h18
-rw-r--r--executor/common_kvm_amd64.h12
-rw-r--r--executor/common_kvm_arm64.h11
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, &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);