diff options
| author | Alexander Potapenko <glider@google.com> | 2025-10-14 13:20:39 +0200 |
|---|---|---|
| committer | Alexander Potapenko <glider@google.com> | 2025-10-17 06:51:20 +0000 |
| commit | e18aa5057febfc3f9f61c8755234e361528def0e (patch) | |
| tree | 49bb7b0dd0b2841fca59d6eb23f49818332cdf81 /executor/common_kvm.h | |
| parent | bc0cbe5709e294d9755f481e7f41be68413e14f9 (diff) | |
executor: introduce __addrspace_guest
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().
Diffstat (limited to 'executor/common_kvm.h')
| -rw-r--r-- | executor/common_kvm.h | 45 |
1 files changed, 28 insertions, 17 deletions
diff --git a/executor/common_kvm.h b/executor/common_kvm.h index b11e3e06b..5be283046 100644 --- a/executor/common_kvm.h +++ b/executor/common_kvm.h @@ -5,23 +5,34 @@ // 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; \ - } +#include "common_kvm_syzos.h" +#include "kvm.h" + +#if SYZ_EXECUTOR || __NR_syz_kvm_add_vcpu +extern char* __start_guest; + +// executor_fn_guest_addr() is compiled into both the host and the guest code. +static inline uintptr_t executor_fn_guest_addr(void* fn) +{ + // Prevent the compiler from creating a .rodata constant for + // &__start_guest + SYZOS_ADDR_EXECUTOR_CODE. + volatile uintptr_t start = (uintptr_t)&__start_guest; + volatile uintptr_t offset = SYZOS_ADDR_EXECUTOR_CODE; + return (uintptr_t)fn - start + offset; +} + +#if SYZ_EXECUTOR +// In Clang-based C++ builds, use template magic to ensure that only guest functions can be passed +// to executor_fn_guest_addr(). +template <typename R, typename... A> +uintptr_t static inline executor_fn_guest_addr(__addrspace_guest R (*fn)(A...)) +{ + return executor_fn_guest_addr((void*)fn); +} + +#endif + +#endif #if SYZ_EXECUTOR || __NR_syz_kvm_assert_syzos_kvm_exit static long syz_kvm_assert_syzos_kvm_exit(volatile long a0, volatile long a1) |
