| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
| |
Enhance the debugging capabilities of C reproducers by passing the VCPU
file descriptor to the syz_kvm_assert_syzos_uexit function. With access to
the VCPU fd, the function can now dump the VCPU's register state upon
assertion failure, providing critical context for debugging guest execution
issues.
|
| |
|
|
|
| |
Not having these results in three copies of every KVM-related #define
in each reproducer.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
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().
|
| |
|
|
|
| |
Use SYZOS_ADDR_EXECUTOR_CODE instead of both. Also put platform-specific
definitions under #if GOARCH_xxx.
|
| |
|
|
|
| |
DEFINE_GUEST_FN_TO_GPA_FN() allows to define helper functions to
calculate guest addresses in the host/guest code.
|
| |
|
|
| |
Implement a pseudo-syscall to check the value of kvm_run.exit_reason
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* Fixes a bug when setting up a 64-bit guest by making the bit
manipulation macros produce unsigned long long: To create a VCPU that
has paging enabled, one needs to set the CR0.PE and CR0.PG bits in
CR0. The latter is problematic when setting up a 64-bit guest since if
the macro is not using 1ULL, it sign extends the output (in 64-bit
mode the control registers are extended to 64-bits with some of the
CR0[32:63] bits reserved). This results in either failing the
KVM_SET_SREGS ioctl (in newer kernel versions) or just failing the
KVM_RUN ioctl with EXIT_REASON_INVALID_STATE.
* Moved the bit manipulation definitions from the amd64 specific to the generic
kvm header to consolidate them with the already existing ones.
Prefixed them with X86_ to avoid confusion.
|
| |
|
|
| |
Add a pseudo-syscall to assert on register values.
|
| |
|
|
|
| |
The new pseudo-syscall will serve as a test assertion, checking the uexit
return value. This is going to help us validate SyzOS code.
|
| |
|
|
|
|
|
|
|
| |
When running syscalls asynchronously, syz_kvm_add_vcpu() sometimes
receives a zero VM handle, on which it then crashes.
Check for the zero value to ensure stability of the tests in sys/linux/tests.
Also make sure to set errno for the pseudo-syscall in the cases where it's not
done by the underlying syscalls.
|
| |
|
|
|
|
|
| |
Detect and report ADRP instructions in the linked binaries to avoid
crashes inside SyzOS.
See https://github.com/google/syzkaller/issues/5565 for more context.
|
| |
|
|
|
|
|
| |
Pass 1024 pages of memory to both syz_kvm_setup_syzos_vm() and
syz_kvm_setup_cpu$arm64() to make sure that:
- there is enough memory for guest allocations (e.g. ITS pages)
- host can tamper with that memory, provoking more bugs
|
| | |
|
| | |
|
| |
|
|
|
| |
It is more common for the constants in the executor to not have the
SYZ_ prefix.
|
| |
|
|
|
|
|
|
|
| |
Let SYZOS distinguish CPUs inside VM by storing their ID in TPIDR_EL1.
Make sure existing code uses that ID:
- in guest_handle_msr(), to ensure concurrent calls do not write to the
same cache line;
- in gicv3_irq_enable(), to ensure proper CPU ID is being used for
IRQ setup.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
syz_kvm_add_vcpu
The old syz_kvm_setup_cpu() API mixed together VM and VCPU setup, making it
harder to create and fuzz two VCPUs in the same VM.
Introduce two new pseudo-syscalls, syz_kvm_setup_syzos_vm() and syz_kvm_add_vcpu(),
that will simplify this task.
syz_kvm_setup_syzos_vm() takes a VM file descriptor, performs VM setup
(allocates guest memory and installs SYZOS code into it) and returns a
new kvm_syz_vm resource, which is in fact a pointer to `struct kvm_syz_vm`
encapsulating VM-specific data in the C code.
syz_kvm_add_vcpu() takes the VM ID denoted by kvm_syz_vm and creates a
new VCPU within that VM with a proper CPU number. It then stores the
fuzzer-supplied SYZOS API sequence into the corresponding part (indexed by
CPU number) of the VM memory slot, and sets up the CPU registers to interpret
that sequence.
The new pseudo-syscall let the fuzzer create independent CPUs that run different
code sequences without interfering with each other.
|
| |
|
|
|
|
|
|
| |
Prepare to let multiple (up to 4) CPUs run different pieces of code
by allocating 4 pages for ARM64_ADDR_USER_CODE.
Pass the CPU id to guest_main(), so that it can pick the correct
starting addres.
syz_kvm_setup_cpu() will implicitly use cpuid=0 to retain its current functionality.
|
| |
|
|
|
|
|
|
|
| |
No functional change.
For multiple CPUs within the same VM, calls to syz_kvm_setup_cpu()
will set up the VM memory space multiple times, so only the last one
will take effect.
Prepare to decouple VM setup from CPU setup by factoring this code out
of syz_kvm_setup_cpu().
|
| |
|
|
|
| |
To ease fuzzing the dirty ring, explicitly reserve two pages with
the KVM_MEM_LOG_DIRTY_PAGES flag at known address.
|
| |
|
|
|
| |
The new pseudo-syscall sets up VGICv3 IRQ controller on the host.
That still requires guest setup code, which will be submitted separately.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
MSR is an ARM64 instruction that writes a value from a GP register to
one of the system CPU registers. Exposing those registers to a fuzzer will
let us trigger unexpected behavior in handling them on the kernel side.
The SYZOS_API_MSR call has two int64 arguments, register ID and value.
Register IDs are 64-bit values obtained from ARM64_SYS_REG() in the Linux asm/kvm.h
UAPI header. Same register IDs are used by ioctl$KVM_GET_ONE_REG and
ioctl$KVM_SET_ONE_REG.
Also add sys/linux/test/syz_kvm_setup_cpu_arm64-msr
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Allow guest payload to call syzos API functions. The available calls
are enumerated by SYZOS_API_* constants, and have a form of:
struct api_call {
uint64 call;
uint64 struct_size;
/* arbitrary call-related data here */
};
Complex instruction sequences are too easy to break, so most of the time
fuzzer won't be able to efficiently mutate them.
We replace kvm_text_arm64 with a sequence of `struct api_call`, making it
possible to intermix assembly instructions (SYZOS_API_CODE) with
higher-level constructs.
Right now the supported calls are:
- SYZOS_API_UEXIT - abort from KVM_RUN (1 argument: exit code, uint64)
- SYZOS_API_CODE - execute an ARM64 assembly blob
(1 argument: inline array of int32's)
|
| |
|
|
|
|
|
|
|
|
| |
For KVM fuzzing we are going to need some library code that will be
running inside KVM to perform common tasks (e.g. register accesses,
device setup etc.)
This code will reside in a special ".guest" section that the executor
will map at address 0xeeee8000. For now it contains just the main function,
but will be extended in further patches.
|
| |
|
|
|
|
|
| |
Refactor phys page allocation in syz_kvm_setup_cpu$arm64 to prepare for
more address ranges.
Load user-supplied code at ARM64_ADDR_USER_CODE and allocate EL1 stack
at ARM64_ADDR_EL1_STACK_BOTTOM.
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
| |
It is impossible to compile a number of definitions in
include/uapi/linux/kvm.h for other platforms, which leads
to syz-extract failing to update constants.
Skip processing of this file for all arches except i386 and
amd64.
This is a hacky and (hopefully) temporary solution until #2754
is implemented.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We generally use the newer C99 var declarations combined with initialization because:
- declarations are more local, reduced scope
- fewer lines of code
- less potential for using uninit vars and other bugs
However, we have some relic code from times when we did not understand
if we need to stick with C89 or not. Also some external contributions
that don't follow style around.
Add a static check for C89-style declarations and fix existing precedents.
Akaros toolchain uses -std=gnu89 (or something) and does not allow
variable declarations inside of for init statement. And we can't switch
it to -std=c99 because Akaros headers are C89 themselves.
So in common.h we need to declare loop counters outside of for.
|
| |
|
|
|
|
| |
This is not needed anymore afer the previous commit.
Fixes #1918
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The added test triggers warnings like these:
<stdin>: In function ‘syz_mount_image.constprop’:
<stdin>:298:3: error: argument 1 null where non-null expected [-Werror=nonnull]
In file included from <stdin>:26:0:
/usr/include/x86_64-linux-gnu/sys/stat.h:320:12: note: in a call to function ‘mkdir’ declared here
extern int mkdir (const char *__path, __mode_t __mode)
^~~~~
cc1: all warnings being treated as errors
<stdin>: In function ‘syz_open_procfs.constprop’:
<stdin>:530:41: error: ‘%s’ directive argument is null [-Werror=format-truncation=]
<stdin>:85:110: note: in definition of macro ‘NONFAILING’
<stdin>:532:41: error: ‘%s’ directive argument is null [-Werror=format-truncation=]
<stdin>:85:110: note: in definition of macro ‘NONFAILING’
<stdin>:534:41: error: ‘%s’ directive argument is null [-Werror=format-truncation=]
<stdin>:85:110: note: in definition of macro ‘NONFAILING’
Use volatile for all arguments of syz_ functions to prevent
compiler from treating the arguments as constants in reproducers.
Popped up during bisection that used a repro that previously worked.
Update #501
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The "define uint64_t unsigned long long" were too good to work.
With a different toolchain I am getting:
cstdint:69:11: error: expected unqualified-id
using ::uint64_t;
^
executor/common.h:34:18: note: expanded from macro 'uint64_t'
Do it the proper way: introduce uint64/32/16/8 types and use them.
pkg/csource then does s/uint64/uint64_t/ to not clutter code with
additional typedefs.
|
|
|
1. Basic support for arm64 kvm testing.
2. Fix compiler warnings in x86 kvm code.
3. Test all pseudo syz calls in csource.
4. Fix handling of real code in x86.
|